2010-12-19

WLI Message Broker versus BPEL PM EDN

WLI is no more.
Well, not exactly, not yet at least, but Oracle made it pretty clear : WLI will have a 9 year support but after that, clients will have to move toward BPEL PM. Knowing that WLI 8.1 is the most widely used version, that changes the whole situation since it will ceased to be supported … next year … (September 2011)
Then, from there, you’ll have two (Oracle) choices : either to migrate your application to WLI 10, or migrate your application to BPEL PM. The choice seems easy to make : “let’s go for WLI 10 !”. But it’s not that simple, since whatever the choice you make, you’ll have to modify or recode from scratch your app and if you go for WLI 10, you still will have to do the same later on, to move towards BPEL PM. To me, migrating to WLI 10 is just a way to slow down what’s unevitable.
With that in mind, what solution would you go for ?
I personally think that going right now toward BPEL PM is a smarter move and that’s why I’m about to demonstrate how to migrate a simple WLI process toward BPEL PM.
Note : I’ll start with a WLI process and then, we’ll see how to “translate” it into a BPEL fashion. I won’t spend much time talking about WLI, because I’m expecting readers to know a bit about it. This blogpost will mainly focus on the BPEL part.

1) Designing a simple WLI process

No fancy stuff : our process will just wait for two messages to arrive, before going further.
It’s a really common stuff WLI is excellent at ! Thanks to its message broker, it adds a very handy layer to handle your messages.
Our messages will be defined according to the following XSD :
<?xml version="1.0"?>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://temp.openuri.org/WLIMigrationToBPEL/sample.xsd"
targetNamespace="http://fr.mbutton.blog/WLIMigrationToBPEL"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:element name="message">
<xs:complexType>
<xs:sequence>
<xs:element name="id" type="xs:string"/>
<xs:element name="label" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

First comes our receiver process :





messageReceiverProcess


And then the “utility” process, we’ll use to send messages.

Note that we could have done a more sophisticated system based on JMS messages & an EventGenerator, but that’s beyond the scope of this article.


messageSenderProcess





Once deployed, as expected, no running process is displayed in the WLI Console :





no_running_process

To do so, we just have to start the processes for testing. First one : the receiver.


startMessageReceiver


Now if we go back in the WLI console, we can now see that this process is running and waiting for some messages to arrive.




processRunningAndWaiting4Msgs





To complete it, we have to send two messages whose IDs are “ID_A” & “ID_B”.


Just call the sender process to do so :





sendMessageA


In the console, we can now see that’s the process has received the event and is no longer waiting for it :



msgAReceived





If we repeat that step with message B, it will complete the process :





messageBReceivedProcessComplete


 Okay, our WLI process works fine, let’s do some more serious business.

2) Converting to BPEL


2.1) BPEL Export

If you’re familiar with WLI, you should have noticed that an interesting option is proposed when you install the product : BPEL Export.


Let’s see what’s that option doing :


exportBPEL


After the export has been done, you should see in the new BpelExport pane :

bpelConversionDone



And some new files in the Application pane :


newBpelFiles


Let’s import the bpel files into JDev :


image


I have to say I’m impressed : I wasn’t expecting that kind of result. What I didn’t know, is that a BPEL process is not orchestrated like a WLI process. So, even if the graphical aspect is pretty much the same, that does not mean anything.


It’s just an empty shell and with three errors stating that some partnerLinks are missing …


image


If you’re not familiar with BPEL, that must be confusing. (and it was for me, when I first worked with BPEL PM !)

2.2) From scratch



The BPEL export is working but only converts the graphical view, which is not exactly what we wanted, especially since the product philosophies are different.


Then, we will start again, from scratch. And the only thing that will remain the same is the XSD we used.

Note : To  be able to develop quickly, I used (and am still using) the VM set up by Oracle which offers a full SOA Suite 11gR1PS2 environment (development & runtime) on RHEL 5. To get the (excellent) VirtualBox image, go to OTN.

2.2.1) Creating the composite

First thing of all, we need to create a new SOA Project. You have to chose the composite template you want to start with.

As we are interested in BPEL, we may choose “Composite With BPEL Process”.


Screenshot-Create SOA Project - Step 2 of 2





As we chose to create a BPEL process, a popup shows up, asking some details about the way we want to create it.


You can change the namespace, the name and the template (“Asynchronous”, “Synchronous” or “One Way”) or define it later. In our case, as there is no need for a return, just pick “One way”.


02-Screenshot-Create BPEL Process


