Friday, June 24, 2011

Reusing task UIs in BPM11g

Scenario: Both sales and finance need to approve the incoming order. The payload is the same for both human tasks.



In this lab we generate the ADF UI project for ApprovePart1 and then configure it to be used for ApprovePart2.

1. Create a simple BPM app with 2 human tasks(same payload) in JDev.
2. Auto-generate the task form for the 1st task.
3. Check out the hwtaskflow.xml file in the UI project.



4. Add a second entry -



4.1. We just need to change WorkflowName and TaskDefinitionNamespace

5. Define users for the roles -
5.1. Sales- jcooper, Finance - jstein

6. Deploy and test. I'm using a FileAdapter to Read in orders.

6.1. login to Workspace as jcooper, make some changes to the payload, then Approve




6.2. login as jstein




full doc at
http://download.oracle.com/docs/cd/E17904_01/integration.1111/e10224/bp_designtf.htm#CHDBHHBI

JDev workspace at -


https://docs.google.com/leaf?id=0B7YrnfO7h717ODdjOTczMjItYmRiYi00Yjk2LWE4NTUtNGQ2MDAyNGVjNzE1&hl=en_US&authkey=CNP1-twC

Thursday, June 16, 2011

Pinning tasks to a user in BPM 11g

Scenario:
A BPM process with 1 swimlane - Supervisors(e.g. mtwain, jcooper, rsteven)
An order enters the system and is then processed via 2 human tasks.

Task 2 should be assigned to the supervisor that processed task 1.



Ergo, if jcooper logs in to workspace and claims/approves ApprovePart1, then ApprovePart2 should be assigned to her.

Assign ApprovePart1 to the Supervisor group



Assign ApprovePart2 to whoever approved the previous task i.e. ApprovePart1

The Human Workflow service provides us with the following function -

hwf:getPreviousTaskApprover()

According to the Description –

Get the previous task approver. The signature of this function is hwf:getPreviousTaskApprover(taskId). The arguments are: 1) taskId - The task id of the task Returns an XML element user, in the namespace http://xmlns.oracle.com/bpel/services/IdentityService, that contains the previous approver user id.

So we need to pass it the taskID of ApprovePart1.

We need to get this from the execData structure so return to the data mapping for ApprovePart1 -



You see I have also created a process variable v_taskid of type String.

Now I need to specify this v_taskid value as the parameter to hwf:getPreviousTaskApprover(). My basic solution here is to copy it to one of
the flexfields in my payload. I'm sure there are more elegant ways of doing this.





Now we can return to the definition of the 2nd Task and add in the parameter.



Auto-generate the ADF task forms and deploy.

Test



Login to BPM workspaces as jcooper



Task has been assigned to the group.

Approve




Task2 has been assigned to jcooper

Wednesday, June 15, 2011

Sharing comments between BPM processes

I have a simple scenario -
A BPM process that accepts in an order and then processes it via 2 human tasks - validateCustomer / validateProduct.
I would like to share comments entered in human task 1 with human task 2.

When we define a Human Task in BPEL we can, via the Advanced tab, activate a checkbox to include the task history, comments etc from a previous task.

This functionality is available as follows in BPM 11g.
(Merci JorgeW.)








Deploy and test


Amend the payload, add a comment etc, Approve.






Comment is visible in the next human task.







Tuesday, June 7, 2011

Invoking SOA Composite as part of a global transaction

Scenario: Java client calls SOA Suite composite to process an order as part of a global transaction. The SOA composite is expose as an EJB service. The composite contains 1 BPEL process that itself calls an EJB service to update our Orders DB.

I'm using SCOTT's schema and have already created a datasource on WLS for it.

name: scottDS
jndi: jdbc/scottDS



Step 1. Create DB Table - test
Create table test (id number(2), quantity number(2));

Step 2. Create a stateless session EJB to update this table
create a new application/project in JDev and include a statelsss session EJB 2.1











Step 2.1 - Add the following business method

