I wrote in my last post about how to route messages between software based on Oracle Advanced Queuing (AQ) and Apache ActiveMQ, using Camel over ServiceMix. Today, I’d like to write about a different option than the ones I talked before: the XA option.
There are situations where, in case of any exception, you have to guarantee that in any way any message is lost and that messages are not received duplicated, these situations are where the X/Open XA standard comes into action.
I started my research on this issue by looking for documentation and examples. Two elements where very useful at this point: an Oracle White Paper about XA and Oracle controlled Distributed Transactions, that allowed me to review the XA topic, and a very good sample of a similar situation that shows how to use XA transactions with Camel across ActiveMQ and WebSphere MQ written by Torsten Mielke. You can find the result code of my XA test on my GitHub repository.
The test has a processor, copied from Torsten’s example, that simulates an exception and allows you to see how the exchange is recovered. But, the interesting issue here is trying to recover after an Oracle database crash or a network failure in the middle of a message exchange. I’ve made many test, for the first ones I used an Oracle 11.2 test database over a Microsoft Windows operative system and Apache ServiceMix 6.0, also over Windows. In this environment, I submitted shutdown abort and shutdown immediate commands to the database and the Geronimo recovery manager didn’t recovered the Oracle branches in prepared state, so I had to commit force the in-doubt transactions.
I wasn’t happy with the previous solution, which it is not recommended by Oracle (read the previously linked white paper) and it isn’t transparent for the user. My final environment wasn’t Windows bases, but Linux, so I ran other tests using another Oracle 11.2 database installed over Linux Red-Hat and Apache ServiceMix 6.0, also over Linux. In this case, the Geronimo recovery manager was capable of recovering prepared transactions and I couldn’t reproduce the error. An Oracle database configuration problem? an operative system issue? That’s I suppose.
I’ve been working with Apache ServiceMix lately and I expect to carry on doing in next months. One of the issues I’ve faced is how to route messages between software based on Oracle Advanced Queuing (AQ) and other systems, using one of the main components of Apache ServiceMix: Camel. In this post, I’d like to start talking about the approach I’ve selected. I’m still working with XA, so this is just the beginning! The code of my proof of concept is on github.
The first topic I had to study was how to deploy the libraries needed to work with Oracle AQ: aqapi.jar and ojdbc6.jar I started embedding the jar files on the bundle, but this approach implies that the libraries have to be attached to each bundle, so I finally decided to create a feature that wraps the files and converts them to OSGI bundles. This is the first module of my code repository, called feature.
Then, I started to work in a basic connection, using the Camel JMS component, by injecting an Oracle AQ connection factory bean. You have my code on the second module of the project, called basic-test. But this solution is not scalable, because the component creates a JMS connection, which implies a JDBC one, each time a message is sent and this is an expensive process, so I investigate the use of connection pools.
The question I had to study at this point was if I just had to create a JDBC connection pool or a JMS one, I selected the second option because a JMS connection not only implies a JDBC connection, as I said before, but also other stuff of JMS api. A very, very basic benchmark showed me that my test environment (Apache Service Mix 6.0.0, Oracle 11.2.0 database on virtual machines) took 3 seconds in sending 100 messages on the performance test, versus 14 seconds on the basic one.
On the other hand, receiving messages test results weren’t so impressive, I tested competing consumers and asynchronous parameters (which cannot be uses in all use cases). My configuration is in the module performance-test of the github code repository, where you can play with the configuration parameters of the bundle and get your own conclusions.