Friday Mar 01, 2013

Webcenter Content (UCM) BPM Integration

This blogs walks through the configurations required in Web Center Content and BPM to invoke a process deployed on the SOA server from the content server workflows. This is a common use case where a BPM or BPEL process has to be invoked from UCM based on an event like document check in.

  1. Prepare the UCM environment for integration with SOA.

This step is only required when the UCM and SOA domains were created separately and the UCM domain is not extended for SOA.

a. Copy the “soa” folder from SOA_ORACLE_HOME to UCM_ORACLE_HOME

For example: Copy D:\Oracle\Middleware\Oracle_SOA1\soa to D:\Oracle\Middleware\Oracle_UCM1\soa

b. Update the class path in setDomainEnv on the UCM server

Windows:

Edit setDomainEnv.cmd in %DOMAIN_HOME%\bin

Add :  set POST_CLASSPATH=%ORACLE_HOME%\soa\modules\oracle.soa.mgmt_11.1.1\soa-infra-mgmt.jar;%POST_CLASSPATH%

UNIX

Edit SetDomainEnv.sh in $DOMAIN_HOME/bin

Add: POST_CLASSPATH="${ORACLE_HOME}/soa/modules/oracle.soa.mgmt_11.1.1/soa-infra-mgmt.jar${CLASSPATHSEP}${POST_CLASSPATH}"

c. Enable Cross Domain Security

Perform the following steps in both UCM and SOA console

1. Login to the Weblogic server console (http://localhost:7001/console/)

2. Select the domain name under Domain Structure. Navigate to the Security Tab

3. Check “Cross Domain Security Enabled”

4. Enter the same credential for both UCM and SOA

d. Restart the servers

2. Enable UCM-BPEL Integration Component

a. Login to content server, navigate to the Admin Server

b. Select component manager for the server on which the component needs to be installed

c. Click on “Advanced Component Manager” and enable the BPELIntegrationComponent

d. Login to the Weblogic Administration console of UCM. Navigate to servers, select the UCM server and click Restart SSL.

3. Configure connection to SOA server

a. Navigate to Administration -> Oracle BPEL Administration -> Connection Configuration

b. From the “Connection Menu” select Add connection

Enter the following credentials

Note: The Provider URL contains the SOA server’s hostname and port. You can test this be running the wlst script in the SOA server and connect to t3://servername:[port]

c. Test the connection. If successful you should see the following screen. Revisit   steps 1 – 3 if there is an error.

4. Process Configuration

a. Navigate to Administration -> Oracle BPEL Administration -> Process Configuration

b. From the process menu select “Add Process”

c. Select the BPM/BPEL process from the drop down

d. Click Save

e. Go to Actions “Upload Payload”

Map the process input fields to the Metadata fields in UCM

   5. Update the SOA composite to enable UCM integration

a. Add the following line to Composite.xml in the SOA/BPM project as shown

<binding.adf serviceName="YourUniqueServiceName" registryName=""/>

 

       6. Configure Workflow in UCM

a. Login to content server

b. Navigate to Administration -> Admin Applets

c. Launch the Workflow Admin Applet

d. Add a new Workflow criteria

 

e. Click on edit criteria workflow. The following screen is where the event trigger condition is set. In this case the workflow will be triggered for Document Type that matches “Document”

f. Edit initiateprocess

              g. Add the users that have access to the workflow and document check in for which the workflow is triggered

h. Add the following lines under Exit conditions

wfGet("conversationId") and 
obIsInstanceClosed("BPEL", wfGet("conversationId"))

 

i. On Events tab click Edit for Entry. Add the line <$wfReleaseDocument()$> before <$endif$> to automatically approve the document. If you do not add this step the document state will be “Pending” and the user has to manually go to Content Management -> Active Workflows -> My Workflow Assignments to approve the document.

<$if not conversationId$>
<$obConfigID="BPEL"$>
<$obInvokeProcess(obConfigID)$>
<$endif$>

7. Login as sysadmin ( the user from step 6) Check in a document of Type Document trigger               condition in step 6) and verify if the BPM/BPEL process is instantiated.

Trouble shooting

  1. Cross domain security – If the cross domain security is configured incorrectly you will see the following error:
