2011-06-16

How to connect BPEL Process Manager on a JMS topic as a durable subscriber ?

On my project, I use BPEL PM as the central BPM. It uses JMS messages to integrate external information. And, at a particular moment of the day, my process is launching some tasks and I want it to freeze the reception of external messages, to be sure my data is not changed during the computing process.
When I was using WLI, I took a closer look at some of the BEA stuff to know how they were passivating / resuming EventGenerators through the WLI console. It gave me a working solution (still in production), but it wasn’t official.

Then, it hit me : isn’t the exact purpose of JMS topics & durable subscribers functionality ? Of course it is, but as the project was up & running in production, I didn’t get the authorization to change the existing system : we do not change something that’s working.
Alright, I can understand. I then kept that idea in my mind … till we had to break up our architecture to replace WLI by BPEL PM. Then, I thought it was the perfect occasion. Then I decided to go for that solution I’ve been thinking about over six months !

My stuff is now working and I thought it could help some people who need the same thing. Here’s what we are going to do in this article :
  1. Design a simple process that listens through a mediator to the publishing of a message on the EDN
  2. Test that process with the Enterprise Manager
  3. Configure the JCA Adapter in charge of JMS and plug our process to a JMS topic
  4. Configure the JCA Adapter to make BPEL PM a durable subscriber
  5. Test how to deconnect BPEL PM from the topic
  6. Test that JMS messages are kept when BPEL PM is offline, and that they are correctly sent when BPEL PM comes back online.
All the example I will be describing is going to be made thanks to the SOA Suite 11gR1PS2 Virtual Box appliance.

Design time

BPEL Process 1 & its Mediator : EDN message consumer

That BPEL process is very simple : the message subscription is going to be performed by a mediator, which will, on the reception of a message, call the BPEL process.
I will spare you the designing of such a process.
Just know the message I’m using is following that schema definition (the same I used in that blogpost) :

<?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>
I’ve updated the WSDL process to use the message as an input, declared a correlation set and defined a static routing rule to route any incoming message to my BPEL process.
And in the end, the composite will look like that :

image

BPEL Process 2 : EDN message sender

A simple BPEL Process whose role is to send (through an Invoke activity) a message over the EDN.
The composite will look like that :

image

Once everything’s ready, just deploy it to the WLS server.

First test

As our process is not yet wired to the real world (that is to say JMS), I’ll use the first BPEL process to push messages over the EDN. That way, it will allow me to see if my BPEL process is correctly triggered.
Thanks to the Enterprise Manager, I’ll use the test interface on my EDNSender BPEL process to trigger message.

image

Note : I could have used the embedded message functionality (right click on “soa-infra (AdminServer)" >
Business Events”, but I prefer my own tool :)

image

But okay, just send a message (one way or another) and see what happens :

image

And when I click on the MessageEater instance, I see that the EDN message has been properly consumed :

image

Wiring JMS

 

Creating the JMS basis

First thing of all, I will create a JMS server configured with a store (to persist messages, mandatory for storing messages when a durable subscriber is offline). Then I define a module containing a topic whose name is BlogTopic and JNDI name is “fr/mbutton/blog/jms/topic”. and a connectionFactory, whose JNDI name is “fr/mbutton/blog/jms/connectionFactory” (pretty original, isn’t it ?).


Name

JNDI Name

BlogTopic

fr/mbutton/blog/jms/topic

BlogConnectionFactory

fr/mbutton/blog/jms/connectionFactory

In the end, I’ve got something like that :

image

Just note that I chose to have a XA enabled connection factory.

Durable subscriber configuration

Now all the configuration has been made, let’s turn back into JDev and our BPEL processes.
To make the link between the JMS part and my BPEL process, I also need to create a JMS Adapter, which will be in charge of receiving JMS messages and send it over the EDN. That adapter can’t exist by itself : it has to be used in a BPEL process. In my example, mine is called “JMSBridge”.
In the component palette, click the section “BPEL Services” and drag and drop a “JMS Adapter” in the right swimlane.

image

