Wednesday, 29 October 2014

BPM & SOA Application missing in JDeveloper 12c gallery

A few weeks ago I did a BPM12c Quickstart Installation under Oracle Linux 6. Everything went smoothly, as described in the install guide as well as on many blogs already.
But I found that most of those blogs did an installation under Windows, where I did it under Oracle Linux in Virtualbox.

You would think (as I did) that it shouldn't matter. However, it turns out that in JDeveloper I was missing the 'BPM Application' amongst others in the JDeveloper New Gallery. Very inconvenient. I couldn't find any hints on the big internet. My friend Google wasn't very helpful in this.

But I wouldn't write this blog if I did not solve it. It turns out that with an update I got it solved.

It turns out that I lacked the 'Spring & Oracle Weblogic SCA' extension. Using the Help->Update functionality I downloaded and installed that and after restarting JDeveloper my 'New Gallery' was properly filled.

For those not so familiar with the JDeveloper update mechanism, here a step by step guide:
  1. Choose Help->Update:
  2.  Leave the Update Centers checked as default and click Next:
  3. Check 'Spring & Oracle Weblogic SCA' and click Next:
  4. Click Finish:
  5. Confirm when asked for restarting JDeveloper.

Tuesday, 28 October 2014

Demo User Community in BPM 12c Quickstart

When you want to do demo-ing or perform the BPM12c workshops on a BPM12c QuickStart developers installation you'll need the Oracle BPM Demo User community. You know: with Charles Dickens, John Steinbeck and friends.

How to do so, you can find on the page following this link. You'll need the demo-community scripting that can be found following this link, and then download 'workflow-001-DemoCommunitySeedApp'.

However, besides adapting the build.properties file, there are a few changes to make in the build.xml.


First, find the property declaration for 'wls.home', and change it to:
<property name="wls.home" value="${bea.home}/wlserver"/>
This is needed, since they renamed the folder for the weblogic server in the FMW12c home. Then, after the comment of 'End Default values for params', add the following
  <!-- Import task def for antcontrib functions as if -->
  <property name="ant-contrib.jar" value="${bea.home}/oracle_common/modules/net.sf.antcontrib_1.1.0.0_1-0b3/lib/ant-contrib.jar"/>
  <taskdef resource="net/sf/antcontrib/antlib.xml">
    <classpath>
      <pathelement location="${ant-contrib.jar}"/>
    </classpath>
  </taskdef>
This is because the script lacks a definition for the ant-contrib lib, needed amongst others for the 'if' activities. After this change, it worked for me.

Wednesday, 24 September 2014

JMS Properties in BPM Suite

Lately I needed to transfer messages from OSB to BPM Suite. The setup was that OSB calls a Webservice implemented by a Mediator component that publishes the message on a JMS queue. The webservice request contains a mesage header and a message payload. The payload published as the JMS message-content, but the message header elements were added as custom JMS-properties to the message. How to do that is quite easy and described for instance in this blog.
The JMS Adapter forJMS documentation can be found here, and the particular part about the properties here.
In essence, in the Assign Values part of the Mediator configuration, custom JMS-properties can be referrered to as
$in.property.jca.jms.JMSProperty.custompropertyname


The BPM Process listens to the queue and needed to be adapted to read the JMS-properties. I could not find info about that, but it turns out to be simple: in the ServiceCall activity you have the Service Properties link:
 This will bring up the service properties dialog:
The green-plus and pensil icons can be used to add and edit the service property assignments:

The property name is of the same structure as with the mediator: 'jca.jms.JMSProperty.name'.
The expression must denote an automatically instantiated dataobject of type string. I tried to use a structured business object, but then apparently only the root element is instantiated. On run-time I got errors that the assignment of the JMS-property to the particular element failed. So for each JMS-Property I created a separate Dataobject of type string. And that works perfectly.

Service VersionInfo in OSB

When deploying a SCA project (SOASuite or BPMSuite) from JDeveloper you'll be asked to provide a version number. Often when deploying using a script (ANT or Maven) based deployment to a test, acceptance or production environment, the used deployment-framework may use a release number for the versions of the different composites. Besides the support of different versions of composites to reside side-by-side in SOASuite, this is convenient, because this way you know what version of the composite is deployed on the particular server. Then it is certain that a deployment of a particular version has succeeded and that the particular change that you ment to deliver is or is not in use.

In OSB there's no such thing as side-by-side support of versions and also you can't see what particular version of a OSB  Configuration is deployed.