vax.xml.ws.WebServiceException: java.lang.SecurityException: [Security:090398]Invalid Subject: principals=[weblogic, Administrators]
  at com.sun.xml.ws.client.dispatch.DispatchImpl.doInvoke(DispatchImpl.java:209)
  1. Enabling UCM System Audit to trace BPEL Integration related errors

Navigate to Administration->System Audit Information and add the BPEL integration component under “Tracing Sections Information”. Update and click “View Server Output” to view the detailed logs.

3. Complex Types as BPEL/BPM process input. With the current release of Webcenter Content (11.1.1.6) UCM does not process the complex type as the process input and the “Update Payload” action will give and error. The work around is to use a simple type as input.

Reference

http://docs.oracle.com/cd/E21764_01/doc.1111/e16759/toc.htm

Custom TaskList Portlet in Oracle BPM 11g

Introduction:

Oracle BPM 11g suite provides the BPM Workspace for end users to view and act upon tasks that are assigned to them. The various User Interfaces available for end users are:

  • The BPM Workspace Application
  • TaskList Portlet in WebCenter Spaces

Customers may need a task list portal as a part of their enterprise application with the tasks displayed in a format that is most appropriate to the business. A Custom Worklist Portlet can be built and consumed from other applications. This article describes solution that uses the Human Task Java APIs to query the BPM engine, Oracle ADF to build the custom portlet and Webcenter spaces to consume the portlet.

The benefit of this approach is that the business can continue to use the enterprise portal to complete the tasks assigned to them in a way that is most suited to the business.

The following sections describe how to build a custom Task List portlet that that can be consumed from Webcenter spaces.

1. Developing an ADF Project to display tasks, details, actions

2. BPM Authentication and Identity Propagation

3. Portletizing the ADF Application

4. Consuming the WSRP in Web Center

1. Developing an ADF Project to display tasks, details, actions

  Create an ADF Application in Jdeveloper with a Java Class in the View Controller project   to query the tasks from the BPM Engine.

a. Connect to the BPM Engine

  BPM Provides the Work List APIs to query and Act upon tasks. The Task services can be  accessed through SOAP connections.

Map properties = new HashMap<CONNECTION_PROPERTY, String>();

properties.put(CONNECTION_PROPERTY.SOAP_END_POINT_ROOT, wsurl);

// SOA server URL, http://[Server Name]:Port"

properties.put(CONNECTION_PROPERTY.SECURITY_POLICY_URI,

"oracle/wss10_saml_token_client_policy");

properties.put(CONNECTION_PROPERTY.MANAGEMENT_POLICY_URI,

"oracle/log_policy");

wfSvcClient =

WorkflowServiceClientFactory.getWorkflowServiceClient(WorkflowServiceClientFactory.SOAP_CLIENT,

properties,

null);

b. Initialize the task attributes to be queried

List queryColumns = new ArrayList();

queryColumns.add("TASKID");

queryColumns.add("TASKNUMBER");

queryColumns.add("TITLE");

queryColumns.add("OUTCOME");

queryColumns.add("STATE");

queryColumns.add("UPDATEDDATE");

queryColumns.add("UPDATEDBY");

queryColumns.add("CATEGORY");

queryColumns.add("HASSUBTASK");

c. Execute the query

querySvc.queryTasks(ctx, queryColumns, optionalInfo, ITaskQueryService.AssignmentFilter.MY_AND_GROUP,null, null,null, 0);

      d. Retrieve the task result set

for (int i = 0; i < tasks.size(); i++) {

Task task = (Task)tasks.get(i);

int taskNumber = task.getSystemAttributes().getTaskNumber();

String title = task.getTitle();

String taskId = task.getSystemAttributes().getTaskId();

String outcome = task.getSystemAttributes().getOutcome();

String state = task.getSystemAttributes().getState();

}

Right Click on the Java Class and create an ADF Data control. Drag and drop the data control on the JSPX to create the task list table.

2. BPM Authentication and Identity Propagation

Identity propagation provides a mechanism to propagate the user token (in this scenario we use the SAML token) when the user logs in to the BPM web service. This method does not required usernames and passwords to be sent as clear text in the code. The SAML token is created when the user logs in for the first time. The SAML token is passed to the BPM webservice to query tasks related to that user.

The following properties can be set for identity propagation:

properties.put(CONNECTION_PROPERTY.SECURITY_POLICY_URI, "oracle/wss10_saml_token_client_policy");

