2

I have an MDB which uses container managed transaction (my container is IBM Websphere 7).

Websphere is using a global (JTA) transaction.

If my MDB thread starts a worker thread, and that thread begins a transaction, will that new thread be within the same transaction as the MDB?

I want the MDB thread to commit its transaction and acknowledge the MQ message as soon as my worker thread is successfully started. I do not want my MDB to rollback if the worker thread rolls back.

Edit: The code in the thread has this - it is not using annotations:

    txn = (UserTransaction)ctx.lookup("java:comp/UserTransaction");
    txn.begin();

So if look at txn.getStatus() it will be something other than STATUS_NO_TRANSACTION. Therefore I need to get the transaction manager appropriate for Websphere 7 and call "suspend()" before the txn.begin()? Is the correct approach to prevent problems?

Tiny
  • 27,221
  • 105
  • 339
  • 599
Puffy_Fluff
  • 105
  • 1
  • 7

2 Answers2

2

Put the code which should not be in the same transaction as the onMessage() method into a separate method and set the transaction attribute for that method to REQUIRES_NEW. This will create a new transaction when the method is called and the success or failure of this new transaction won't affect the preexisting one.

By the way, you aren't supposed to do explicit thread management in JavaEE applications.

From the EJB 3.0 spec:

The enterprise bean must not attempt to manage threads. The enterprise bean must not attempt to start, stop, suspend, or resume a thread, or to change a thread’s priority or name. The enterprise bean must not attempt to manage thread groups.

You could look at using the timer service to effectively create a separate thread while leaving thread management to the server.

Tiny
  • 27,221
  • 105
  • 339
  • 599
Neil Weightman
  • 331
  • 2
  • 4
  • We are using something like this to start the threads: com.ibm.asynchbeans.WorkManager.startWork(...) – Puffy_Fluff Nov 15 '12 at 19:56
  • OK, great. Just change the transaction attribute and you should be fine, then. – Neil Weightman Nov 15 '12 at 20:02
  • I posted an edit to my original question about the right way to implement requires new in this code. Thanks. – Puffy_Fluff Nov 15 '12 at 20:44
  • All you need to do is set the transaction attribute for the method in the deployment descriptor for whichever method contains the thread-related code. You don't need to do any explicit transaction-related coding in your EJB along the lines that you describe. – Neil Weightman Nov 15 '12 at 21:08
1

If you are using ejb 3.1 an option would be to do the worker work in a method annotated with

@Asynchronous

This will give you a new transaction and the work will be performed in a separate thread.

http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/asyncMethodOfEJB/AsyncMethodEJB.html

Read more about default transaction mode: Default EJB transaction mode for asynchronous methods?

Community
  • 1
  • 1
Aksel Willgert
  • 11,367
  • 5
  • 53
  • 74