Since I was asked several thimes by project managers to denote different versions of a particular service in different releases I came up with a very simple solution.

First I defined an xml schema, like the following:
<?xml version="1.0" encoding="UTF-8" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            targetNamespace="http://xmlns.darwin-it.nl/CDM/xsd/V1/SVC/VersionInfo"
            xmlns:ver="http://xmlns.darwin-it.nl/CDM/xsd/V1/SVC/VersionInfo" elementFormDefault="qualified">
  <xsd:element name="VersionInfo" type="ver:versionInfoType">
    <xsd:annotation>
      <xsd:documentation>Version info</xsd:documentation>
    </xsd:annotation>
  </xsd:element>
  <xsd:complexType name="versionInfoType">
    <xsd:sequence>
      <xsd:element name="versionNr" type="xsd:string"/>
      <xsd:element name="versionDate" type="xsd:string"/>
      <xsd:element name="author" type="xsd:string"/>
      <xsd:element name="change" type="xsd:string"/>
      <xsd:element name="svnId" type="xsd:string"/>
    </xsd:sequence>
  </xsd:complexType>
</xsd:schema>
In my setup this xsd is placed in a separate shared xsd-project.
Then in the root of each OSB Service-project I place an xquery file as follows:
xquery version "1.0" encoding "UTF-8";
<ver:VersionInfo xmlns:ver="http://xmlns.darwin-it.nl/CDM/xsd/V1/SVC/VersionInfo">
  <ver:versionNr>1.50.01</ver:versionNr>
  <ver:versionDate>2014-09-17</ver:versionDate>
  <ver:author>M. van den Akker</ver:author>
  <ver:change>ChangeNr - Particular change</ver:change>  
  <ver:svnId>$Id: versie.xq 1520 2014-09-17 10:25:29Z makker $</ver:svnId>  
</ver:VersionInfo>
This xquery is nothing more than an xml-file with an xquery-prolog, a trick you can use to externalise hardcoded properties from your proxy-services. So it doesn't have input and output variable declarations. You could replace certain fields like versionNr with ant-properties to replace it during an ant deployment. In my current setup I change it by hand when commiting the changes in Subversion.

In my proxyservices at the 'entry points' of the services, the start of the first stage in the message flow, I add an assign and an alert. In the Assign the xquery is executed to a versionInfo variable:
Assign with VersionInfo xquery
 Then an alert is added to have the version info shown after the call of the service. This way you can see with what version of the service the request is handled:
Alert of version information
The expression of the alert is:
concat('Version: ',$versionInfo/ver:versionNr,', date: ',$versionInfo/ver:versionDate)
This is where the xsd comes along, because to help you enter this expression, but especially to get this valid (to get the namespace added), you must add the versionInfo element of the xsd as the versionInfo variable. You could also add the namespace manually, but adding the variable structure is more convenient.

This alert is actually optional, but can be usefull when debugging, investigating services and service executions. The xquery resides after deployment on the OSB Server and can be reviewed using the Project Explorer in the Servicebus console. It can be hard for the system-administrator to conclude from script output if a deployment succeeded. The comparison of the versionInfo.xq on the OSB with the version in a release-document that you deliver with your deployment can help him out. OSB commits the deployment as a whole, so the correct version-number in the versionInfo.xq file indicates a successfull deployment.

Another trick you could notice in the screendump is that I use a seperate alert destination for development/debug messages. I found that you can't set the loglevel on an alert. You need to do that on each proxyservice in a compound service configuration. Because I found that very inconvenient, I added a seperate alert destination for debug messages. On acceptance and/or production you can switch of the logging of debug messages on that particular destination.

Monday, 2 June 2014

Message Correlation using JMS

Last year I created a few OSB services with the asynchronous request response message exchange pattern. OSB does not support this out of the box, since OSB is in fact synchronous in nature. Although OSB supports the WS-Addressing namespaces, you need to set the WS-Addressing elements programmatically.

Since OSB is synchronous the request and response flows in the Asynchronous Request/Response pattern are completely seperated implemented from eachother. That means that in the response flow you don't know what request message was responsible for the current response. Even worse: you don't know what client did the request and how to respond to that client in a way you can correlate to the initating instance. Using SOA/BPM Suite as a client, you want to correlate to the requesting process instance.