properties.put(CONNECTION_PROPERTY.SOAP_IDENTITY_PROPAGATION , "saml");

3. Portletizing the ADF Application

Portletizing the ADF application creates an Oracle JSF Portlet bridge that exposes the application as a JSR 286 portlet that can be consumed by other applications.

a. Right click on the jspx in the Application Navigator and click Create Portlet entry.

    b. Deploy the Portlet to the WC_Portlet Server

    c. Attaching a policy to the Portlet prodcucer end point

Login to the Enterprise Manager Console, expand Application Deployments. Right click on   the deployed application and select Web services. Select WSRP_V2_Markup_Service from the list of Web Services.

Click Attach/Detach in the policies tab

Select oracle/wss10_saml_token_service_policy and click Attach

Click OK to save the changes

4. Consuming the WSRP in Web Center

a. Registering the Portlet

Login to the Web Center Spaces Server EM Console

Expand Service WebCenter Spaces, right click webcenter and select Settings->Service Configuration


Select Portlet producers -> Add

Enter the following details, test and click OK

b. Consuming the portlet

Add the Portlet in the Webcenter spaces page

Tuesday Mar 13, 2012

BPM 101 Series: Collaborative Process Modeling using MDS, Composer and Jdev

MDS is the metadata repository used by many pieces of the Oracle Fusion Middleware product stack.  There are times when you can combine MDS repositories but for the most part these repositories exist to support their individual pieces of the stack.  In the context of BPM the MDS repository is used as a means to share project artifacts and attributes between the web based composer environmnet and jdeveloper.  Jdeveloper is geared towards the developer while Composer is geared towards process analysts and business users.  It should be stated that the statement of direction for Composer is to grow  the functionality and include much more in terms of functionality and satisfaction of use cases.


That brings us to our need to share between the composer and jdeveloper environments.  a generic slide that has been referenced often is the ability to continuously develop and refine the process models using collabortion between business owners, process analysts, developers and other stakeholders.

social bpm

Using the Composer Space within Webcenter Spaces is one way to collaborate around process models and can include various stakeholders to the process.  The use case referenced here is the sharing of composer models between the web based composer application and jdeveloper.  From within Jdev you can create a connection to MDS and use that connection to push and pull versions of the process model that may get implemented in Jdev.  A simple use case could involve the first cut of a process model that now needs to have a simulation run on it from within Jdev.  A developer would need to create a connection to the MDS repository and pull down the process models and then create simulation artifacts and run simulation against that candidate process model. 

The two main connection resources that need to be created in Jdev are the application server connection and the actual MDS database connection.  Once you wrap the MDS db connection with an mds resource configuration piece you can easily pull down existing projects and snapshots to the local Jdev environment.

       mds db connection
+     mds resource configuration
+     application server configuraton
= ------------------------------------------
      mds_resource_pallette_connection

Below are the steps to create an MDS connection:

1. Select to view the MDS Navigator by clicking on View > MDS Navigator.

2. Click on the 'Configure Connection' icon.


3.  Click on the add symbol to create a new MDS Connection 

4. Specify a name for the new connection and click on the plus sign if you are not yet connected to your WLS application server instance.

5.  Specify a name for your app server connection.

6. Specify the username/password for the WLS server.  In a dev environment this should probably be an administrator on the WLS server. Click next.

7.  Enter your hostname, port and domain name.  Click next.

8. Test your connection. Click next after receiving 'success' for all 9 tests.

9. Click 'Finish'

10.  You are returned to the 'New BPM MDS Connection' panel.  Click the 'add' symbol in the 'SOA MDS' location.

11. A new panel opens.  Name your SOA mds connection and click on the 'add' symbol in the DB Connection section.

12. A new panel opens to create a database connection to your DB instance hosting the MDS schema.  Input connection information and click 'Test' to test the connection.  Once complete click 'Ok'.

13. The new connection should now show up on the 'Create SOA-MDS Connection' panel.  The obpm partition should also show up automatically in the 'Select MDS partition' section.  Test the connection by clicking the 'Test Connection' button. Click 'Ok'.

14. You should now see your create connection name, application server and soa MDS connection name showing in your original BPM MDS Connection panel.  Click the 'Test' button.  Upon success click 'Ok'.

15. Click 'Ok' on your original 'Configure Connection' panel. 

16. Congratulations! You now have Composer projects that you can 'check out', 'export' or otherwise interact with.

Our next BPM 101 series article will go into the use case scenarios for securing and sharing BPM Composer projects between Business Analysts and Developers.




Thursday Feb 09, 2012

Writing Human Task User Interfaces in .Net

This post explores how to use the Human Workflow Services to write a Human Task User Interface using ASP.NET/C# and fully integrate it into the BPM Workspace application.

READ MORE >>

Sunday Dec 18, 2011

Creating a Web Service Proxy in ADF to Consume a Web Service

Abstract

There is more than one way to design your ADF application to consume web services.  One example is to use the ADF wizards to create data controls to access the web service. Another example is to use the ADF wizards to create a proxy to the web service you want to consume. This article is an example of the proxy development process.

Introduction

Oracle has made it extremely easy to quickly develop a body of customizable code that can consume a web service. If there are complexities, they will be involved in the creation of the object that is transported as a SOAP message in the web service transmissions. Otherwise, the wizard gets you to a place very quickly where you can utilize the targeted web service.

There are a large number of public web services you can use to practice creating ADF code to consume the web service.  Just query on the Internet for "public web services".  One site is www.service-repository.com. The web service I have selected for this example is Top Movies.

This development example is completed using JDeveloper 11g Release 1 (11.1.1.4.0).

Overview

The following summarizes what is accomplished in this article.

Create the Application

  • Start the Create Application Wizard
  • Name your application
  • Name your project
  • Configure Java settings

Create the Web Service Proxy

  • Select the Create Web Service Proxy wizard
  • Select the Client Style Select the WSDL
  • Select the WSDL to Java packages mappings
  • Define Port Endpoints
  • Define the Asynchronous Methods
  • Define Oracle Web Service Message Policies
  • Define Message Handlers

Review and Understand the Generated Code

  • Review the Project Structure
  • Review the Generated Code and Cross-References to the WSDL
  • Understanding the binding Element

Consuming the Web Service

  • Create the driver class
  • Review and understand the code 

Using Environments and Migrations

  • Identifying Four methods of migrating between environments
  • Using generated class constructors for migrations

Construction

Create the Application

Start the Create Application Wizard

  • Open up JDeveloper. Click on the Application Menu > New. 

Define the Application Dialog

  • Select Generic Application from the Application Template list.
  • Application Name:  TopMovie
  • Directory: D:\JDev\jdev11114\TopMovie
  • Click Next

Define the Project Dialog

  • Select Web Services from the Project Technologies list.
  • Click on the move button to shuttle the service to the selected side.

The wizard will add an additional step > Project Java Settings.

You will see that 2 technologies were added to the selected window: Java and Web Services.

  • Click Next

Configure Java Settings Dialog

  • Assign a Default Package:  webservices
  • Click Finish

Create the Web Service Proxy

Start the ADF Wizard

  • Right mouse click the Project > WebServices
  • Click New

New Gallery Dialog Box

  • When the New Gallery dialog box appears perform the following steps.
  • Select Current Project Technologies tab
  • Select Business Tier > Web Services in the categories list
  • Select Web Service Proxy in the items list
  • Click OK

Create Web Service Proxy Welcome Dialog Box

  • Click Next 

Select Client Style Dialog Box

  • Select JAX-WS Style (this should be the default)
  • Click Next

Select Web Service Description Dialog Box

  • Enter the location of the WSDL file.
    • This can be a local copy or you may have a URL address to enter which is also acceptable.
  • By default, "Copy WSDL Into Project" is selected. Keep the default setting.
  • Click Next

Specify Default Mapping Options Dialog Box

  • Enter a Package Name:  com.topmovie
  • Enter a Root Package for Generated Types:  com.topmovie.types
  • By default, "Unwrap Wrapped Parameters" is selected.  Keep the default.
  • Click Next

Port Endpoints Dialog Box

  • This is an optional task.  Keep the defaults.
  • Click Next

Asynchronous Methods Dialog Box

  • Accept the default selection "Generate asynchronous methods where specified by the JAX-WS binding"
  • Click Next

Policy Dialog Box

  • Accept all the defaults in this dialog box
  • Click Next

Defined Handlers Dialog Box

  • Accept all the defaults in this dialog box
  • Click Next

