• Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Caller bean is discarded when callee throws EJBException?

 
Himai Minh
Ranch Hand
Posts: 1361
7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Refering to p.386, table 15,
consider this scenario:

if Bean A has method a() with transaction type attribute = required,
Bean B has method b() with transaction type attribute = requires_new,
a() invokes b().
Bean A is the client of Bean B.

if b() throws EJBException , bean B's transaction is rolled back and bean B is discarded.
Will bean A be discarded also?
Will bean A's transaction marked rollback?

The table says
From client's view, if the client executes in a transaction, the client's transaction may or may not be marked for rollback.

This table does not mention if the client , which is also a bean, will be discarded.
 
Himai Minh
Ranch Hand
Posts: 1361
7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Let me answer my own question.
If bean B throws a system exception and the caller, bean A catches the exception, bean B is discarded and bean A is not discarded. (I can see bean A is not discarded when I shut down the container, the @PreDestroy method of bean A is called.) The transaction of bean A is not rollback.

If bean B throws a system exception and the caller bean A does not catch the exception, bean B and A will be discarded. And the transaction of bean A is marked for rollback.
 
Frits Walraven
Creator of Enthuware JWS+ V6
Saloon Keeper
Pie
Posts: 2536
113
Android Chrome Eclipse IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Himai,

Good question ! and the answer is: it depends

Normally you want a method anotated with REQUIRES_NEW not to affect the current transaction. Coding will be something likes this:

In this case BeanA is not affected by the transaction rollback and the EJBException inside beanB.

Now if you don't catch the exception, BeanA.methodA() will throw a System Exception (i.e. EJBException). Normal rules apply:
  • Exception will be logged by the container
  • EJB will be discarded
  • Transaction will be rollbacked (or marked for rollback: setRollBackOnly() if transaction was started by another client, let's say initialClient)
  • Container will throw EJBException to the initialClient or EJBTransactionRollbackException to the initialClient (if transaction was started by initialClient)


  • Does this clear up your doubts?

    Regards,
    Frits
     
    Himai Minh
    Ranch Hand
    Posts: 1361
    7
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    For everyone's reference as this seems very important for the exam,
    If these three conditions hold:

    1. bean B 's b() method's transaction attribute type is also required
    2. b() throws a system exception
    3. a() catches the exception,

    these will happen:
    1. a() catches the exception wrapped by EJBTransactionRollbackLocalException
    2. bean B is discarded.
    3. bean A is not discarded.
    4. a()'s transaction is marked for rollback.


    It concludes that if the caller bean (eg bean A in this case) catches the system exception thrown by the callee bean, the caller bean is not discarded.
    If the callee's transaction is a new one, the caller's transaction won't be rollbacked.
    If the callee's transaction is the same as the caller's , the caller's transaction will be rollbacked.
     
    Himai Minh
    Ranch Hand
    Posts: 1361
    7
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Hi, Frits. Thanks for your example.
    A similar question was asked in Enthuware.
    I tried with a similar example:



    Warning: A system exception occurred during an invocation on EJB BeanB method public void com.ivan.scbcd6.BeanB.methodB()
    javax.ejb.EJBException
    ...
    Caused by: java.lang.RuntimeException: run time exception from b
    ...

    Info: A transaction rollback ?false

    Info: Server shutdown initiated
    Info: pre destroy method called for Bean A.



    As we can see, the transaction of A is not marked for rollback. When I shut down the server, the @PreDestroy of Bean A is called.
     
    Himai Minh
    Ranch Hand
    Posts: 1361
    7
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator



    In this case, both bean A and B are discarded. @PreDestroy methods of both beans are not called when the container is shut down.

    A system exception occurred during an invocation on EJB BeanB method public void com.ivan.scbcd6.BeanB.methodB()
    javax.ejb.EJBException
    ....
    Caused by: java.lang.RuntimeException: run time exception from b
    ...

    Warning: A system exception occurred during an invocation on EJB BeanA method public void com.ivan.scbcd6.BeanA.methodA()
    javax.ejb.EJBException
    ....
    Caused by: java.lang.RuntimeException: run time exception from b
    ...

    Warning: StandardWrapperValve[OtherServlet]: PWC1406: Servlet.service() for servlet OtherServlet threw exception
    javax.ejb.EJBException
    ...
    Caused by: java.lang.RuntimeException: run time exception from b
    ...

     
    Himai Minh
    Ranch Hand
    Posts: 1361
    7
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    This time, bean B and Bean A's transaction attributes are both REQUIRED and Bean A catches Bean B's exception:




    A system exception occurred during an invocation on EJB BeanB method public void com.ivan.scbcd6.BeanB.methodB()
    javax.ejb.TransactionRolledbackLocalException: Exception thrown from bean
    ...
    Caused by: java.lang.RuntimeException: run time exception from b
    ...
    Info: A transaction rollback ?true
    Info : pre destroy method called for Bean A.



    The exception from bean B is wrapped by TransactionRolledBackLocalException and Bean B is discarded. But Bean A is not discarded.
     
    Himai Minh
    Ranch Hand
    Posts: 1361
    7
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Tried with bean A and B's transaction attributes are REQUIRED, but this time bean A does not catch the exception from bean B:

    A system exception occurred during an invocation on EJB BeanB method public void com.ivan.scbcd6.BeanB.methodB()
    javax.ejb.TransactionRolledbackLocalException: Exception thrown from bean
    ....
    Caused by: java.lang.RuntimeException: run time exception from b
    ....

    Warning: A system exception occurred during an invocation on EJB BeanA method public void com.ivan.scbcd6.BeanA.methodA()
    javax.ejb.EJBTransactionRolledbackException
    ....
    Caused by: javax.ejb.TransactionRolledbackLocalException: Exception thrown from bean
    ...
    Caused by: java.lang.RuntimeException: run time exception from b
    ...

    Warning: StandardWrapperValve[OtherServlet]: PWC1406: Servlet.service() for servlet OtherServlet threw exception
    javax.ejb.EJBTransactionRolledbackException
    ...
    Caused by: javax.ejb.TransactionRolledbackLocalException: Exception thrown from bean
    ...
    Caused by: java.lang.RuntimeException: run time exception from b
    ...




    Bean A got a EJBTransactionRollbackException that wraps the EJBTransactionRollbackLocalException, which wraps the runtime exception.
    When the EJB container is shut down, no @PreDestroy method is called. Bean A and B are discarded.
     
    With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
    • Post Reply
    • Bookmark Topic Watch Topic
    • New Topic