Saturday, December 18, 2010

Canceling a running composite in SOA Suite 11g

Simple scenario -

An order XYZ is being processed in a composite that includes the following
components-
File Adapter(read) --> Mediator --> BPEL --> human workflow --> DB
Adapter(write).

In the meantime the customer cancels the order XYZ by calling the call center.
The order db is updated accordingly via the call center app, but now we
need to kill the soa composite instance that's still running.

I could create a composite sensor based on the unique Order ID.
The info is then written to the SOA_INFRA table composite_sensor_value

From this table I can then get the COMPOSITE_INSTANCE_ID value.
I can save this pair - Order ID and COMPOSITE_INSTANCE_ID to the DB.

Now we know which composite is processing Order ID XYZ.

Regarding cancelling the running process -

We can use the COMPOSITE_INSTANCE_ID to query
the cube_instance table.

e.g. select * from cube_instance where cmpst_id = xxx;

I can then do the usual purge.

But how should we model this from an architectural perspective?
My OCS colleague, Markus, suggested a generic composite that takes care of
the "cancellation" of all running SOA composite instances.

So we could have the user cancellation call to the call center triggering an event that our generic composite processes.

So essentially we have the following -

1. Create an event via the EDN-Framework.
1.1. The payload contains the info required (orderID, CompositeID etc.) to
find the appropriate running instance.

2. Event is picked up by a Mediator which routes on to a BPEL process that does
the actual purging.

Example to follow after the holidays.

Wednesday, December 8, 2010

Human Workflow API Part 3 - ITaskQueryService.AssignmentFilter

leading on from the previous post...

We have a couple of roles in HW.
For example, the user that actually does the "approving" e.g. jverne.

Also we have the process owner e.g. cdickens.

We can leverage the Java API to process the HW tasks from both perspectives.

We just need to set the ITaskQueryService.AssignmentFilter appropriately.




//Query a list of tasks assigned to jcooper
List tasks = querySvc.queryTasks(ctx,
queryColumns,
optionalInfo, // Payload
ITaskQueryService.AssignmentFilter.OWNER,
null, //No keywords
null, //No custom predicate
null, //No special ordering
0, //Do not page the query result
0);

Friday, November 26, 2010

Human Workflow Java API Part 2

Continuing on from the previous post...

The payload I tested with is as follows -



Now I want to access the custName value in the payload.

Here's the code snippet(thanks to my colleaue Mireille) -

Element el= task.getPayloadAsElement();
String custName = null;
custName = getElementValue(el, "custName");
if(el != null){
System.out.println("Payload customer name = " + custName);


}
else{
System.out.println("Payload is null");
}

public static String getElementValue(Element pElement, String pElementName){
String value=null;
NodeList myNodeList = pElement.getElementsByTagName(pElementName);
Element myElement = (Element)myNodeList.item(0);
NodeList myChildNodeList = myElement.getChildNodes();
for (int i=0; i {
value = ((Node)myChildNodeList.item( i )).getNodeValue().trim();
if( value.equals("") value.equals("\r") ){
continue;
}
else{
break;
}
}
return value;
}

Testing...




The complete Java class is as follows -

package com.niall.hwclient;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import java.util.Map;

import oracle.bpel.services.workflow.client.IWorkflowServiceClient;
import oracle.bpel.services.workflow.client.IWorkflowServiceClientConstants;
import oracle.bpel.services.workflow.client.WorkflowServiceClientFactory;
import oracle.bpel.services.workflow.query.ITaskQueryService;
import oracle.bpel.services.workflow.task.ITaskService;
import oracle.bpel.services.workflow.task.model.Task;
import oracle.bpel.services.workflow.verification.IWorkflowContext;

import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;


public class HwTask {
public HwTask() {
super();
}

public String getTaskdetails(String user){

Map properties = new HashMap();
properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.EJB_PROVIDER_URL, "t3://localhost:8001");
properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.EJB_SECURITY_CREDENTIALS, "welcome1");
properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.EJB_SECURITY_PRINCIPAL, "weblogic");