Finish Dialog Box

  • Review and Click Finish
  • Save your changes (Control-S)

Review Application Structure

Project View

Numerous class files and supporting files such as the WSDL file are generated. Below is a screenshot of the WebServices Project structure that is generated with the proxy web service wizard.

Code and WSDL Cross-References

An examination of the WSDL file will help understanding the resulting code generation via the wizard. Every time you use this wizard the code generation will be very similar to the structure reviewed below. By studying this structure you can very quickly know where to go to create code anytime you use this wizard. Below is a table of the structure elements cross-referenced to the WSDL location.

Structure Name

WSDL Location

TopMovies.java

wsdl:service name="TopMovies"

You will always have one class file generated for your service with the name "serviceName.java"

TopMoviesSoap.java

wsdl: portType name="TopMoviesSoap"

Also contains the methods used to invoke the web service

TopMoviesSoap12Client.java

wsdl: binding name="TopMoviesSoap12Client"

A template that provides the beginning code to invoke the web service using SOAP 1.2 bindings

TopMoviesSoapClient.java

wsdl:binding name="TopMoviesSoapClient"

A template that provides the beginning code to invoke the web service using SOAP 1.1 bindings (for backward compatibility)

TopMoviesProxy

a container that encapsulates all the class files and supporting files (such as the wsdl) in the defined structure

Types Section

WSDL Location

ArrayOfString.java

s:complexType name="ArrayOfString"

GetMovieAtNumber.java

s:complexType name="GetMovieAtNumber"

GetMovieAtNumberResponse.java

s:complexType name="GetMovieAtNumberResponse "

GetTop10.java

s:element name="GetTop10"

GetTop10Response.java

s:element name="GetTop10Response"

ObjectFactory.java

provides methods to create object instances of the above types

package-info.java

references the package of class files for the types (com.topmovie.types)

Notes about the binding Element in the WSDL structure

The binding element serves two purposes.

1.   It is a link between the abstract elements (<wsdl:types>, <wsdl:message>, <wsdl:operation>, <wsdl:portType>) and the concrete elements (<wsdl:service>, <wsdl:port>, <wsdl:binding>) in the WSDL.

 The attribute "type" is the name of the portType:

<wsdl:binding name="TopMoviesSoap12" type="tns:TopMoviesSoap">

<wsdl:binding name="TopMoviesSoap" type="tns:TopMoviesSoap">

"tns:TopMoviesSoap" is the portType

Notice that there are two bindings.  The binding with name "TopMoviesSoap12" is a SOAP 1.2 binding element. The binding with name "TopMoviesSoap" is a SOAP 1.1 binding. You can find additional information about the two supported formats with a search on the Internet. Many WSDL files provide both bindings for backward compatibility. There are three key differences of SOAP 1.2 over SOAP 1.1:

1) A new namespace: http://schemas.xmlsoap.org/wsdl/soap12/

2) The encodingStyle attribute is now a single URI, instead of a list of URIs

3) There is a new attribute: soapActionRequired, which is used to indicated that the server needs the SOAPAction value.

2.    The binding element provides a container for information such as the protocol and the operation of the Web service. The transport attribute is the protocol.

In the binding element you can identify the operations that can be executed when consuming the web service and these become the methods used within the Java template code with "Client" in the class name (e.g. TopMoviesSoapClient.java).

Consuming the Web Service

Create a Driver

The next step is to create our code that will execute the newly created methods and consume the Top Movies web service.

The job of accomplishing this is made easier by reviewing either the TopMoviesSoapClient.java or TopMoviesSoap12Client.java class files. Each of these serve as a starting point to writing your own code to execute the operations you want to target.

Below is a segment of the TopMoviesSoapClient.java:


public static void main(String [] args)
{
  topMovies = new TopMovies();
  TopMoviesSoap topMoviesSoap = topMovies.getTopMoviesSoap();
  // Add your code to call the desired methods.
}

This can be used to begin our own coding efforts.

Create a New Class File

  • Right mouse click the project and click New on the menu

New Gallery Dialog Box

  • Select Current Project Technologies tab
  • Select General > Java from the Categories list
  • Select Java Class from the Items list
  • Click OK

Create Java Class Dialog Box

Complete the form as follows:

  • Name:  TopMovieWS
  • Package:  webservices
  • Extends:  java.lang.Object
  • Select Main Method check box
  • Click OK

