7 Replies Latest reply on Dec 18, 2012 4:35 AM by jmartisk

    Unable to catch RuntimeException in client EJB

    bibhu

      Hi,

       

      I want to throw a runtime exception from my dao layer ,and catch it in service layer to parse the exception and show a meaningful message to user.

      But, when I do this , EJB wraps this exception with RolledBackException and the client EJB is not able to catch it as it expects a SecurityBreakException  which extends RuntimeException.

       

      I can't throw a checked exception from the class as it implements HibernateListenrs.

       

      Adding sample code snippet for more clarity:

       

       

      // after every save/update/delete the follwing class get triggered

       

      public class DataChangeListener implements PostDeleteEventListener, PostUpdateEventListener, PostInsertEventListener, Initializable {

      public void onPostInsert(final PostInsertEvent event) {

      //check  if the user is not allowed to do so ,throw a SecurityBreakException

      // else do nothing and let the transaction commit.

      }

      public void onPostUpdate(PostUpdateEvent event) {

      //same as onPostInsert

      }

      public void onPostDelete(PostDeleteEvent event) {

      //same as onPostInsert

      }

       

       

      @Local public interface SaveUserDataService{

      public void save(Person person);

      }

       

      //client EJB which expects a SecurityBreakException

      @Stateful SaveUserDataServiceBean implements SaveUserDataService{

      public void save(Person person){

      try{ //code to call dao layer to save a person

      } catch (SecurityBreakException e) {

      // parse the exception and show a meaningful message to user

                }

            }

      }

       

       

      //The exception class

      public class SecurityBreakException extends RuntimeException {

      private static final long serialVersionUID = 1L;

      String message;

      public SecurityBreakException(String message) {

      super(message); this.message = message;

            }

      }

       

      Please guide.

        • 1. Re: Unable to catch RuntimeException in client EJB
          take-4c-ktym

          Hi,

           

          Had you already solved this problem ?

           

          I have a question.
          Though SecurityBreakException extends RuntimeException,
          the design is proper ?

           

          I think that RuntimeException is categorized in system exception
          and it is generally in the case that there is no proper implementation even if catching it.
          Ex) NullPointerException, ArrayOutOfBoundsException, etc

           

          So, how about stopping the way that SecurityBreakException extends RuntimeException ?

          • 2. Re: Unable to catch RuntimeException in client EJB
            bibhu

            Hi Katayama,

            sorry for my late reply.

            No, the problem is not solved yet.
            I think the design is correct.We can't throw a checked exception from the method  public void onPostInsert(final PostInsertEvent event) ..

            So, I am bound to make SecurityBreakException extend RuntimeException.

            • 3. Re: Unable to catch RuntimeException in client EJB
              jmartisk

              I guess you cannot work around the fact that the exception will be wrapped. But you still can try to catch the wrapper exception and inspect it to see if the exception inside is your SecurityBreakException, can't you?

               

              catch (EJBTransactionRolledbackException e) {
                  if(e.getCause() instanceof SecurityBreakException) {
                      SecurityBreakException ex = (SecurityBreakException)e.getCause();
                      // parse the exception and show a meaningful message to user    
                  }
              }
              
              • 4. Re: Unable to catch RuntimeException in client EJB
                bibhu

                Hi Jan,


                First of all thanks for your answer.
                Catching the EJBTransactionRolledbackException will help to show a meaningful message to user.
                But handling a generice exception like  EJBTransactionRolledbackException might not be a good idea. It may eat the exceptions where I dont want this scenario and distrurb everything.

                • 5. Re: Unable to catch RuntimeException in client EJB
                  jmartisk

                  In that case you can just rethrow the EJBTransactionRolledbackException so you don't lose it..

                   

                  catch (EJBTransactionRolledbackException e) {
                      if(e.getCause() instanceof SecurityBreakException) {
                          SecurityBreakException ex = (SecurityBreakException)e.getCause();
                          // parse the exception and show a meaningful message to user    
                      } else 
                  
                          throw e;
                  }
                  
                  
                  • 6. Re: Unable to catch RuntimeException in client EJB
                    bibhu

                    As per your suggestion,I tried catching the EJBTransactionRolledbackException,but no luck.
                    The exception is thrown out side of the try() block i.e.exception is thrown after the execution of this method.

                     

                    Below is my understanding on why it is not able to catch .let me know if doesn't make any sense.

                     

                    I am using EJB with Seam on server side and GWT (dont bother ;just a GUI tehnology like JSF)on client side.

                    @Local public interface SaveUserDataService{

                    public void save(Person person);

                    }

                     

                    //client EJB which expects a SecurityBreakException

                    @Stateful SaveUserDataServiceBean implements SaveUserDataService{

                    public void save(Person person){

                    try{ //code to call dao layer to save a person

                    } catch (SecurityBreakException e) {

                    // parse the exception and show a meaningful message to user

                              }

                          }

                    }

                     

                    When user clicks on save button , the request comes to save() method of SaveUserDataServiceBean which  is the boundary ejb .

                    Transaction begins when the call stack starts and commits when the call stack ends.Call stack is basically the stack of methods consists of all the methods starting from the boundary method (root of the stack ie "save(Person person) ") till the last call to DAO ;basically all nested method calls.

                     

                    So, container commits/rolls back the transaction when the stack ends i.e. the boundary method completes execution, and DataChangeListener is triggered just before the commit.

                     

                    Thanks

                    Bibhu

                    • 7. Re: Unable to catch RuntimeException in client EJB
                      jmartisk

                      Oh yeah, I kind of thought so.. I guess you can't catch the exception if it goes from the onPostInsert callback, because that metod is called asynchronously to any of your other invocations - after you finish your EJB call.

                      I guess you can either

                      - try to throw the exception earlier than during commit, for example right from the "save" method?

                      - use bean-managed transactions and try to do the commit yourself in the end of the "save" method - and if the commit fails, you can parse the exception from it.