try
{
//Create JAVA WorflowServiceClient
IWorkflowServiceClient wfSvcClient =
WorkflowServiceClientFactory.getWorkflowServiceClient(WorkflowServiceClientFactory.REMOTE_CLIENT, properties, null);

//Get the task query service
ITaskQueryService querySvc = wfSvcClient.getTaskQueryService();
//Login as jcooper
IWorkflowContext ctx = querySvc.authenticate("cdoyle","welcome1".toCharArray(),null);
//Set up list of columns to query
List queryColumns = new ArrayList();
queryColumns.add("TASKID");
queryColumns.add("TASKNUMBER");
queryColumns.add("TITLE");
queryColumns.add("OUTCOME");

// also get the payload
List optionalInfo = new ArrayList();
optionalInfo.add(ITaskQueryService.OptionalInfo.PAYLOAD);
//
//Query a list of tasks assigned to jcooper
List tasks = querySvc.queryTasks(ctx,
queryColumns,
optionalInfo, // Payload
ITaskQueryService.AssignmentFilter.MY,
null, //No keywords
null, //No custom predicate
null, //No special ordering
0, //Do not page the query result
0);
//Get the task service
ITaskService taskSvc = wfSvcClient.getTaskService();
//Loop over the tasks, outputting task information, and approving any
//tasks whose outcome has not been set...

for(int i = 0 ; i < tasks.size() ; i ++)
{
System.out.println("In task loop...");
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();

// Get the payload
Element el= task.getPayloadAsElement();
String custName = null;
custName = getElementValue(el, "custName");
if(el != null){
System.out.println("Payload customer name = " + custName);


}
else{
System.out.println("Payload is null");
}



/* if(outcome == null)
{
outcome = "APPROVED";
taskSvc.updateTaskOutcome(ctx,taskId,outcome);
}*/

System.out.println("Task #"+taskNumber+" ("+title+") is "+outcome);
}
}
catch (Exception e)
{
//Handle any exceptions raised here...
System.out.println("Caught workflow exception: "+e.getMessage());
}

return "done";
}
public static String getElementValue(Element pElement, String pElementName){
String value=null;
NodeList myNodeList = pElement.getElementsByTagName(pElementName);
Element myElement = (Element)myNodeList.item(0);
NodeList myChildNodeList = myElement.getChildNodes();
for (int i=0; i {
value = ((Node)myChildNodeList.item( i )).getNodeValue().trim();
if( value.equals("") value.equals("\r") ){
continue;
}
else{
break;
}
}
return value;
}
}

Monday, November 22, 2010

BPM Signal Events and EDN Part 2

Now we will create another Business Event at the composite level – OrderProcessedEvent







The new event surfaces in the Business Catalogue.



Return to the BPM Design editor and set the implementation type of the End Event to Signal.





Now we have no errors in our process.

Create the required process variables so that it is runnable.

Add a new Business Object of type Order.



Add a Process Data Object variable of this type



Set the Data Associations for Start and End




Ok, so now as soon as the order has been processed, a Mediator component will pick this up and write the order to a file. Here we will leverage the File Adapter(Write) we created earlier.



We then wire this to the File Adapter(Write)
Don't forget to create the required transformation in the Mediator.



Deploy and Test

Sample input file to be dropped into the /in directory



Result

BPM Signal Events and Oracle EDN

Simple scenario –

A new order arrives via file and kicks off the BPM Order process.
This can be easily modelled in Oracle SOA Suite 11g.
Our order has the following xsd –



Steps

Create a couple of directories on the file system




Create a BPM Application in JDeveloper



Go to the Composite view



Create a file adapter – (Read) based on the XSD – pointing to /in directory
Create a file adapter – (Write) based on the XSD – pointing to /out directory



Add a Mediator to pick up the read order



Add a routing rule to publish an event



Create the event definition





Switch to the BPM Project view

The event has been automatically added to the Business catalogue.



Right-mouse click on the Start icon and change the type to Signal






No we have EDN kicking off the BPM process via a Signal event.
I'll flesh this process out in the next post!

Friday, November 19, 2010

JCAPS - SOA Suite 11g Interoperability/Migration

Greetings from South Africa!

Just spent a couple of days around Capetown and am now up in Hermanus whale watching.
Certainly beats the November cold of southern Germany!

Regarding the above, apart from standard integration via web services and JMS, tighter integration can be achieved using the SOA Suite 11g Spring component described in the last post. Essentially we can wrap the JCAPS JCD as a Spring component and leverage it's functionality directly in our composite. Please ping me if you're interested in more details.

Monday, October 25, 2010

Spring & BPEL extension functions in SOA Suite 11g PS2

Last December I uploaded a doc detailing a simple Spring lab - here now is an example based on Patchset 2.