There are of course several ways to solve this. I choose to use a Universal Distributed Queue for several reasons, where knowledge of JMS and performance were a few. I only need to temporarly store a message against a key. Coherence was not on my CV yet. And a database table requires a database(connection) with the query-overhead, etc.

Unfortunately you can't use the OSB transports or SOASuite JMS adapters to get/browse for a message using a correlation-id in a synchronous way. When you create a proxy service on a jms transport or configure a JMS Adapter for read it will be a polling construction. But it's quite easy to do it in Java, so I created a java-method to get a message based on a CorrelationId.

One thing I did not know back then was that if you put a message on the queue from one OSB Server Node (having a JMS Server) it can't be read from the other node, as such. Messages are stored in the local JMS Server member of the Queue.

I found that you can quite easily reach the local member of a Universal Distributed Queue on a certain JMSServer on Weblogic by prefixing the JNDI name of the queue with the JMSServer separated with the at-sign ('@'):

    String jmsSvrQueueJndi = jmsServer +"@" +queueJndi

The problem now is: "how do you know which JMS Servers are available servicing your queue?"
I solved that by providing a comma seperated string of JMS Server names as a parameter in the Java-Callout in my proxy service. But that left me with a more or less hardcoded string of JMS Server names, that needs to be expanded when a second OSB Server node with a JMSServer instance is added. I figured that I should be able to query that from the WebLogic instance. And of course it can: that's I'm writing the blog.

First you need to get a connection to an MBeanServer in WebLogic. You can create a remote server connection, but since my java class is running on the OSB Server within WebLogic, a JNDI-lookup is better.

I reused a class that I created in the past for doing JNDI lookups of JDBC-Connections for both inside or outside the application server. I'll add it at the end of this blog entry.

To get a MBServer connection you simply get a JNDI Context from the JNDI Provider above do a lookup of the JNDI name "java:comp/env/jmx/runtime":
mbServer = (MBeanServer) jndiContext.lookup("java:comp/env/jmx/runtime");
 The documentation for this can be found here.

From the MBean Server you can get a list of JMS Servers by first instantiating a jmx 'ObjectName' using:
ObjectName queryObjName = new ObjectName("com.bea:Type=JMSServer,*");
Here we're about to ask for all MBeans of type 'JMSServer'.

 I named the JMSServers in my setup each with the same prefix 'OSBJMSServer' and a number like 'OSBJMSServer1', 'OSBJMSServer2'. So I want all the JMS Servers that start with 'OSBJMSServer'. For this I need to provide a jmx query expression. Luckily this is quite simple:
QueryExp queryExp = Query.initialSubString(Query.attr("Name"), Query.value("OSBJMSServer"));
Here I create a query expression that queries on the initial substring on the "Name" attribute of the ObjectName, that equals the query value "OSBJMSServer". I found a blog on the jmx query possibilities here.

Having this in place you only need to perform the query:
Set objNames = mbServer.queryNames(queryObjName, queryExp);
This gets you a set with all the ObjectName objects that matches the query-expression.

Now since I only need the plain name's of JMSServers (not their canonical names) I can add them easily into a List:
  List jmsServers = new Vector();
...
  for (ObjectName objName : objNames) {
   String jmsServerCanonicalName = objName.getCanonicalName();
   String jmsServerName = objName.getKeyProperty("Name");
   jmsServers.add(jmsServerName);
   lgr.debug(methodName, "JmsServerCanonicalName [" + jmsServers.size() + "]: " + jmsServerCanonicalName);
   lgr.debug(methodName, "JmsServerName [" + jmsServers.size() + "]: " + jmsServerName);
  }

For the canonical name there is a getter. For the Name property you need to use the getKeyProperty() method.

WebLogicJms Class

 The complete WeblogicJms class:
package nl.darwin-it.jms;

import java.util.List;
import java.util.Set;
import java.util.Vector;

import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.Query;
import javax.management.QueryExp;
import javax.naming.Context;
import javax.naming.NamingException;

import nl.darwin-it.jndi.JndiContextProvider;
import nl.darwin-it.log.Logger;

/**
 * @author Martien van den Akker, Darwin-IT Professionals Version 1.1 , 2014-06
 *         Class with methods to query JMS artifacts from WeblogicJMS
 */
public class WeblogicJms {
 public static final String MBSVR_JNDI = "java:comp/env/jmx/runtime";
 public static final String JMSSVR_OBJNAME_BASE_QRY = "com.bea:Type=JMSServer,*";
 public static final String JMSSVR_QRY_ATTR = "Name";
 public static final String JSBJMSSVR_NAME_PREFIX = "OSBJMSServer";

