Peter
Peter

Reputation: 5894

Transaction in JPA using multiple threads

My objective is to provoke an optimistic locking exception in my application using a unit test. I already have a understanding on how to do this in theory. But my problem in practice is how do I maintain a transaction between two threads ?

So, this is what I've done so far:

I am using a JUnit test with:

@RunWith(SpringJUnit4ClassRunner.class)

using EntityManager org.springframework.orm.jpa.JpaTransactionManager

where each method is defined @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)

and start a transaction with entityManager.getTransaction().begin(); and end with entityManager.getTransaction().rollback());

This works great, saving, updating etc in single threaded tests.

To create multiple threads I use Springs TaskExecutor (similiar to what's desribed here: Any good Spring threading with a TaskExecutor examples?)

But what do I have to do to maintain the transaction between the two threads? I've tried stuff like annotating the run()-method with @Transactional but this doesn't work.

Upvotes: 4

Views: 8030

Answers (1)

Sashi
Sashi

Reputation: 2425

Few questions that come to mind -

Global Transaction
Should all of your threads be part of the same transaction? The implications are that, if a thread throws an exception, do you want to rollback changes in other threads?

Local Transaction Should each thread have it's own transaction boundary with out affecting other threads? In this case, the exceptions and rollbacks in one thread do not affect other threads.

To achieve global transactions, you will most likely have to use a JTA transaction manager with appropriate resource drivers. Spring does not have default support for global transactions. If your application is running in a Java EE application server (Jboss, Weblogic), you get JTA support by default and you could configure spring to use your application server's transaction management capabilities. If you are running in tomcat, you could plugin an open source JTA implementation like -

Atomikos

Jboss Transactions

To achieve local transactions (i.e., each thread with it's own transaction boundaries), I don't think you will have to do anything more than use spring transactional annotations. In the following example, just make sure that 'service' is a spring bean and doSomething() is appropriately annotated.

taskExecutor.execute( new Runnable() {
           public void run() {
                service.doSomething( );
           }
      });

Upvotes: 6

Related Questions