A wizard will start. First page is just a welcome screen. The 2nd will prompt for a service name, the 3rd will ask what kind of provider you want, chose “Oracle WebLogic JMS”

image

On the 4th screen, chose a connection to a server (chose “localhost-wls”). On the 5th screen, leave it as it is (“Define from schema…”) and click next.

image

On screen 6, chose the operation “Consume Message” and click “Next”. Screen 7 is where things become a bit trickier.

image

You can see a field “JNDI Name” at the bottom. You would be tempted to enter the JNDI name you previously defined (for the topic). But that would make no sense since it seems that we can define the destination on which we want to consume messages. Then what can it be ? Let’s see …
First, chose your destination (by clicking the “browse” button, you will scan through the previously chosen connection all the available destinations).

image

Once you’ve chosen the correct destination, the screen will display another option “Durable Subscriber ID”,
due to the fact we are working with a topic, and a default value will be set for the field “JNDI Name”.

image

Where does that JNDI name come from ?
After googling a while, I found that this name is (and has to be) a JNDI name defined on the binding “Outbound Connection Pools” of the JCA Adapter : JMS Adapter.  Ok, if you don’t know much about JCA, it sounds a bit complex, but it is not.
Connect to the WLS console (http://localhost:7001/console)
In the deployment section, look for the deployed “Resource Adapter” whose name is “JMS Adapter”, and click on it.

image

Go in the section “Configuration > Outbound Connection Pools

image

Click on the ‘+’ just before the “oracle.tip.adapter.jms.IJmsConnectionFactory” : it displays a set of configuration bound to JNDI names. You should start to guess where I’m about to go.

image

Here’s the default JNDI name “eis/wls/Topic” that appeared in the assistant. Click on it and it will lead you
to the configuration screen.

image

On that screen is some interesting information, such as the “ConnectionFactoryLocation” property, which indicates the JNDI name of the JMS connection factory you want to use.
But going with that configuration will NOT work. It’s due to a simple fact : to properly define a durable subscriber, you have to define a durable subscriber ID AND a client ID.
The durable subscriber ID was definable in the JDev assistant, but what about the client ID ? There’s unfortunately no dedicated field : we have to use the field “FactoryProperties”. To be more specific, you have to define your client ID such as : “ClientID=yourUniqueClientID”. As exposed here : http://forums.oracle.com/forums/thread.jspa?messageID=9520314, you have not only to define a unique subscriber ID but also a unique client ID. Then, as you can provide only a client ID for a “outbound connection”, you will have to define more than one.
Note : no matter what your choice is (using the default conf or create yours), updating the default configuration will create a deployment plan.
Personnally, I prefer to define my own stuff, that way, when I update a configuration, it’s easier to predict what changes it will imply. So click on the “New” button to define your own configuration. Select the existing group and click “Next”.

image

After that, enter a JNDI name and click “Finish”.

image

And finally, chose a destination where to save your deployment plan.

image
Check that your deployment plan has been taken into account and you’re done.
image

Last step, we now have to configure our freshly created “outbound connection pool”.

image

I simply defined the “ConnectionFactoryLocation” property to match the JNDI name I defined for my connection factory, I set a client ID and changed the fact my connectionFactory is transaction enabled. (of course, if your connectionFactory is not, leave that value to “false”).
The configuration, from the WLS side, is now over, so let’s turn back to JDev.
I can now set the last piece of missing information of the 7th screen …

image

… and go on with the wizard, straigth to the 8th screen. Here, we’ll define the schema used to qualify the message payload.

image

And that’s it ! You’re done !

image
Now on the BPEL Process “JMSBridge”, just remove the receive activity and replace it with another Receive activity, but this time which is linked to the JMS Adapter. Don’t forget to click on the checkbox “Create instance”. Remove also the original partnerLink as well as the variable used in the original Receive activity.
Then, add a Invoke activity and chose “Event” instead of “PartnerLink” and add a variable. Add an assign activity between the Receive and the Invoke and define a copy operation to replicate the message from the incoming payload to the payload of the outgoing message.

If, when you compile, you have an error message “Error(31,72): Service "jmsbridge_client_ep" does not
exist as wire source”, edit the composite and remove what’s left of the previous partnerLink.

image

In the end, your process will look like that :

image

Testing the JMS binding

First of all, restart your server. I’ve experienced some problem when I didn’t. Even if you redeploy your JMS Adapter, it won’t work and you will end in having NPE while trying to bind to the topic.
During the server restart, look for that message :
[2011-06-13T23:46:59.046+02:00] [AdminServer] [NOTIFICATION] [] [oracle.soa.adapter] [tid: weblogic.work.j2ee.J2EEWorkManager$WorkWithListener@bf46a] [userId: <anonymous>] [ecid: 0000J2AyCeQFw000jzwkno1DxcGx00000I,0] [APP: soa-infra] [dcid: 11d1def534ea1be0:-66ae329:1308af61f0e:-7fd1-0000000000000011] JMSAdapter BPELDurableSubscriber JMSMessageConsumer_init: Successfully created MessageConsumer for destination fr/mbutton/blog/jms/topic (payload = 1, subscriber = JMSBridge)

You can double check by verifying that your JMS Adapter is correctly bound to the topic. To do so, just go in the “Services > Messaging > JMS Modules” and click on your module.


image

Then in the monitoring section, click on the subtab “Durable Subscriber” : a line should be displayed.

image

Now, we have to make sure that a BPEL process instance is created when a JMS message is sent / received.

To send JMS messages, you can use a java class or use HermesJMS or do whatever you want to, it’s up to you ! :) But I chosed to write a custom class.
Here’s the payload I sent :

