Tuesday, August 30, 2011

Propagate the authenticated user from BPM to ADF using Contextual Events

A common issue that we are facing in nearly all implementations involving creating custom ADF Applications with Oracle Business Process Management Workspace Task Flows is getting the authenticated user (and setting history columns such as created by, created on, etc) from the BPM workspace application to the embedded, as regions, custom ADF Applications.

In normal ADF Applications, to get the authenticated user, using the “ADFContext.getCurrent().getSecurityContext().getUserName()” API will return you with the authenticated user. This is not the case if you created an ADF Application, zipped it into an ADF Library JAR File and used this ADF Application (and more specifically the different Page Flows) as ADF Regions in a Human Task Form.

The above mention method does not work (ADFContext.getCurrent().getSecurityContext().getUserName()) in remote ADF BC, always returning anonymous, as it is the intermediary user between the BPM and ADF Application.

Oracle provides us with an API to get the authenticated BPM user from a human task (that is from the BPM context), using the IWorkflowServiceClient, ITaskQueryService queryService and IWorkflowContext wfContext interfaces.

So the question now is how to pass the username from the BPM Human Task section to the ADF region? Well, of course using Oracle ADF Contextual Events.

So, let’s first start with creating the custom ADF application. This will be a very simple application, where I will create a simple java class with just one method. This method will have only one parameter and will return a string and will be used for handling the contextual event.
I just created an ADF Application, named “DemoADF” and selected “Fusion Web Application (ADF)” from the Application Templates.
Create a new java class in the Model project, specifying Demo as the class name and create a new method as follows:

public String getAuthenticatedUserFromBPM(String username){
     return "Hello " + username;
}
Once you created the getAuthenticatedUserFromBPM method, right-click the Demo.java class and from the context menu select “Create Data Control”. JDeveloper with automatically create for you a data control, exposing all public methods defined in the Demo.java POJO.
Now, create an ADF Task Flow in the ViewController project. Name it DemoTF and ensure that the “Create with Page Fragments” checkbox is selected.
From the components palette, drag and drop a view component onto the bounded task flow and name it Demo.
Double click the Demo view and create the demo fragment, accepting all defaults.
From the Data Controls section, expand the Demo data control and the getAuthenticatedUserFromBPM method and drag and drop the String return type on the Demo.jsff fragment as an input text with label.
On the “Edit Action Binding” window, just click the OK button. You can optionally change the label of the input text to something meaningful, for example “Authenticated User”. The page fragment should resemble as the image below.

