7 Replies Latest reply on Nov 24, 2007 4:59 AM by pmuir

    Exception handling of PersistenceException

    dapeng

      Hi,

      Hibernate executes the statements only on flushing, which is most of the time at the end of a tx. It means, any database related exception (foreign key constraint or unique constraint etc.) will be thrown in a deferred fashion(not at the time of invocation, but at the time of tx commitment). At the end of the 5 and 6 JSF phases, a TransactionRolledBackException is thrown, when all action methods have been executed. There is no chance to catch such kind of ConstraintException in service layer or in JSF actions.

      What is the best-practice for handling these exceptions?

      The normal behaviour I excpeted from the system is to add a faces message and stay on the same view. I think the only guy who can do this job is a ExceptionHandler. First question is why not allow to add user defined ExceptionHandler? Second question is: Can I use any of the existing handler to implement the desired behaviour? In the documentation I only see examples which redirects to another view. Is there a shortcut (EL-expression) to find out the current view and use it as thre redirection target? If not, I would like to implement it. My plan is to use a PhaseListener to catch the current view and put it somewhere (request attribute or thread locale, anyway, anywhere reachable by a EL-expression) for later use and configure in the pages.xml

      <exception class="javax.persistence.PersistenceException">
      <end-conversation/>
      <redirect view-id="{el-expression-to-the-current-view}">
      <message>Database access failed</message>
      </redirect>
      </exception>
      

      I would like to know your opinions to the solution. Whether you have better suggestion or see general problems

      thx for your feedback!



        • 1. Re: Exception handling of PersistenceException
          pmuir

          Normally flush occurs when flush() is explicitly called or at container-called-method boundaries.

          What do you want to do in your user defined exception handler?
          You can also stay on the current view by omitting the redirect element.

          • 2. Re: Exception handling of PersistenceException
            dapeng

            Hi, Pete,


            I've got the following case. A method (no conversation) will be called to delete a row in the database. The backing bean method returns without error, because the flush is not occured at this time. Later the SeamPhaseListener commits the first tx, which flushes the persistence context. During the flush a ConstraintViolationException is thrown because of a foreign key constraint exception. But my application code has no chance to catch this exception, because the backing bean method has finished already.

            The only possibility is to write a complex error handling, which is able to do something after the tx commit. I have 2 problems here.
            1. Currently SpringTransaction swallows the cause exception, so that I can't find the ConstraintViolationException in the exception stack. I will switch to another trnasaction manager and sees whether it is cleaner.
            2. The exception handling mechanism doesn't allow me to hook in user defined exception handler, so that I can check the exception stack, so some logic. I think the redirect, end-conversation and http error are not enoughj under all circumstances.

            Like to know your opinion.

            Dapeng

            • 3. Re: Exception handling of PersistenceException
              pmuir

              AFAIK (though I see some Spring stuff in there so I'm no longer sure) that a tx commit doesn't cause the PC to be flushed. As I've mentioned to you on another thread the flush occurs when you manually call flush() - which you may do or at container invoked method boundaries.

              • 4. Re: Exception handling of PersistenceException
                dapeng

                The default flush mode of hibernate persistence context is transaction, which means a flush will occur
                1) when flush is called manually
                2) when tx commits
                3) when a query must be executed, which may require a flush

                For conversation I chose to manually flush the session, so that I can also catch the exception. But for actions with other scopes (e.g. request), I prefer to use the default flush mode, which occurs at tx commit. I am looking for a solutions for this situation. Here the tx commit is called in the SeamPhaseListener, which is too late for any application method to react.

                • 5. Re: Exception handling of PersistenceException
                  pmuir

                  So you are using a Session? Not JPA? You need to enumerate your config if you are off the standard EJB3-with-Seam when you start your posts

                  • 6. Re: Exception handling of PersistenceException
                    dapeng

                    I am using Seam in JSF layer + tx (SeamPhaseListener) and Persistence context management. Spring in the middle layer. and JPA for persistence.

                    My problem is:
                    new JSF request, seam starts tx, jsf layer calls spring, which calls JPA daos. Jpa dao executes several statements, the call returns and JSF lifecycle finishes phase 5. SeamPhaseListener commits tx, which causes persistence context to flush (all pending statements collected before). During the flush, some DB error occurs (unique constraint or foreign key constraint). Upon the flush error, tx rollbacks, but my code are already executed at this time (after action method return). I've got no chance to handle the exception besides using a ExceptionHandler.

                    Better idea there?

                    • 7. Re: Exception handling of PersistenceException
                      pmuir

                      Explicitly flush the PC in the INVOKE APPLICATION and catch the exceptions there.