 private static final String className = "WeblogicJms";
 private static MBeanServer mbServer = null;
 private static Logger lgr = new Logger(className);

 /**
  * Get a lazy instantiation for the MBServer and cache it.
  * 
  * @return
  * @throws NamingException
  */
 private static MBeanServer getMBServer() throws NamingException {
  if (mbServer == null) {
   final Context jndiContext = JndiContextProvider.getJndiContext();
   mbServer = (MBeanServer) jndiContext.lookup(MBSVR_JNDI);
  }
  return mbServer;
 }

 /**
  * Get a list of JMS Servers belonging to OSB (OracleService Bus)
  * 
  * @return
  * @throws NamingException
  * @throws MalformedObjectNameException
  * @throws NullPointerException
  */
 public static List getOSBJMSServers() throws NamingException, MalformedObjectNameException,
   NullPointerException {
  final String methodName = "getOSBJMSServers";
  lgr.debugStart(methodName);

  List jmsServers = new Vector();

  final MBeanServer mbServer = getMBServer();

  ObjectName queryObjName = new ObjectName(JMSSVR_OBJNAME_BASE_QRY);

  QueryExp queryExp = Query.initialSubString(Query.attr(JMSSVR_QRY_ATTR), Query.value(JSBJMSSVR_NAME_PREFIX));

  Set objNames = mbServer.queryNames(queryObjName, queryExp);
  lgr.debug(methodName, "Found " + objNames.size() + " objects");
  for (ObjectName objName : objNames) {
   String jmsServerCanonicalName = objName.getCanonicalName();
   String jmsServerName = objName.getKeyProperty("Name");
   jmsServers.add(jmsServerName);
   lgr.debug(methodName, "JmsServerCanonicalName [" + jmsServers.size() + "]: " + jmsServerCanonicalName);
   lgr.debug(methodName, "JmsServerName [" + jmsServers.size() + "]: " + jmsServerName);
  }

  lgr.debugEnd(methodName);
  return jmsServers;
 }

 /**
  * Get the list of JSB JMS Servers in XML format serialized to string.
  * 
  * @return
  * @throws MalformedObjectNameException
  * @throws NullPointerException
  * @throws NamingException
  */
 public static String getOSBJMSServersXML() throws MalformedObjectNameException, NullPointerException,
   NamingException {
  final String methodName = "getOMSServersXML";
  lgr.debugStart(methodName);
  StringBuffer jmsServersXMLBuf = new StringBuffer("");
  List jmsServers = getOSBJMSServers();
  for (String jmsServer : jmsServers) {
   jmsServersXMLBuf.append("");
   jmsServersXMLBuf.append(jmsServer);
   jmsServersXMLBuf.append("");
  }

  jmsServersXMLBuf.append("");
  lgr.debugEnd(methodName);

  return jmsServersXMLBuf.toString();

 }

}

JNDI ProviderClass

The JNDI Provider Class:
package nl.darwin-it.jndi;

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

import nl.darwin-it.log.Logger;

/**
 * Class providing and initializing JndiContext.
 * 
 * @author Martien van den Akker
 * @author Darwin IT Professionals
 */
public abstract class JndiContextProvider {
 private static final String className = "JndiContextProvider";
 private static Logger lgr = new Logger(className);
 private static Context jndiContext = null;

 /**
  * Get an Initial Context based on the jndiContextFactory. If
  * jndiContextFactory is null the Initial context is fetched from the J2EE
  * environment. When not in a J2EE environment, the factory class is fetched
  * from the jndi.properties file that should be in the class path.
  * 
  * @return Context
  * @throws NamingException
  */
 private static Context getInitialContext() throws NamingException {
  final String methodName = "getInitialContext";
  lgr.debugStart(methodName);
  Context ctx = new InitialContext();
  lgr.debugEnd(methodName);
  return ctx;
 }

 /**
  * Create a Subcontext within the Initial Context
  * 
  * @param subcontext
  * @throws NamingException
  */
 public static void createSubcontext(String subcontext)
   throws NamingException {
  final String methodName = "createSubcontext";
  lgr.debugStart(methodName);
  lgr.debug(methodName, "Create Subcontext " + subcontext);
  Context ctx = getJndiContext();
  ctx.createSubcontext(subcontext);
  lgr.debugEnd(methodName);
 }