Now, we need to package this ADF Application that we have just created into an ADF Jar Library. To do this, right-click the ViewController project, select new from the context menu and in the “New Gallery” window, select “Deployment Profiles“ from the Categories and “ADF Library JAR File” from the items and click OK.
In the “Create Deployment Profile” window, give your deployment profile a meaningfull name (for example, DemoADF, and click OK.
In the “Edit ADF Library JAR Deployment Profile Properties”, just click OK. The same with the “Project Properties” window, just click OK.
To deploy your ADF Application in the ADF JAR Library, you need to right-click the ViewController project and select Deploy > DemoADF

In the “Deploy DemoADF” window, click next and in the Summary screen, make sure to note down the location of the generated jar file (in my case, it’s C:\JDeveloper\mywork\myBlog\DemoADF\ViewController\deploy) and click Finish.
So, we are done with the custom ADF Application, now it’s time to create our SOA Application. So create a new application, name it DemoSOA and from the templates select “SOA Application”.
In the project name screen, you can give your project the same name as your application, that is DemoSOA.
In the “Configure SOA settings” screen, select “Composite with BPEL Process” from the Composite Template section and click Finish.
In the “Create BPEL Process” window, accept all defaults and click OK.
Create a Human Task by dragging the Human Task component form the Component Pallet onto the components swim lane. On the “Create Human Task” window, accept all defaults and click OK. Your composite application should resemble as the image below.
Edit the newly create Human Task and assign the “weblogic” user as the participant of this Human Task.
Edit the BPEL component and drag and drop a human component between the receive (receiveInput) and invoke(callbackClient) activity.
Edit the Human Task component that you have just dropped onto the BPEL Designer and in the “Task Definition” drop down, select “Humantask1” (it’s the human task that you have created in the composite application) and click OK.
Now it’s time to generate the human task form for the human task component. To do this, go to the composite.xml file, and double-click the human task component. From the human task editor, select Create Form > Auto-Generate Task Form.
In the “Create Project” window, give your project a name, such as DemoHT, and click OK.
JDeveloper will automatically create for you the ADF Human Task Form in the project that you have specified in the previous step. Once finished, it should display you with the auto-generated form.
So, now I want to include the Demo.jsff page fragment that I have create from the custom ADF Application in my human task form. How to do this? First, we need to create a File System Connection to the location of the generated ADF JAR Library. You can do this using the Resource Palette. In the “Create File System Connection” window, give your connection a name (for example, DemoADF) and the path to the generated ADF JAR Library. Click “Test Connection” to test your connection and then OK.
From the Resource Palette, expand the IDE Connection, File System and your file system connection name (in my case it’s DemoADF) and you should see the generated ADF JAR Library (DemoADF.jar).
To include and use the contents of this jar file in the human task project, make sure that you have selected from the application navigator the DemoHT project, and from the Resource Paletter, right-click the DemoADF.jar file and select from the context menu “Add to Project”.
In the “Confirm Add ADF Library” window, just click the Add Library button.
Open the Human Task Form (taskDetails.jspx) and from the Component Palette, make sure that you have selected DemoADF.jar from the drop down menu.

Expand the Regions section and drag and drop the DemoTF region from into the panelGroupLayout component that is included into the Contents showDetailHeader component as an ADF Region (you might find it easier to user the structure window).
In the same panelGroupLayout component, drag and drop a button component, above the ADF region. You can optionally change the button text (in my case, I changed it to Get Authenticated User).
We need to create an action for this button so that it will get the authenticated user. To do this, double click the “Get Authenticated User” button and create a new managed bean with a new method as in the image below and click OK.
Replace the contents of the getAuthenticatedUser method with the code below:

String userId = "";

try {

IWorkflowServiceClient wfSvcClient;
ITaskQueryService queryService;
IWorkflowContext wfContext;

// Get username of User Login
String contextStr = ADFWorklistBeanUtil.getWorklistContextId();
wfSvcClient = WorkflowService.getWorkflowServiceClient();
queryService = wfSvcClient.getTaskQueryService();
wfContext = queryService.getWorkflowContext(contextStr);
userId = wfContext.getUser();

} catch (Exception e) {
e.printStackTrace();
}

return userId;


When prompted, please import the following packages:

import oracle.bpel.services.workflow.client.IWorkflowServiceClient;
import oracle.bpel.services.workflow.datacontrol.WorkflowService;
import oracle.bpel.services.workflow.query.ITaskQueryService;
import oracle.bpel.services.workflow.verification.IWorkflowContext;
import oracle.bpel.services.workflow.worklist.adf.ADFWorklistBeanUtil;

Using the above specified method, we can get the authenticated BPM workspace user. Please note that this method ONLY works within the BPM context, that is from a human task form. To propagate the authenticated user returned by the method to the custom ADF Application that we have included onto the human task form, we will have to use ADF Contextual Events.

To do this, select the “Get Authenticated User” button and from the Property Inspector, expand the Behaviour category and click the green plus sign (Add a New Event Entry) in the Published Events section.
Specify GetAuthenticatedUserEvent as the event name in the “Publish Contextual Event” window and select the “Pass Custom Value from” check box.
From the drop down menu, next to the “Pass Custom Value from” check box, select “Managed Bean Method Return” and select the managed bean that you have created (DemoBean) and in the Properties drop down, the method that you have created for getting the authenticated user (authenticatedUser) and click OK.
So now the “Get Authenticated User” button will call the managed bean method that will return the authenticated user and will create an event.

We need to specify who will “listen” for these events created, that is we need to register the ADF region that we have created from the custom ADF Application as a subscriber of these events. To do this, make sure that the human task form is opened (taskDetails1.jspx) and click the bindings tab.
From the bindings page, select the “Contextual Events” tab and from the “Subscribers” tab, click the green plus icon (Add a New Subscription).

In the “Subscribe to Contextual Event” window, click the browse button next to the Event text box.
In the “Select Contextual Event” window, select the GetAuthenticatedUserEvent event and click OK.
From the Publisher drop down, select the taskDetails1PageDef.eventBinding entry and select the browser icon next to the Handler text box. From the “Select Handler” window, select the getAuthenticatedUserFromBPM handler (expand DemoTF1, DemoPageDef) and click OK.
Back in the “Subscribe to Contextual Event” window, ensure that the Parameters tab is selected and click the green plus icon.
In the name, specify outcome and in the value, specify #{payLoad} and click OK.
So now, we are ready to deploy and test if the authenticated user from the BPM workspace is propagated to the custom ADF application that was included in the Human Task form as an ADF region.

First, we need to deploy the DemoSOA project by right-clicking the project and selecting Deploy > DemoSOA
and then we need to deploy the human task form. Please note that you should deploy the project that contains the human task form (DemoHT) using the Application menu, Deploy > DemoHT and NOT by right-clicking the project and selecting deploy.
Once you have successfully deployed both, DemoSOA and DemoHT projects, please go to the Oracle Enterprise Manage (http://localhost:7001/em), locate the newly deployed SOA Composite Application (DemoSOA) and create a new instance by clicking on the test button.
Specify a value in the input field and click the “Test Web Service” button.
This will create a new instance of the DemoSOA composite application. If you remember, this composite consists of a BPEL and a Human Task Component. So it will initiate a bpel process and when it reaches the human task component, it will wait for a human intervention by the weblogic user.

So let’s login to the BPM workspace application (http://localhost:8001/bpm/workspace) to see all pending tasks.
Click on the DemoSOA task and wait for the human task form to load on the bottom half of the screen.

Click the “Get Authenticated User” button and, voila, you should see the authenticated user, in this case weblogic, to get propagated from the BPM workspace to the custom ADF Application that we have developed earlier and included in the human task form as an ADF region.
Download: Propagate the authenticated user from BPM to ADF using Contextual Events