Java: XA Transaction Propagation in Many Threads

How can I use a transaction manager (e.g. Bitronix , JBoss TS or Atomikos ) in Java SE (not Java EE or Spring) to support the following use case:

Suppose we have the following class:

public class Dao { public void updateDatabase(DB db) { connet to db run a sql } } 

and we create a Java Runnable from this, as shown below:

 public class MyRunnable extends Runnable { Dao dao; DB db; public MyRunnable(Dao dao, DB db) { this.dao=dao; this.db = db; } public run() throws Exception { return dao.updateDatabase(db); } } 

Now, in our Service layer, we have another class:

 public class Service { public void updateDatabases() { BEGIN TRANSACTION; ExecutorService es = Executors.newFixedThreadPool(10); ExecutorCompletionService ecs = new ExecutorCompletionService(es); List<Future<T>> futures = new ArrayList<Future<T>>(n); Dao dao = new Dao(); futures.add(ecs.submit(new MyRunnable(dao, new DB("db1"))); futures.add(ecs.submit(new MyRunnable(dao, new DB("db2"))); futures.add(ecs.submit(new MyRunnable(dao, new DB("db3"))); for (int i = 0; i < n; ++i) { completionService.take().get(); } END TRANSACTION; } } 

And the client can be a servlet or any other multi-threaded environment:

 public MyServlet extend HttpServlet { protected void service(final HttpServletRequest request, final HttpServletResponse response) throws IOException { Service service = new Service(); service.updateDatabases(); } } 

What will be the correct code for the BEGIN TRANSACTION and END TRANSACTION parts? Is it possible? If not, what needs to be changed? Requirements - to support the updateDatabases () method at the same time (since it will access several databases at the same time) and transactional.

+4
source share
3 answers

It seems like this can be done using Atomikos using SubTxThread

 //first start a tx TransactionManager tm = ... tm.begin(); Waiter waiter = new Waiter(); //the code that calls the first EIS; defined by you SubTxCode code1 = ... //the associated thread SubTxThread thread1 = new SubTxThread ( waiter , code1 ); //the code that calls the second EIS; defined by you SubTxCode code2 = ... //the associated thread SubTxThread thread2 = new SubTxThread ( waiter , code2 ); //start each thread thread1.start(); thread2.start(); //wait for completion of all calls waiter.waitForAll(); //check result if ( waiter.getAbortCount() == 0 ) { //no failures -> commit tx tm.commit(); } else { tm.rollback(); } 
+2
source

The XA specification requires that all XA calls be made in the same thread context. To clarify the reason for this, this is due to the fact that a commit can be called before any of the transaction branches are created even in your threads.

if you are just interested in how to make these three calls in an XA transaction in JBoss TS

First make sure your -ds.xml points to your data source as <xa-datasource>

 InitialContext ctx = new InitialContext(parms); UserTransaction ut = (UserTransaction) ctx.lookup("java:comp/UserTransaction"); ut.begin(); //Some Transactional Code ut.commit(); 

Keep in mind that with the code above, you cannot use the ExecutorService to parallelize calls.

Side note: I don’t know much about this, but JTS / OTS claims to allow multiple threads to share a transaction. I think this happens by propagating a transactional context like ws-coord / ws-transaction and is supported by JBossTS. Maybe a red herring, but if you don't crunch at times, it might be worth exploring.

+1
source

What about you

  • BEGIN_TRANSATION: connect to all 3 databases in the service,
  • pass Connection objects (instead of db object) to MyRunnable
  • END_TRANSACTION: call commit and close all three connections to your service
0
source

Source: https://habr.com/ru/post/1343403/


All Articles