The defaults that should already be selected are: Access Modifiers > public, Other Modifiers > None, Constructors from Superclass and Implement Abstract Methods.

Complete the new Class file to look like the following:



package webservices;

import com.topmovie.TopMovies;
import com.topmovie.TopMoviesSoap;
import com.topmovie.types.ArrayOfString;

import java.io.UnsupportedEncodingException;

import java.net.MalformedURLException;
import java.net.URL;

import java.net.URLDecoder;

import java.util.Iterator;
import java.util.List;

import javax.xml.namespace.QName;

import oracle.xquery.parser.Qname;

public class TopMovieWS {

    private static TopMovies topMovies;

    public TopMovieWS() {
        super();
    }

    public static void main(String[] args) {
        int movieRank = 1;

        // sample from TopMoviesSoapClient.java
        topMovies = new TopMovies();
        QName serviceName = topMovies.getServiceName();
        System.out.println("Service Name: " + serviceName + "\n");
        URL wsdlDocumentLocation = topMovies.getWSDLDocumentLocation();
        System.out.println("WSDL Location: " + wsdlDocumentLocation);
        URLDecoder decoder = new URLDecoder();
        String decodedURL = null;
        try {
            decodedURL = decoder.decode(wsdlDocumentLocation.toString(), "UTF-8");
        } catch (UnsupportedEncodingException e) {
            System.out.println("Error");
        }
        System.out.println("WSDL Location without URL Escape codes: " + decodedURL);

        // consume the web service with SOAP 1.1 binding
        TopMoviesSoap topMoviesSoap = topMovies.getTopMoviesSoap();
        movieRank = 2;
        String movieAtNumber = topMoviesSoap.getMovieAtNumber(movieRank);
        System.out.println("SOAP 1.1 binding - Movie at number " + movieRank + " is " +
                           movieAtNumber + "\n");

        // consume the web service with SOAP 1.2 binding
        TopMoviesSoap topMoviesSoap12Client = topMovies.getTopMoviesSoap12();
        movieAtNumber = topMoviesSoap12Client.getMovieAtNumber(movieRank);
        System.out.println("SOAP 1.2 binding - Movie at number " + movieRank + " is " +
                           movieAtNumber + "\n");

        // also execute the Top 10 Movie operation
        TopMoviesSoap top10MoviesSoap = topMovies.getTopMoviesSoap();
        ArrayOfString top10MoviesArrayOfString = top10MoviesSoap.getTop10();
        List listOfTop10Movies = top10MoviesArrayOfString.getString();
        Iterator iterator = listOfTop10Movies.iterator();
        int iMovieCount = 0;
        while (iterator.hasNext()) {
            String movieDesc = (String)iterator.next();
            iMovieCount++;
            System.out.println(iMovieCount + ". Top 10 Movie: " + movieDesc);
        }
    }
}


Notes About the Code

The auto-complete feature in JDeveloper makes it very easy to inspect your possibilities as you begin typing your code. One of the very nice features is to use the control-space key stroke to use the Declaration Insert operation on your code. They will do the necessary casting and shortcuts your work considerably. All you need to do is modify the variable names to your own coding standards.

A provided enough code to explore the two operations made available and some of the other more interesting methods (e.g. getServiceName(), getWSDLDocumentLocation()).

Sample of Output

Below is a sample of the output produced by the code.