Then, import the XSD in the XSD folder of your SOA project.

2.2.2) Some explanations before the example


That’s where the fun begins. Coming from WLI, I designed something with the “WLI message broker” in mind : I thought my BPEL process would just listen to the desired messages (thanks to filters) and get them.  But that’s not what happened.


In fact, the “WLI message broker” & the EDN (Event Delivery Network) are pretty different. Just think as a JMS topic : when a producer sends a message, all the consumers receive it. That’s the principle of the “WLI message broker” (this has been voluntarily simplified).


With EDN, even if a message, matching the filter you’ve defined in your BPEL process, arrives, you won’t receive it. Why ? Because you have to tell which instance is aimed. Lost ? We will see that in a few lines.


In our simple example, in which two messages are expected before being able to go on, you need to first define a correlationSet for the messages to know where to go. It might sound pretty weird, especially when you’re used to work with classical MOMs but don’t worry, it’s not that bad :)


Another thing you need to know is that for now, in the SOA Suite 11gR1PS2, there’s no way you can define two filters on the same message in a single BPEL process. I mean, you can do some tricks (such as defining several times the same event, with a different name) but I think this has been to be improved. Normally, it should be available next January, in the SOA Suite 11gR1PS3. For now, it’s easier to use a mediator to do the routing & filtering job.


Again, we will see that in our example.


2.2.3 ) Creating the Mediator



A mediator is a component whose role is to filter, transform and route messages within the SOA Suite (as opposed to the OSB, whose role is exactly the same, but outside the SOA Suite). In our example, the mediator is the component that will receive & filter EDN messages, and then route them to the good BPEL process route.