 /**
  * Set jndiContext;
  */
 public static void setJndiContext(Context newJndiContext) {
  jndiContext = newJndiContext;
 }

 /**
  * Get jndiContext
  */
 public static Context getJndiContext() throws NamingException {
  final String methodName = "getJndiContext";
  lgr.debugStart(methodName);
  if (jndiContext == null) {
   lgr.debug(methodName, "Get Initial Context");
   Context ctx = getInitialContext();
   setJndiContext(ctx);
  }
  lgr.debugEnd(methodName);
  return jndiContext;
 }
}

Tuesday, 20 May 2014

OSB Publish: exception with apparent valid XSLT

I ran into this earlier, but today it happened to me again, so apparently a blog would be a good idea.

I use quite some Xslt's in my OSB Project. Merely because I'm more used to XSLT than in XQuery, but also because I've the feeling that it is better suitable in tranforming big XSD. And I found a few minor problems with some XSD's in the XQuery mapper of OEPE.

Anyway, in an XSLT there is a special attribute "exclude-result-prefixes" that allows you to name all the namespace-prefixes that you declare for referencing functions that should be excluded from the resulting xml.
Today (as I did before) I added some prefixes to the attribute. Refreshing my the XSLT folder in OEPE and publishing the project lead me into the following exception:
Conflicts found during publish.
[MyPipelinePair, Response Pipeline, MyOperation-TransformResponse, Replace action] XQuery expression validation failed: com.bea.wli.sb.resources.ResourceException: An error occurred creating the XSLT executor: javax.xml.transform.TransformerException: java.lang.IllegalStateException: The XSLT resource "XSLT MyService/CBS/V1/xslt/MyXSLT" is not in a valid state..
javax.xml.transform.TransformerException: org.xml.sax.SAXParseException; lineNumber: 19; columnNumber: 69; Element type "xsl:variable" must be followed by either attribute specifications, ">" or "/>".
[MyPipelinePair, Response Pipeline, MyOperation-TransformResponse, Replace action] XQuery expression validation failed: com.bea.wli.sb.resources.ResourceException: An error occurred creating the XSLT executor: javax.xml.transform.TransformerException: java.lang.IllegalStateException: The XSLT resource "XSLT MyService/CBS/V1/xslt/MyXSLT" is not in a valid state..

Reading this error, what do you think was wrong with my XSLT?
At first I indeed checked my variable declarations, but I did not touch those. It appeared however that  publisher in OEPE has a limitation in the attribute-length for this attribute.It's one of those errors that does not say what it means at all.

I use the JDeveloper XSLT-mapper, and if you create a new XSLT with it, by default you're provided with several namespace-declarations for xpath-extensions functions for bpel, bpm/bpmn, humanworkflow, ldap, mediator, etc. Most of them you won't use, especially in an OSB project, since (in 11g that is) those functions are not supported by OSB. So you can remove all the unnecessary namespace declarations from the header, making them obsolete for the "exclude-result-prefixes"-attribute. This makes not only the XSLT-header shorter, but it allows you to cleanup the "exclude-result-prefixes" as well.

When the "exclude-result-prefixes"-attribute is shortened enough, the xslt is publishable again.

Wednesday, 7 May 2014

OSB: SplitJoin

Yesterday I had a mail-exchange with a colleague. He was giving an ADF-course, where students complained that in the market little was known about the techniques that they had to work with. Espessially that there's nobody who knows everything. The actual question was about security and SAML. This post is not about that, see my previous one. But I figured that although I did quite a lot with SOA/BPMSuite, OSB and other FMW tools, I do not know everything about Oracle the FMW SOA tools. Today I took a look into the SplitJoin component of OSB. The last days I created a compound service in an OSB Proxy Service, where the different sub-components could be executed in parallel. Having a closer look into the SplitJoin component it actually sort of amazed me. Although you can do a sort of process modelling in a proxyservice, including if-then-else, loops, etc. you can't do parallism. The name of the SplitJoin already suggests that this is intended to solve just that. But the name of the component not nearly suggests what it actually is. To create a split join, you'll have to create a new component:
Then OEPE asks for a binding/operation in a wsdl in your project. The resulting component has an extension that a little better suggests the specifics of the component: '.flow'.

For this post I created a more or less dummy SplitJoin, and added a scope element with a fault-handler:

