Home > SOA Suite > Global transactions with JMS or AQ and BPEL in 11g

Global transactions with JMS or AQ and BPEL in 11g

The concept of a global (XA) transaction is very useful in many integration scenarios, as it is much easier to operate a solution where all changes or no changes are performed. BPEL is primarily intended for long-running processes where a single global transaction is impractical, but even so it is often possible to model using transactional parts with known milestones. This pattern is used in Oracle AIA, for example. In the real world many organizations use BPEL for simple processes where a single global transaction can be used as well.

Assume that a message arrives on a queue. It needs to be transformed and processed somehow; then another message should be written to an output queue, a database should be updated and a long-running asynchronous process spawned. If something goes wrong the message should be rolled back to the input queue where it can be retried (or eventually moved to dead letters by the queue manager) and all the other changes should be rolled back as well.

This was possible to do in 10.1.3.3, but it required some black magic. The WSDL file for the input adapter had to be modified and all the BPEL processes had to run in-memory with completionPersistLevel=off and with transaction=participate everywhere. It worked, but the instances would never appear in the BPEL console, making it hard to see what was going on in the system.

With 11g this works much better. It is no longer necessary to use in-memory optmization and the full audit trail can be saved and viewed in the console. The Mediator can be used as well. However, the procedure is still poorly documented and it still requires manual changes in the generated code.

To try it out, create two queues (one inbound and one outbound) and a test table. Create a new composite. Add an inbound AQ or JMS adapter and an outbound AQ or JMS adapter. Add a database adapter for the test table. Create an asynchronous BPEL process that does nothing. Create a synchronous BPEL process that inserts a record into the table, calls the asynhrounous BPEL process and finally enqueues a message into the output queue. Finally create another BPEL process or Mediator component that dequeues a message from the input queue and invokes the synchronous BPEL process.

Enqueue a message on the input queue. The entire flow should appear in the console, a new record should be present in the table and a message should appear in the output queue. So far so good. Now, disable enqueue for the output queue and try again. What happens? Without a global transaction the message will be removed from the input queue, a new record will appear in the table, the asynchronous process will run but nothing appears on the output queue!

Right, do the obvious thing. Edit composite.xml and add bpel.config.transaction=required for all the BPEL processes. Assuming that the application server has been configured correctly with an XA data source this should do the trick, right? Wrong. The changes are rolled back, so there will be no new record in the table and no asynchronous process. However, the message is still removed from the input queue and lost.

Time for some undocumented magic. Edit the WSDL file for the input adapter and add a new type, a new element and a new message. Include the new message as output message, making the WSDL synchronous. For example (assuming an opaque JMS adapter and showing only the relevant parts):

Edit the BPEL process or Mediator component that dequeues the message and add a reply to the adapter. Good to go? Almost. Everything looks good, but for some reason the message will still be lost. As a final step the input adapter must be configured with jca.retry.all=true in composite.xml. With that option in place, deploy the code and try again. This time the message should be returned to the input queue and retried and eventually moved to dead letters, where it can be handled.

In summary:

1) Configure all BPEL processes with bpel.config.transaction=required in composite.xml.
2) Modify the generated WSDL file for the AQ or JMS adapter and add an output message, making it synchronous.
3) Configure the AQ or JMS adapter with jca.retry.all=true in composite.xml.
4) Use an XA data source.

This has been tested with 11.1.1.5.

About these ads
Categories: SOA Suite
  1. Sumit
    2012-07-11 at 10:08 | #1

    Thank u so much….making the adapter synchronous did the trick….i was struggling on this for so long…. Any idea why impact does the synchronous adapter have on the rollback procedure.

    • 2012-07-11 at 10:19 | #2

      Yes, I do. If the adapter is asynch it will dequeue the message, save it internally and commit the dequeue before calling your code. A rollback in your code cannot affect the original transaction, which has already been committed. With a synchronous call on the other hand the adapter can dequeue the message and call your code using the same global transaction. That way a rollback returns the message to the queue.

  2. Gary Bolton
    2013-02-05 at 23:48 | #3

    We are using topics and are trying to find a way to control the acknowledgement so that we can redeliver to a particular consumer. We are trying to use client_acknowlege in the connection factory. Basically, we want to wait to acknowlege the message until the global transaction completes successfully. It sounds like the same process of configuring the adapter as synchronous might do the trick. Does the JMS adapter support this?

    • 2013-02-06 at 08:39 | #4

      I don’t know about the detailed semantics for client_acknowledge in the adapter, but if you have a persistent topic with multiple consumers and the consumers are configured to use global transactions with a synchronous adapter configured the way I have described it everything should work. A message committed to the topic will be delivered to every consumer. If one consumer rolls back, the message is returned to the topic for redelivery to that consumer, but the other consumers are not affected. In other words you get redelivery for a particular consumer.

      One word of warning, though. JMS is only a standard, the actual implementations can differ a lot. It can be problematic to get global XA transactions working correctly with some implementations. Oracles AQ JMS works well. I seem to recall testing this with Weblogic JMS as well. If you are using another JMS implementation you will have to dig into the details. If so it may be a good idea to test that the global transactions are working with a simple Java program before you spend too much time with the more complex adapter!

  3. priti
    2013-09-05 at 14:16 | #5

    Hi Erik, I am still facing one issue after making the wsdl async. I am getting the below error while compiling. Error(74): Operation “Consume_Message” of portType “{http://xmlns.oracle.com/pcbpel/adapter/jms/AP/ErrorHandler/JMS_IN}Consume_Message_ptt” is a request-response operation. Need to respond with a activity.

    This is my first activity in bpel , where I am listening to a JMS queue.

    • 2013-09-05 at 14:32 | #6

      For this to work the BPEL process that reads the JMS message must be synchronous, it cannot be async.The transaction will be committed (and the message removed from the queue) when the BPEL process replies to the adapter. Alternatively the transaction will be rolled back and the message returned to the queue when the BPEL process fails with an exception. Does that answer your question?

  4. Parshant Mehra
    2013-09-10 at 04:38 | #7

    Eric, Very nice article. But one point. Instead of going with Synchronous adapter, we can use – oneWayDeliveryPolicy to sync. This setting does the same job as synchronous adapter does . But I will try your topic suggestion.

    Thanks,
    Parshant

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: