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 :
- Design a simple process that listens through a mediator to the publishing of a message on the EDN
- Test that process with the Enterprise Manager
- Configure the JCA Adapter in charge of JMS and plug our process to a JMS topic
- Configure the JCA Adapter to make BPEL PM a durable subscriber
- Test how to deconnect BPEL PM from the topic
- Test that JMS messages are kept when BPEL PM is offline, and that they are correctly sent when BPEL PM comes back online.
BPEL Process 1 & its Mediator : EDN message consumerThat 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) :
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.<?xml version="1.0"?><xs:schemaxmlns:xs=http://www.w3.org/2001/XMLSchematargetNamespace="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>
And in the end, the composite will look like that :
BPEL Process 2 : EDN message senderA simple BPEL Process whose role is to send (through an Invoke activity) a message over the EDN.
The composite will look like that :
Once everything’s ready, just deploy it to the WLS server.
First testAs 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.
Note : I could have used the embedded message functionality (right click on “soa-infra (AdminServer)" >
Business Events”, but I prefer my own tool :)
But okay, just send a message (one way or another) and see what happens :
And when I click on the MessageEater instance, I see that the EDN message has been properly consumed :
Creating the JMS basisFirst 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 ?).
In the end, I’ve got something like that :
Just note that I chose to have a XA enabled connection factory.
Durable subscriber configurationNow 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.
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”
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.
On screen 6, chose the operation “Consume Message” and click “Next”. Screen 7 is where things become a bit trickier.
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).
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”.
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.
Go in the section “Configuration > Outbound Connection Pools”
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.
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.
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”.
After that, enter a JNDI name and click “Finish”.
And finally, chose a destination where to save your deployment plan.
Check that your deployment plan has been taken into account and you’re done.
Last step, we now have to configure our freshly created “outbound connection pool”.
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 …
… and go on with the wizard, straigth to the 8th screen. Here, we’ll define the schema used to qualify the message payload.
And that’s it ! You’re done !
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.
In the end, your process will look like that :
Testing the JMS bindingFirst 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.
Then in the monitoring section, click on the subtab “Durable Subscriber” : a line should be displayed.
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 :
And in the EnterpriseManager, here’s what I’ve got in return :
Here are the details of this BPEL process instance :
So I guess I can say my bridge is working. Now the fun begins.
Testing the durable subscriptionTo 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 applicationUsing the EM, click on the “Retire” button.
Then if you click on your partition (the one on which you deployed your SAR), you should see the status “Retired”.
But the most interesting part is the topic monitoring, especially, the durable subscriber tab.
Before, it was like that :
And now it’s more (at least it should be) like :
Okay, so now, I have to send a message and normally, nothing should happen (fingers crossed)
The message has been sent !
I’ll wait for about one minute. Meanwhile, let’s have a look at the topic monitoring :
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 :
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.
Finally, let’s have a look at the BPEL process instances : it works !
And in detail :
Hope it will help some fellows out there ! Thanks for reading ! :)