Service Name: {http://www.kirupafx.com}TopMovies
WSDL Location: http://www.kirupafx.com/WebService/TopMovies.asmx/#%7Bhttp%3A%2F%2Fwww.kirupafx.com%7DTopMovies?wsdl
WSDL Location without URL Escape codes: http://www.kirupafx.com/WebService/TopMovies.asmx/#{http://www.kirupafx.com}TopMovies?wsdl
Note that the WSDL location is a combination of the WSDL URL plus the Service Name.
SOAP 1.1 binding - Movie at number 2 is The Godfather: Part II (1974)
SOAP 1.2 binding - Movie at number 2 is The Godfather: Part II (1974)
1. Top 10 Movie: The Godfather (1972)
2. Top 10 Movie: The Shawshank Redemption (1994)
3. Top 10 Movie: The Godfather: Part II (1974)
4. Top 10 Movie: The Lord of the Rings: The Return of the King (2003)
5. Top 10 Movie: Casablanca
6. Top 10 Movie: Schindler's List
7. Top 10 Movie: Shichinin no samurai (1954)
8. Top 10 Movie: Buono, il brutto, il cattivo, Il (1966)
9. Top 10 Movie: Pulp Fiction (1994)
10. Top 10 Movie: Star Wars: Episode V - The Empire Strikes Back (1980)

Environments and Migrations

As developers we will most likely be working in a setting that has the traditional division of environments (e.g. Development, Testing, QA, PreProduction, Production). When this is your setting you will most likely have a separate WSDL file for the web service(s) to be consumed. If this is your case, then you must also prepare your code to make migrations easier.

The code generated by the wizard is very specifically tied to the addresses provided in your WSDL file. Consequently, if you migrate your code from a development environment to a test environment, your code will be calling the development web service by default. This needs to be corrected for the migration process.

There are at least four ways that I know about to accomplish this:

  1. Hard code your changes for each migration
  2. Make references to each environment's WSDL in the connections.xml file
  3. Use the BindingProvider Interface
  4. Use one of the additional constructors provided in the generated Java code where the class file name is the ServiceName.java (our example is TopMovies.java)

For this discussion I will illustrate using one of the additional constructors for the TopMovies.java class file.

TopMovies Class Constructors and Migrations

TopMovies()

This constructor has no parameters. Below is the constructor generated from the wizard. With no parameters, the constructor will use the hard-coded URL that was generated by the wizard from your WSDL file and assign it to "wsdlLocationURL".

  public TopMovies()
  {
    super(wsdlLocationURL,
          new QName("http://www.kirupafx.com", "TopMovies"));
  }

TopMovies(URL wsdlLocation, QName serviceName)

This constructor is expecting two parameters.  Below is the constructor generated from the wizard.

  public TopMovies(URL wsdlLocation, QName serviceName)
  {
    super(wsdlLocation, serviceName);
  }

You must supply the wsdlLocation and the serviceName.  One way you can use this in multiple environments is to store your WSDL location for that corresponding environment in a file (topMovies.properties for example). You write your code to read the targeted properties file and retrieve the designated WSDL location.

Below is my sample code with the new code (in yellow) needed to call the constructor with two parameters. I have hard coded the wsdlLocation but in a multi-environment setting you will use another means to supply the wsdlLocation based upon the current environment.


package webservices;

import com.topmovie.TopMovies;
import com.topmovie.TopMoviesSoap;
import com.topmovie.types.ArrayOfString;

import java.io.UnsupportedEncodingException;

import java.net.MalformedURLException;
import java.net.URL;

import java.net.URLDecoder;

import java.util.Iterator;
import java.util.List;

import javax.xml.namespace.QName;

import oracle.xquery.parser.Qname;

public class TopMovieWS {

    private static TopMovies topMovies;

    public TopMovieWS() {
        super();
    }

    public static void main(String[] args) {
        int movieRank = 1;

        URL topMoviesURL = null;
        try {
            topMoviesURL = new URL("http://www.kirupafx.com/WebService/TopMovies.asmx?wsdl");
        } catch (MalformedURLException e) {
            System.out.println("An error occurred creating the URL: " + e.toString());
        }
        QName qualifiedName = new QName("http://www.kirupafx.com", "TopMovies");
        topMovies = new TopMovies(topMoviesURL, qualifiedName);

        QName serviceName = topMovies.getServiceName();
        System.out.println("Service Name: " + serviceName + "\n");
        URL wsdlDocumentLocation = topMovies.getWSDLDocumentLocation();
        System.out.println("WSDL Location: " + wsdlDocumentLocation);
        URLDecoder decoder = new URLDecoder();
        String decodedURL = null;
        try {
            decodedURL = decoder.decode(wsdlDocumentLocation.toString(), "UTF-8");
        } catch (UnsupportedEncodingException e) {
            System.out.println("Error");
        }
        System.out.println("WSDL Location without URL Escape codes: " + decodedURL);

        // consume the web service with SOAP 1.1 binding
        TopMoviesSoap topMoviesSoap = topMovies.getTopMoviesSoap();
        movieRank = 2;
        String movieAtNumber = topMoviesSoap.getMovieAtNumber(movieRank);
        System.out.println("SOAP 1.1 binding - Movie at number " + movieRank + " is " +
                           movieAtNumber + "\n");

        // consume the web service with SOAP 1.2 binding
        TopMoviesSoap topMoviesSoap12Client = topMovies.getTopMoviesSoap12();
        movieAtNumber = topMoviesSoap12Client.getMovieAtNumber(movieRank);
        System.out.println("SOAP 1.2 binding - Movie at number " + movieRank + " is " +
                           movieAtNumber + "\n");

        // also execute the Top 10 Movie operation
        TopMoviesSoap top10MoviesSoap = topMovies.getTopMoviesSoap();
        ArrayOfString top10MoviesArrayOfString = top10MoviesSoap.getTop10();
        List listOfTop10Movies = top10MoviesArrayOfString.getString();
        Iterator iterator = listOfTop10Movies.iterator();
        int iMovieCount = 0;
        while (iterator.hasNext()) {
            String movieDesc = (String)iterator.next();
            iMovieCount++;
            System.out.println(iMovieCount + ". Top 10 Movie: " + movieDesc);
        }
    }
}

The qualified name logic used in the code above was found by referring to line 67 in TopMovies.java (shown in yellow below).

  public TopMovies()
  {
    super(wsdlLocationURL,
          new QName("http://www.kirupafx.com", "TopMovies"));
  }

The URL is simply the place where the WSDL file is located. If you add this code to your previous TopMovieWS.java you and run it you will notice a slight difference in the display of the wsdlDocumentLocation:

  WSDL Location: http://www.kirupafx.com/WebService/TopMovies.asmx?wsdl
  WSDL Location without URL Escape codes: http://www.kirupafx.com/WebService/TopMovies.asmx?wsdl

The display now reflects the URL assignment you made in your code.

Summary

Once you know how, ADF development to support consuming web services becomes a very simple and straight forward task. The heavy lifting has already been done for you. You only need to provide the parameter values needed to execute your targeted operations and when necessary, make adjustments to allow for code migration from one environment to another.

Additional Resources

Harvard Lecture by Prof. David J. Malan about Web Services, SOAP 1.2, and WSDL 1.1

W3C: From SOAP/1.1 to SOAP Version 1.2 in 9 points

Oracle: Integrating Web Services Into a Fusion Web Application

JDeveloper Tutorial - Developing an ADF Client Using a Web Service Data Control

Oracle: Calling a Web Service from an Application Module

I

Thursday Dec 08, 2011

Source Code Control (SVN) and Team Development with ALBPM and OBPM 10g

Source code control is essential to managing the life-cycle of an application. Plus, it facilitates a predictable deployment practice. This document discusses how to use the SVN code repository to manage ALBPM and OBPM 10g projects. This document concludes with a suggested procedure for allowing development teams to submit their changes to a source code repository, which can then be deployed by system administrators to the BPM engines.

Several BPM consultants have provided input to this document. And, it represents a compilation of their experiences.


[Read More]

Friday Dec 02, 2011

Getting started with tuning your SOA/BPM database using AWR

In order to continue to get good performance from your SOA or BPM 11g server, you will want to periodically check your database – the one you are storing your SOAINFRA schema in – to see if there are any performance issues there.

This article provides a very brief introduction to the use of the Automatic Workload Repository (AWR) in the Oracle Database and what to look for in the reports for your SOA/BPM environment.

READ MORE >>

Thursday Dec 01, 2011

Welcome to the BPM in practice blog!

Hello and welcome to this space on Oracle blogs dedicated to practical implementation of Oracle's BPM Suite and surrounding technologies.  This space is designed to host dozens of guest bloggers from the ranks of Oracle engineers, field solutions consultants, architects and general developers.  The goal is to disseminate practical guidelines and examples from actual implementations or proof of concept exercises.  Our hope is that it not only promotes greater use but better and more defined use of Oracle's BPM Suite by those who have engaged it's powerful capabilities.

As best practices, design patterns and common use cases emerge or are refined they will be discussed in detail here for the good of the BPM community.  Technical deep dives and short hands-on lab-like posts will also be a regular part of the menu so stay tuned and enjoy.

About

This blog was created to share bite sized bits of information picked up in the field by Oracle's team of solution consultants and engineers.Bon appetite! Locations of visitors to this page

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today