@MessageDriven transactions and redelivery semantics
Asked Answered
B

2

8

What's the best way to accomplish the following?

  • @MessageDriven bean does some work on database
  • on failure, I want to roll back the DB transaction
  • but I also want the JMS message NOT to be redelivered, i.e., don't re-try.

I can think of a few ways that might work. Are there any others, and which is the best?

  • use @TransactionManagement(type=BEAN) and UserTransaction, and explicitly roll back after catching exception. e.g.:

    catch (Exception e) { e.printStackTrace(); utx.rollback(); }

  • Use container-managed transactions, specify @TransactionAttribute(value=NOT_SUPPORTED) on onMessage and then delegate DB activity to a separate method with @TransactionAttribute(value=REQUIRED).

  • Leave the transaction handling alone and re-configure the retry property in the server. I'm using Glassfish 3.1.1, and I'm not exactly sure how to set this.

  • Leave everything alone and explicitly check the message for re-delivery in the onMessage body, and exit out if re-delivered. (message.getJMSRedelivered()?)

What has worked well out there? Is there a standard/best-practice way for dealing with this?

Botsford answered 31/12, 2011 at 17:33 Comment(0)
O
8

Simplest and most portable approach is use @TransactionAttribute(value=NOT_SUPPORTED) on onMessage() as you state and to move the DB work to another bean with @TransactionAttribute(REQUIRES_NEW)

Be careful about the separate method approach as this will not work. In a JMS MDB the onMessage() method is the only method where @TransactionAttribute can be used.

Ordinate answered 2/1, 2012 at 19:0 Comment(2)
Thanks, this worked perfectly. The note about @TransactionAttribute in MDBs was key - you're right, you can only annotate onMessage. I didn't annotate onMessage in the end but did move the logic to another EJB with REQUIRES_NEW.Botsford
Just as a note, it works with the child EJB annotated with "REQUIRED".Neolatin
G
2

Personally I never do any work in the MDB, but dispatch immediately to an (injected) session bean.

This bean then does the DB work. It either starts a new transaction, or I catch any exception from the bean and log it (but don't let it propogate, so no redelivery).

This also has the advantage that the business logic is easly reusable from other places.

Globefish answered 2/1, 2012 at 9:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.