An experienced SOASuite developer might recognize the structure. For me another hint was the Design Palette:
The SplitJoin is actually a BPEL-Process! So you're not only can do parallel flows, but in the pallete you can see that there are several flow-control constructs available for the process:
  • For Each
  • If
  • Parallel
  • Raise/Reraise Error
  • Repeate Until
  • Scope
  • While
  • Wait
I'm not going to give a BPEL-small-course here. If you google on 'OSB SplitJoin Examples' you'll get several examples of SplitJoin constructions.

I will make several remarks here.
Firstly, given the names and constructions, apparently the supported BPEL version is BPEL 2.0. Secondly, you would think that you could inter-exchange bpel processes from SOASuite-BPEL. However if you implement several Assign Operations, you'll see that the different operations on the messages/variables are done in BEA-extensions. The Log operation is also a BEA-extension to the BPEL-Assign construct.

Furthermore, I found that you can't introspect into the xml-structure of the messages in the expression builders of the assign operations. Like I'm used to in JDeveloper BPEL Designer, or even in the OEPE ProxyService 'MessageFlow'-modeller. This is very inconvenient, because you'll have to edit the xpath-expressions by hand. And I found by trial and error that you couldn't refer to the root-element of the element. If you log a variable, you'll see the root-element. But apparently you'll have to refer to the sub-elements relatively from the variable. like: '$ServiceReply.part1//ns1:subElement'.

Although you can model a complete BPEL process in the SplitJoin, I would be reluctant to use it excessively in OSB. For a complex BPEL process I would use Oracle SOASuite. Not only because the Jdeveloper BPEL Designer is more convenient, the support of the Runtime Engine in EnterpriseManager is much better. In OSB you can't introspect into a running/completed instance as you can in EM.

Lastly, you can't call a SplitJoin/BPEL-flow directly from your ProxyService. You'll need to generate a BusinessService on it. This is actually quite simple: just right click on the SplitJoin -> Oracle Service Bus -> Generate Business Service.

In my case I created a simple wsdl specially for the SplitJoin solution. This one is then called from my proxy-service only for the parallelism part. The request and response messages are based on a separate xsd with the different request and response elements combined. In the ProxyService I already created functionality to aggregate and transform the response-parts to a combined response.
If you open the source of the SplitJoin-BPEL-flow, you'll get:
<?xml version="1.0" encoding="UTF-8"?>
<bpel:process name="SplitJoin"
              targetNamespace="http://www.example.com/flow/CBS/V1/SplitJoin"
              xmlns:tns="http://www.example.com/flow/CBS/V1/SplitJoin"
              xmlns:bpel="http://docs.oasis-open.org/wsbpel/2.0/process/executable"
              xmlns:rescon="http://www.bea.com/alsb/flow/resources/config"
              xmlns:bea="http://www.bea.com/bpel/ui/extensions"
              xmlns:ext="http://www.bea.com/bpel/extensions"
              xmlns:expr="http://www.bea.com/wli/sb/stages/config"
              xmlns:trf="http://www.bea.com/wli/sb/stages/transform/config"
              xmlns:bind="http://xmlns.darwin-it.nl/CDM/wsdl/V1/CBS/Service" 
              bea:name="SplitJoin">
    <bpel:partnerLinks>
        <bpel:partnerLink name="SplitJoin" partnerLinkType="tns:SplitJoin"
                          myRole="SplitJoin">
        </bpel:partnerLink>
    </bpel:partnerLinks>

    <bpel:variables>
        <bpel:variable name="request"
                       messageType="bind:requestMessage">
        </bpel:variable>
        <bpel:variable name="response"
                       messageType="bind:responseMessage">
        </bpel:variable>
    </bpel:variables>

    <bpel:sequence>
        <bpel:receive partnerLink="SplitJoin" operation="serviceOperation" variable="request" createInstance="yes">
            <rescon:receiveInfo>
                <rescon:wsdl ref="CDM/wsdl/V1/CBS/service" binding="bind:Service_pttSOAP11Binding"/>
            </rescon:receiveInfo>
        </bpel:receive>
        <bpel:reply partnerLink="SplitJoin" operation="serviceOperation" variable="response"></bpel:reply>
    </bpel:sequence>
</bpel:process>

The splitJoin is a nice component. But it's unclear to me why a seperate engine is added just to be able to do parallism. And the designer could be improved. But better still: leave it over to the SOASuite BPEL designer and engine. For me personally I'm not sure to what extend I should use this..