Note : I am sorry, but to limit the number of screenshots, I displayed all the cascading popups on a same screen. Just refer to the numbers to see in what order they’re displayed.


  1. Create a Mediator component by drag ‘n’ dropping a Mediator component (on the right) to the composite (in the middle), this will display window “1”

  2. Click on the “+”, this will bring the window “2”, in which you are asked to create an EDF (Event Definition File)

  3. Click once again on the “+”, to create your message. Windows “3” will show up.

  4. Click on the magnifying glass to chose your event (window “4”)

  5. Once again, click on the magnifying glass and select (in window '”5”) the type associated to the XML message

05-Mediator


As the Mediator is not going to publish messages on the EDN, set the “Run as publisher” option to “No”.


06-runAsPublisherNo


Here’s your Mediator (in purple) in the composite.


07-compositeUpdated


For the mediator to be able to route the messages, we must have three “listening branches” in our BPEL process. One to start the process and the two others to receive the expected messages. To do so, we have to update the WSDL of the BPEL process :

08-wsdlEdition


First, declare the message namespace (the one from your XSD) in the wsdl:definition tag. Then, import the namespace (wsdl:types tag).

After that, just  update the definition of the message you will receive, in the wsdl:message > wsdl:part @element. (according to the prefix you have defined for your imported namespace, it should be yourNamespace:message. And finally, create operations so as to have three different operations (“start'”, “receiveMessageA” & “receiveMessageB”).


09-wsdlEditionDone


Our BPEL process seems ready. Let’s go back to the mediator : that’s not mandatory, but as it is cleaner, I want you to be aware of it : if we do not define a filter rule in the Mediator, it wll listen for each and every message, even if the static routing rules you have defined are not designed to process that message. Don’t worry, I will explain what a static routing rule is.


10b-mediatorCompleteFilter


To define a filter, simply enter the correct expression knowing it allows logic expression (“or” & “and”), so you can do pretty much what you want.


10-mediatorFilter


Now we’ve filtered the messages we want to process in our Mediator, we have to define a proper route for each one (out of three).


11-addStaticRoutingRule


When you create a static routing rule, you have to define if it will invoke a service (partnerLink) or fire an event. In our case, it’s a partnerLink (= a call to a webservice operation, which is one of our BPEL process operation)


12-serviceRoutingRule


Then, we have to select the proper operation, matching the filter we are going to define.

13-chooseOperation

Note : OK, I wanted to show that error because it seems to me that it is a real bug : if you want to update the filter rule, once you’ve already defined, JDev will try to add another filter, which is forbidden. If you take a look at the example below, it tries to add another rule, in addition to the previous version. You may fix that by going in the source and remove the troubling filter.

14-errorWhenUpdatingFilterRule


Anyway, what you have to remember is that once created, the filter needs to be updated directly in the source (composite.xml), if needed. Maybe it’s just the JDev version I worked with, but if you’re using the same Virtualbox appliance as me, you might encounter the same issue.



15-compositeUpdateRule


Once you’ve defined what operation was to be called, we need to define what the trigger will be (= define a filter). In our example, I want the “start” branch of my BPEL process to be called when a message, whose ID is ‘START’, is received (pretty logical, huh ?). Just click on the filter icon and you will see a popup like that :


16A-START


Repeat the step for each message / BPEL branch to be called. Note that I used the mode “Parallel'” rather than “Sequential”. With three rules, it doesn’t really matter. But if you have more than twenty, it could lead to some performance issues : in “Parallel”, one thread is created to execute the checking (one rule = one thread), whereas in “Sequential”, only one thread will perform each rule, one after the other.


16B-AllDone


Once you are done, note that all the components are now wired in the composite graphical view.


17-compositeUpdated


Now, we will add another process, used to push messages on the EDN.

Define a new BPEL process. (“One-way” is the right choice for that process since we are not expecting any message in return).


18-messageSender


Simply add an “Invoke” activity by drag ‘n’ dropping it just after the activity “receiveInput”. An “Invoke” activity means that the process is making a call, whereas a “Receive” activity means that the process is being called.

In our example, the Invoke activity will publish a message (Event) on the EDN. Just switch “PartnerLink” to “Event” in the dropdown “Interaction Type”.

Look for the event “myMessage” and then, define a variable associated to it (even if we will not use it). Be sure to update the WSDL in order to have the proper message used. (that means you’ll have to declare and import the correct namespace, like you did for the first BPEL process).


19-invoke


From a composite point-of-view, here is the the newly created process, which will help us to send messages over the EDN.


20-composite


Now, we have the impression that everything is set up : a process which will receive messages (through its mediator) and another which will publish messages. But if you remember what I wrote earlier, you should know that this won’t be enough for this example to work : a correlationSet is missing …

For your messages to be able to reach your instance, you have to define something that bind them together. That’s the role of the correlationSet : you define a common property, whose value is going to be the same.

For instance, on my message, I’ll define a correlationSet on the property “label”. That way, all the messages whose “label” property is the same will be directed to the same BPEL instance(s).


Note : several BPEL instances may have the same correlationSet.

  1. On the “Receive” node, look for the “Correlations” tab, click on the starred white sheet to create a new correlationSet

  2. Chose a name, type & alias

  3. Chose on what message property your correlationSet will rely on


21-CorrelationSet


Add a flow element (means its branches will be processed in parallel) and define two branches. In each branch, add a receive activity. Here’s what our BPEL Process should look like.


22-Receive


Now, just wire the newly created receive operations to the messageClient.


23-LinkReceiveA


When the wire is drawn, a popup will ask some details about that link. Chose the webservice operation you want your receive activity to be bound to.


24-ChooseOperationA


Create a variable that will receive the payload coming from the webservice operation call.


25-ReceiveAVariable


And then, chose the correlationSet you created before. That’s how you define a link between the three messages. Repeat that step for the second operation.

26-setCorrelationSet


Here’s what our final BPEL Process looks like :

27-BpelProcessComplete


Now we’re ready to have it running.

Start your server and deploy your BPEL project.


28-Deploy


Don’t forget to define the version you want to use for your SOA Project


29-DeployVersion


In the SOA Pane, you should see seomething like

Buildfile: /oracle/jdevhome/jdeveloper/bin/ant-sca-compile.xml
scac:
[scac] Validating composite "/home/oracle/jdeveloper/mywork/Migration/BPELFromWLI/composite.xml"
[scac] Setting BPELC option 'classpath' to /oracle/jdevhome/jdeveloper/jdev/extensions/oracle.sca.modeler.jar:/oracle/jdevhome/jdeveloper/soa/modules/oracle.soa.fabric_11.1.1/fabric-runtime.jar:/oracle/jdevhome/jdeveloper/soa/modules/oracle.soa.mgmt_11.1.1/soa-infra-mgmt.jar:/oracle/jdevhome/oracle_common/modules/oracle.fabriccommon_11.1.1/fabric-common.jar:/oracle/jdevhome/jdeveloper/soa/modules/oracle.soa.bpel_11.1.1/orabpel.jar:/oracle/jdevhome/jdeveloper/soa/modules/oracle.soa.mediator_11.1.1/mediator_client.jar:/oracle/jdevhome/oracle_common/modules/oracle.mds_11.1.1/mdsrt.jar::/home/oracle/jdeveloper/mywork/Migration/BPELFromWLI/SCA-INF/classes
[scac] Setting BPELC option 'classpath' to /oracle/jdevhome/jdeveloper/jdev/extensions/oracle.sca.modeler.jar:/oracle/jdevhome/jdeveloper/soa/modules/oracle.soa.fabric_11.1.1/fabric-runtime.jar:/oracle/jdevhome/jdeveloper/soa/modules/oracle.soa.mgmt_11.1.1/soa-infra-mgmt.jar:/oracle/jdevhome/oracle_common/modules/oracle.fabriccommon_11.1.1/fabric-common.jar:/oracle/jdevhome/jdeveloper/soa/modules/oracle.soa.bpel_11.1.1/orabpel.jar:/oracle/jdevhome/jdeveloper/soa/modules/oracle.soa.mediator_11.1.1/mediator_client.jar:/oracle/jdevhome/oracle_common/modules/oracle.mds_11.1.1/mdsrt.jar::/home/oracle/jdeveloper/mywork/Migration/BPELFromWLI/SCA-INF/classes
[scac] WARNING: in Router.mplan: Case "MessageReceiver.messagereceiver_client.start" doesnt have any payload transformation Please make sure source and target message part name are same and of same type. Otherwise, target reference may fail to execute with error message like "Input sourcelike Null" or "Part not found"
[scac] WARNING: in Router.mplan: Case "MessageReceiver.messagereceiver_client.receiveMessageB" doesnt have any payload transformation Please make sure source and target message part name are same and of same type. Otherwise, target reference may fail to execute with error message like "Input sourcelike Null" or "Part not found"
[scac] WARNING: in Router.mplan: Case "MessageReceiver.messagereceiver_client.receiveMessageA" doesnt have any payload transformation Please make sure source and target message part name are same and of same type. Otherwise, target reference may fail to execute with error message like "Input sourcelike Null" or "Part not found"
BUILD SUCCESSFUL
Total time: 6 seconds

And in the Compiler Pane, no errors (but maybe a few warnings).

2.2.4) Running the example

Now we’ve compiled & deployed our BPEL processes, it’s time to use them.


30-EM

First thing of all, we will test the process that sends messages over the EDN and send a start message.

To test a BPEL process, just click on the Test button, just like on the picture below.

31-Test


Choose the process that sends messages and on the screen, chose to the XML view, that would normally display an empty message. Just complete the payload with the correct values, that is to say ‘START’ in the id field and whatever you want in the label field. Remember that, as we based our correlationSet on that label field, you will have to keep the same value if you want your messages to be routed to the correct instance.


32-XMLView

If everything went well, click on the link that allows you to see the details of the call. You should normally see the steps shown below, with the call of the “MessageSender”, the routing by the “Router” mediator and then finally, the process “MessageReceiver” which is running.


33-ProcessStarted


If you click on that last step, you will see that the start branch has been called and that the process is now waiting for two branches (highlighted in yellow) to be called.

34-MessagesPending


Just for some testing purposes, if you try to trigger the very same message, you’ll end up with a faulted process, whose failure reason is a conflicting receive. Which is absolutely normal, since we based our correlationSet on a field whose value is the same as the first we used to trigger the first process. If you want another process to start, change the value of the “label” field.


35-SecondCall


Now, if we send a message whose id is one the ids expected (and of course, with the same label), you should see something like the picture below, with a “mid process receive” activity.


36-MidProcessReceive


If we take a closer look to that running instance, we now see that the first branch is no longer waiting to be called (= for a message to come).


37-IDA_Received


Now, we send the third and last message, whose id is “ID_B” and we can now see that a second “mid process receive” is visible and that all the states of the steps are at “Completed”.


38-BothMsgReceived


Let’s have a look at the general BPEL instance, and now, we can see that everything has been received and that the instance is now completed.


39-ProcessCompleted


Well, that’s it. I hope my explanation was clear enough. Else, feel free to ask and I’ll try to answer as accurately and as fast as possible.

In the meantime, if you were to wonder about Oracle products, about the way to migrate WLI projects toward BPEL PM, I invite you to contact Simone Geib (SOA Suite Product Manager) and she’ll try to answer your questions. (Her email address is first_name.last_name@oracle.com)

Ok, to be sure to understand how everything works here, don’t hesitate to play with correlationSets, multiple instance and so on. Once again, you’ve got a perfect VirtualBox appliance to play with !

Enjoy :)



2 comments:

Anonymous said...
This comment has been removed by a blog administrator.
Anonymous said...
This comment has been removed by a blog administrator.