To begin with you may need to download the JDev Spring extension (Menu --> Help --> Check for Updates).

An excellent intro to Spring is the official doc at http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/pdf/spring-framework-reference.pdf

Ok, so now back to our simple example -

In this example we will have a Java class that does some simple SOA Composite logging for us. We will leverage the BPEL XPath extension functions as detailed in Appendix B of the SOA Suite Developers Guide - available at http://download.oracle.com/docs/cd/E14571_01/integration.1111/e10224/bp_appx_functs.htm#CHDECDHG

This is based on an excellent example from Clemens Utschig - so vielen Dank!

I'm going to use the following -

ora:getDomainId()
ora:getECID()

ora:getCompositeName()
ora:getCompositeInstanceId()

ora:getComponentName()
ora:getComponentInstanceId()

ora:getElement()

Steps -

1. Create the Java Interface for the logger
2. Create the Java class that implements the interface
3. Spring-enable
4. Expose the Spring component as an SCA Service
5. Create a SOA Composite with a BPEL process
6. Invoke the Spring component from BPEL
7. Deploy and Test
1. Create the Java Interface for the logger
1.1. Create a new generic application in JDev - LoggingWithSpringApp
1.2. Name the project - LoggingWithSpring
1.3. Create the Java interface - ILogger - package name my.company.com




1.4. Add a log() method.


public void log(String domainID, String ecid, String compositeName,
String compositeInstanceID,String componentName,
String componentInstanceID, String elem );
}

2. Create the Java class that implements the interface




2.1. Implement the log() method.

public void log(String domainID, String ecid, String compositeName,
String compositeInstanceID, String componentName,
String componentInstanceID, String elem) {

StringBuffer msg = new StringBuffer();
msg.append("[Domain ID] ").append(domainID).append("[ECID]").append(ecid).
append("[Composite Name]").append(compositeName).append("[Composite Instance ID]").
append(componentInstanceID).append("[Component Name]").append(componentName).
append("[Component Instance ID]").append(componentInstanceID).append("[Input Element]").
append(elem);
System.out.println(msg.toString());
}

3. Spring-enable

3.1. Create a new Spring Bean configuration in the project



3.2. call it logger-context.xml

3.3. Select Spring 2.5 Core in the component palette




3.4. Drag a bean from the Spring 2.5 Core component palette

3.5. set name and class as below




4. Expose the Spring component as an SCA Service

4.1. Change the palette to Weblogic SCA and drag & drop a Service




4.2. Set as follows -




5. Create a SOA Composite with a BPEL process

5.1. File --> New --> SOA Composite --> Composite with BPEL process
5.2. call the composite - LoggingWithSpringComposite
5.3. Create the BPEL process




5.4. Go to the Composite Editor view and drop a Spring Context component.



5.5. Make the Java class and interface.



5.6. Wire together.





6. Invoke the Spring component from BPEL

6.1. add an Invoke activity to the BPEL process to call the logger




6.2. Add an Assign activity to set the call arguments
6.3. See below for the 7 assigns





6.4. add an Assign after the Invoke to set input to output



7. Deploy and Test

7.1. Deploy ot SOA Suite and test via EM.



View results in server log

Tuesday, October 12, 2010

Bruce Silver on Oracle BPM 11g

Makes for very interesting reading -

http://www.oracle.com/us/corporate/analystreports/infrastructure/bruce-silver-bpm-suite-11g-083869.pdf

To quote from the report -
"Oracle not only is first out of the gate with BPMN 2.0 support, but sets the competitive bar extremely high for a long time to come."

Cheers Bruce!

Leveraging BPM Project templates

BPM project templates are stored in MDS. You already have a database based MDS
installed with SOA Suite (DEV_MDS).

In the following simple scenario we will leverage this to work with project templates. We will create a template in JDev and consume it in Process Composer.

Step 1. - Create a Project template in JDev

One thing all BPM projects need are Services.
So this is what our template could contain. So lets begin by creating a new project in JDeveloper of type BPM Template.






Add content to the Business Catalog - currently Business Objects, Human Tasks, Services and Rules etc. are visible in the context of Process Composer.

Create a DB based MDS connection (DEV_MDS schema)

Right click on the project and select --> Publish to BPM MDS




View the MDS repository after publishing.



Now open the web-based Process composer e.g. http://localhost:8001/bpm/composer
and create a new project based on a template.