public String callDB(int id, int quantity) {
Connection connection = null;
DataSource dataSource = null;

try
{
/*
* 1. Create an InitialContext.
* 2. From the initial context, lookup the logical datasource reference
that is in the deployment descriptor.
*/
InitialContext initialcontext = new InitialContext();
dataSource = (DataSource)initialcontext.lookup("jdbc.scottDS");

System.out.println("***** Got Datasource...");
// Check to see if the datasource is valid
if(dataSource==null)
{
System.err.println("*** DataSource retrieved is null, did you add the code?");
throw new ServletException("DataSource retrieved is null");
}

connection = dataSource.getConnection();
Statement stmt = connection.createStatement();
String insert = "insert into test values(" + id + "," + quantity + ")";
System.out.println("INSERT = " + insert);
stmt.executeUpdate(insert);

ResultSet rset = stmt.executeQuery("Select to_char(sysdate) from dual");
while (rset.next())
{
System.out.println("*** Date = " + rset.getString(1));

}
}

catch (Exception e)
{
System.err.println("*** init() Exception, " + e.getMessage());
System.err.println(e);
}
return "Ok";

}

Step 3 - Deploy and view the JNDI tree

specify jndi name before deploying -





Step 4 - Create a new SOA App in Jdeveloper

Create a SOA Composite app
Add the ejb jar from the previous project to the apps classpath.
(We really only need the interface!)










Create the following input xsd





Create a synchronous BPEL process



Create an EJB reference






Wire up



Add the Invoke to the BPEL process



Add the required Assigns, before and after








Step 5 - Expose the composite as an EJB Service








Make InputOrder and OrderType serializable



Deploy and view in JNDI tree

Step 6 Create the EJB client in the SOA project

package demoejbtxsoa;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import java.util.Hashtable;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import processorder.demo_ejb_tx_soa.demo_ejb_tx_soa_app.com.oracle.xmlns.InputOrder;
import processorder.demo_ejb_tx_soa.demo_ejb_tx_soa_app.com.oracle.xmlns.OrderType;
import processorder.demo_ejb_tx_soa.demo_ejb_tx_soa_app.com.oracle.xmlns.ProcessOrder;
import processorder.demo_ejb_tx_soa.demo_ejb_tx_soa_app.com.oracle.xmlns.ProcessResponse;


public class MyEJBClient {
public static void main(String [] args) throws Throwable {
try {
final Context context = getInitialContext();

Proxy proxy = (Proxy)context.lookup("ejb/SOAEJBService");

// preparing the method to be called on the remote EJB
Method method =
ProcessOrder.class.getDeclaredMethod("process", new Class[] {InputOrder.class});
InputOrder id = new InputOrder();
id.setId(23);
id.setCustName("NiallC");
id.setQuantity(7);
OrderType ot = new OrderType();
ot.setComments("Good Customer");
ot.setProduct("Oracle SOA Suite 11g");
ot.setProductGroup("FMW");
ot.setProductKey(new Long(12345));

id.setOrder(ot);

InvocationHandler handler = Proxy.getInvocationHandler(proxy);

ProcessResponse response = (ProcessResponse)handler.invoke(proxy, method, new Object[] { id });


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

private static Context getInitialContext() throws NamingException {
Hashtable env = new Hashtable();
// WebLogic Server 10.x connection details
env.put( Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory" );
env.put(Context.PROVIDER_URL, "t3://127.0.0.1:7001");
env.put(Context.SECURITY_PRINCIPAL, "weblogic");
env.put(Context.SECURITY_CREDENTIALS, "welcome1");

return new InitialContext( env );
}
}

Run the client -

Check the DB




Step 7 JTA enable...

Add the following code to the EJB Client -

import javax.transaction.UserTransaction;

public final static String JTA_USER_XACT = "javax.transaction.UserTransaction";

UserTransaction ut = (UserTransaction)context.lookup(JTA_USER_XACT);
ut.begin();

//ut.rollback();
ut.commit();



Define BPEL to participate in the global TX.

Add this property to BPEL specification in composite.xml






Test

commit()





rollback()