image

And in the EnterpriseManager, here’s what I’ve got in return :

image

Here are the details of this BPEL process instance :

image

So I guess I can say my bridge is working. Now the fun begins.

Testing the durable subscription

To test a durable subscription, there’s not many tests : the only one that makes sense is to de-activate the durable subscriber, send a JMS message, wait for a few seconds to see that the message is kept on the topic and that no BPEL process instance is created. Then, when the durable subscriber is reactivated, the JMS message must be consumed.
But how to disconnect a BPEL process from a topic ? Well that’s an interesting question. During my tests, I found out that a shutdown was disconnecting completely the composite from the topic. Then when a message arrived, the topic did not persist it since there was no durable subscriber. Not what I needed.
I then tried to “retire” the composite and there was my solution. The link was still there but was considered as “Inactive”, which is precisely what I was looking for.
In my use case, I had to develop a class which allows me to retire the process programmatically. In that article, I will simply use the EM to do so.

Retire the application

Using the EM, click on the “Retire” button.

image

Then if you click on your partition (the one on which you deployed your SAR), you should see the status “Retired”.

image

But the most interesting part is the topic monitoring, especially, the durable subscriber tab.
Before, it was like that :

image

And now it’s more (at least it should be) like :

image

Okay, so now, I have to send a message and normally, nothing should happen (fingers crossed)
The message has been sent !

image

I’ll wait for about one minute. Meanwhile, let’s have a look at the topic monitoring :

image

We can see that a message is currently on the topic. Means no one has eaten it yet (relief).
On the EM dashboard, the two previous instances are still there but no new instance has been created :

image

Now, it’s time to reactivate the composite (I won’t put a screenshot of the activation, I guess you know how it works :p)

The topic monitoring shows the durablesubscriber has been reactivated (Active = true) and there’s no message left.

image

Finally, let’s have a look at the BPEL process instances : it works !

image

And in detail :

image

Hope it will help some fellows out there ! Thanks for reading ! :)

4 comments:

Lucas Jellema said...

Very interesting article. Thanks for sharing it with us. And it's a good thing it wasn't eaten rightaway (so Max did not have to start over again).

Lucas

Maxence Button said...

Thanks for the kind word. It's flattering, especially coming from you ! :)

Max

Jagadeesh Varma said...

Thanks Max It's really very helpful.

Jagadeesh Varma said...

Thanks Max It's really very helpful.