4

JBoss 4.x
EJB 3.0

I've seen code like the following (greatly abbreviated):

@Stateless
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class EJB1 implements IEJB1
{
   @EJB
   private IEJB1 self;

   @EJB 
   private IEJB2 ejb2;

   @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
   public boolean someMethod1()
   {
     return someMethod2();
   }

   @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
   public boolean someMethod2()
   {
     return self.someMethod3();
   }

   @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
   public boolean someMethod3()
   {
     return ejb2.someMethod1();
   }
}

And say EJB2 is almost an exact copy of EJB1 (same three methods), and EJB2.someMethod3() calls into EJB3.someMethod1(), which then finally in EJB3.someMethod3() writes to the DB.

This is a contrived example, but have seen similar code to the above in our codebase. The code actually works just fine.

However, it feels like terrible practice and I'm concerned about the @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) on every method that doesn't even actually perform any DB writes. Does this actually create a new transaction every single time for every method call with the result of:

new transaction
-new transaction
--new transaction
---new transaction
...(many more)
-------new transaciton (DB write)

And then unwraps at that point? Would this ever be a cause for performance concern? Additional thoughts?

Harrison F
  • 492
  • 5
  • 15

2 Answers2

12

Does this actually create a new transaction every single time for every method call

No, it doesn't. The new transaction will be created only when calling method by EJB reference from another bean. Invoking method2 from method1 within the same bean won't spawn the new transaction.

See also here and here. The latter is exceptionally good article, explaining transaction management in EJB.

Edit:
Thanks @korifey for pointing out, that method2 actually calls method3 on bean reference, thus resulting in a new transaction.

Community
  • 1
  • 1
jFrenetic
  • 5,384
  • 5
  • 42
  • 67
  • 1
    He injects the second bean via @EJB, not just calling method. self.someMethod3() - STARTS TRANSACTION – korifey Dec 08 '11 at 18:13
  • Thank you for your answer jFrenetic - do you have any insight on performance implications of needlessly invoking new transactions in chained method calls where no DB writes are done (until at the very end as my question explains)? Is it negligible (as in I shouldn't worry about it), or is it significant enough for me to raise a stink over it and then try to cleanup our existing code? – Harrison F Dec 08 '11 at 19:09
  • Well, EJB transactions go far beyound DB writes. I insist you on reading the article I provided in the second link, it'll give you much more insight on how the transactions are handled by container. I'd say it depends, sometimes it's crucial for a method to spawn a new transaction (see the "Dealing with exceptions" section in the mentioned article). Also [Sun's official J2EE tutorial](http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/Transaction3.html) recommends on using @REQUIRED (the default) in early phases of development. – jFrenetic Dec 08 '11 at 19:45
4

It really creates new JTA transaction in every EJB and this must do a serious performance effect to read-only methods (which makes only SELECTS, not updates). Use @SUPPORTS for read-only methods

korifey
  • 3,379
  • 17
  • 17
  • 1
    -1 The answer is wrong. No transaction is created in local method calls. – jFrenetic Dec 08 '11 at 18:06
  • 1
    Alright, taking back my down vote. I was looking at method1 implementation. – jFrenetic Dec 08 '11 at 18:16
  • Crap, that's impossible unless you edit your answer. Sorry about that. – jFrenetic Dec 08 '11 at 18:19
  • 1
    No problem, everybody mistakes 8) – korifey Dec 08 '11 at 18:25
  • You say that it seriously affects performance of read-only methods on the DB. Why is that? My assumption is that you are needlessly creating transactions for an operation that doesn't require a transaction (IE just the SELECTs). Secondly, creating a new transaction for each chained method call that say 10 calls later finally performs the DB write - is this still not a performance problem? Would this not still result in 10 different transactions that then unwind after the DB write? – Harrison F Dec 08 '11 at 18:58
  • Guess you probably won't be checking back. In any case, thank you for your answer +1. – Harrison F Dec 09 '11 at 17:40
  • 1
    @jFrenetic your first comment saved my day – SourceVisor Dec 05 '16 at 16:26