Suppose I want to implement an application container. Not a full-on Java EE stack, but I need to provide access to JDBC resources and transactions to third party code that will be deployed in an application I'm writing.
Suppose, further, that I'm looking at JBossTS for transactions. I'm not settled on it, but it seems to be the best fit for what I need to do, as far as I can tell.
How do I integrate support for providing connection resources and JTA transactions into my Java SE application?
How do I integrate support for
providing connection resources and JTA
transactions into my J2SE application?
Hi Chris
There are two elements to this problem:
1) Making the JTA API, mainly UserTransaction, available to application code, so it can start and end transactions. In A Java EE environment it’s published into a well known location in JNDI. If you have a JNDI implementation that’s the way to go (Use JBossTS’ JNDIManager class to help you with the setup). Otherwise, you need some kind of factory object or injection mechanism. Of course you can also expose the implementation class direct to the end user, but that’s somewhat nasty as it limits any chance of swapping out the JTA in the future.
public javax.transaction.UserTransaction getUserTransaction() {
return new com.arjuna.ats.internal.jta.transaction.UserTransactionImple();
}
That’s it – you can now begin, commit and rollback transactions. Some containers also publish the TransactionManager class to applications in similar fashion, but it’s really designed for use by the container itself and rarely needed by the application code.
2) Managing enlistment of XAResources automatically. Resource managers i.e. databases and message queues, have drivers that implement XAResource. Each time the application gets a connection to the resource manager, a corresponding XAResource needs to be handed off to the JTA implementation so it can drive the resource manager as part of the 2PC. Most app servers come with a JCA that handles this automatically. In environments without one, you need some alternative to save the application code from having to do this tedious task by hand. The TransactionalDriver bundled with JBossTS handles this for JDBC connections. XAPool may also be worth considering.
JBossTS has been embedded in many environments over the years. Some of the lessons learned are documented in the Integration Guide http://anonsvn.jboss.org/repos/labs/labs/jbosstm/trunk/atsintegration/docs/ ] and if you want a worked example you could look at the tomcat integration work http://anonsvn.jboss.org/repos/labs/labs/jbosstm/workspace/jhalliday/tomcat-integration/ ]
JBoss's TM is horrible. At least, if
you are hoping for ACID transactions.
Hi erickson
I don’t think I’d go quite as far as ‘horrible’. It’s incredibly powerful and highly configurable, which can make the out of box experience a bit daunting for newcomers. Correct recovery configuration is particularly tricky, so I fully endorse your comment about rigorous testing. Beyond that I’m not aware of any documented test cases in which it currently fails to provide ACID outcomes when used with spec compliant resource managers. If you have such as case, or just more constructive suggestions for improvement, please let JBoss know so the issue can be addressed.
Don't reinvent the wheel. Use the
Spring Framework. It already provides
this functionality and much more.
-1 Spring does not provide a JTA implementation, just a wrapper for various 3rd party ones. This is a common misunderstanding.
JTA supports local transactions and
global transactions.
Another misconception I’m afraid. The JTA spec deals only with XA i.e. global transactions. Various well known techniques exist for making a JTA transaction manager drive local transactions. These usually involve wrapping the Connection in an XAResource. Whilst most implementations support this it’s actually outside the scope of the spec and so you must check with the vendor before choosing a JTA implementation if you need this behaviour.
Try Atomikos TransactionsEssentials.
Unlike competing open source JTA/XA implementations, this one was written from the start for JSE. Consequently, it offers premium JDBC and JMS pools as well as JTA/XA functionality, and you will find it very easy to integrate into your applications.
Best
Guy
Don't reinvent the wheel. Use the Spring Framework. It already provides this functionality and much more.
You can use Spring, much as I'm not that keen.
An example of what you might want is here
JTA supports local transactions and global transactions.
Local transactions can be easily handled by Spring, JPA or even manual commits on connections.
Global transactions REQUIRE a transaction coordinator. That's a separate product/library which is not readily available in open source (or at least I'm not aware of it).
So, if I look onto the header of your post ("JTA"), the answer is NO SIMPLE WAY.
If I read your posting itself ("provide access to JDBC resources and transactions"), I'd say Spring, JPA and Hibernate all would cover your needs (as I understood them).
P.S. Correction: JTA doesn't really support local transactions (as people have pointed me out), but a case when you only need a single connection is essentially a local transaction, even if controlled by JTA, especially when Transaction Manager is located in the same JVM (as it often happens).
"JBoss's TM is horrible. At least, if you are hoping for ACID transactions. The best that one can say about it is that it will probably not screw up as long as it doesn't have to contend with any failures. And it's not alone... most transaction managers (even some commercial ones) really don't work."
Not sure what homework you did to make the above statement, but JBossTS (the TM in JBoss since 2006, when it was acquired) does provide full ACID semantics. It was also originally part of the HP NetAction suite, where it was deployed in more mission critical applications than any of the other open source TMs.
I've elected to use the Bitronix Transaction Manager to solve this problem, although apparently there's at least one other option that wasn't apparent to me at the time (Atomikos).
Solving this ended up requiring me to use the Tomcat in-process JNDI provider as well, in order to associate the transaction with a JNDI name. Due to a limitation of that provider, I could not use the default name for a JTA UserTransaction, which isn't immediately apparent from the documentation.
Thanks to all for the helpful answers anyhow!