JTA Transactional Resource Implementation by Example
Asked Answered
A

1

7

I'm trying to understand the basic principles of making a remote/networked resource compliant with JTA, and I'm thunderstruck by how little documentation/blogs/articles there are out there on the subject.

Say I have written my own special type of server, the "IAmYourFaja" server, or "IAYF". And let's say I wrote/implemented my very own TCP-based network protocol for interacting with this server, called IAYFCP (IAYF Comms Protocol). Finally, I wrote a Java client library for accessing and sending message to a remote IAYF server over IAYFCP. Still with me?

Now I have a use case where I need to do the following distributed transaction:

  1. Insert a record in a relational/JDBC database; then
  2. Fire a message to my IAYF server; then
  3. Push a message to a JMS broker

I need these to all transact so that if any one component fails at any point, I can roll all of them back and not have any altered state in these network resources.

The ultimate goal would be to be able to run the following code (pseudo-code here):

// "JTA Example"
DistributedTransaction dTrans = getTransaction();
DataSource jdbcDataSource = getDataSource();
IayfClient iayfClient = getIayfClient();
JmsClient jmsClient = getJmsClient();
try {
    dTrans.begin();

    // 1. Insert a record in a relational/JDBC database
    insertRecord(jdbcDataSource, "INSERT INTO widgets ( fizz, buzz ) VALUES ( 35, true )");

    // 2. Fire a message to my IAYF server
    iayfClient.fireMessage(IayfMessages.LukeIamYourFaja, 12);

    // 3. Push a message to a JMS broker
    jmsClient.publishMessage("Noooooooooo! (then jumps off ledge and Vader goes off to the bar)");

    // If we get here then all 3 networked resources are ready/capable of committing, so do it, do it now!
    dTrans.commit();
} catch(Throwable t) {
    // Something went wrong, roll back all 3.
    dTrans.rollback();
}

So the JDBC driver and JMS library I'm using are already JTA-compliant. This means that to make this code possible, I need to make my IAYF client library also JTA compatible. The problem is, I don't understand which JTA interfaces I would need to implement:

So a few questions:

  1. Which interface do I need to implement (and why): XAResource, UserTransaction, or both?
  2. Is that all I need to do to comply with JTA and make my IAYF client/service transactional? Anything else I need to do to make the "JTA Example" code above work as expected?
  3. True or false: Java EE containers have their own transaction managers that I could leverage with near-zero config, however, if I run my app in a non-Java EE/JTA compliant container, then I need to provide my own Transaction Manager, and could use something like Bitronix or Atomikos to accomplish this?
Apiculate answered 13/12, 2014 at 19:37 Comment(0)
A
6

The UserTransaction interface is what you're using in your application (your pseudo-code above) to work with different resources. The DistributedTransaction would implement the UserTransaction interface. That DistributedTransaction object is your way to access the transaction manager.

In order for the transaction manager to carry out the distributed transaction against your 3 different resources, each needs to implement the XAResource interface and be registered somehow with the transaction manager. The details of how to register with the transaction manager depend on the implementation. For example see this section of the WebLogic documentation: Registering an XAResource to Participate in Transactions

So your client would implement XAResource and speak IAYFCP to your IAYF server. That also means that your IAYFCP protocol will need to support 2 phase commit.

Starting at section 3, this JBossTS documentation covers the XAResource interface too.

Yes, Bitronix, Atomikos and JBossTS are all listed as open source JTA implementations, according to this Wikipedia article on JTA. I suggest choosing one, implemeting a stub XAResource and then try registering your "Hello, world" XAResource with the transaction manager to see that it will make calls to your start/prepare/commit/rollback methods.

Audsley answered 19/12, 2014 at 6:54 Comment(5)
Thanks @Harold L (+1)! A few followups: (1) Please confirm: I would not need to implement UserTransaction, because this would be provided by the Transaction Manager, yes?Apiculate
(2) When you say "your IAYFCP protocol will need to support 2 phase commit...", is this another Java API I need to implement (if so which API and where is it documented?), or is it just that I need to interpret the basic principles of the 2 phase commit protocol into the client-server communication?Apiculate
(3) Please confirm, only because I can't quite decipher your answer to this above: I only need something like Bitronix/Atomikos/JBossTS if I'm using distributed transactions outside of a Java EE server (because Java EE servers have their own transaction managers), yes? Furthermore, if I do happen to need an "independent" transaction manager, such as Bitronix/Atomikos/JBossTS, then do I stand it up as its own server/VM, or is it just a lib that I pull into my project, like any other JAR? Thanks again - the bounty reward is coming soon!Apiculate
I can't give you the bounty if you can't help me with these followup questions! Please advise!Apiculate
Ugghhh, classic SO. Hamped and damped.Apiculate

© 2022 - 2024 — McMap. All rights reserved.