1 2 Previous Next 20 Replies Latest reply on Jan 19, 2006 8:22 AM by Francesco Persico

    JBoss 4.0.3 - EJB 3.0 - Exception caused by UNIQUE constrain

    jonefun Newbie

      Problem while attempting to persist data that violates UNIQUE key constrainst.

      Exeption is being caught by [JDBCExceptionReporter] but is not being thrown. My Stateless session been is therefore completely unaware of any problem, however my web app handles the EntityBean in disconnected mode catches a RuntimeException

      JBoss throws a "java.lang.RuntimeException" and so my

      >>>> Exception in JBOSS is :---------------------------------------------------------------

      16:33:20,351 WARN [JDBCExceptionReporter] SQL Error: 335544665, SQLState: HY000
      16:33:20,351 ERROR [JDBCExceptionReporter] GDS Exception. 335544665. violation of PRIMARY or UNIQUE KEY constraint "INTEG_11907" on table "PERSON"
      16:33:20,351 ERROR [AbstractFlushingEventListener] Could not synchronize database state with session
      org.hibernate.exception.GenericJDBCException: could not insert: [com.onlineshop.entity.bean.Person]
      at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:91)
      .....
      Caused by: org.firebirdsql.jdbc.FBSQLException: GDS Exception. 335544665. violation of PRIMARY or UNIQUE KEY constraint "INTEG_11907" on table "PERSON"
      at org.firebirdsql.jdbc.AbstractPreparedStatement.internalExecute(AbstractPreparedStatement.java:503)
      ... 33 more

      >>>> Exception in WEB APP is :---------------------------------------------------------------

      WHACKO : Error : java.lang.RuntimeException: org.jboss.tm.JBossRollbackException: Unable to commit, tx=TransactionImpl:XidImpl[FormatId=257, GlobalId=tron/47, BranchQual=, localId=47] status=STATUS_NO_TRANSACTION; - nested throwable: (org.hibernate.exception.GenericJDBCException: could not insert: [com.onlineshop.entity.bean.Person])
      java.lang.RuntimeException: org.jboss.tm.JBossRollbackException: Unable to commit, tx=TransactionImpl:XidImpl[FormatId=257, GlobalId=tron/47, BranchQual=, localId=47] status=STATUS_NO_TRANSACTION; - nested throwable: (org.hibernate.exception.GenericJDBCException: could not insert: [com.onlineshop.entity.bean.Person])
      at org.jboss.aspects.tx.TxPolicy.handleEndTransactionException(TxPolicy.java:185)
      ....
      Caused by: org.jboss.tm.JBossRollbackException: Unable to commit, tx=TransactionImpl:XidImpl[FormatId=257, GlobalId=tron/47, BranchQual=, localId=47] status=STATUS_NO_TRANSACTION; - nested throwable: (org.hibernate.exception.GenericJDBCException: could not insert: [com.onlineshop.entity.bean.Person])
      at org.jboss.tm.TransactionImpl.commit(TransactionImpl.java:354)
      ... 19 more
      Caused by: org.hibernate.exception.GenericJDBCException: could not insert: [com.onlineshop.entity.bean.Person]
      at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:91)
      .....
      ... 20 more
      Caused by: org.firebirdsql.jdbc.FBSQLException: GDS Exception. 335544665. violation of PRIMARY or UNIQUE KEY constraint "INTEG_11907" on table "PERSON"
      at org.firebirdsql.jdbc.AbstractPreparedStatement.internalExecute(AbstractPreparedStatement.java:503)
      ... 33 more

      If anybody can help me understand why no exception is being thrown I would be very grateful. Is this a bug with Firebird JCA JDBC Resource Adapter or is it a problem with JBoss / Hibernate .. or is it just me expecting something that I shouldn't be expecting.

      Thanks for reading this far :)

      Jono

        • 1. Re: JBoss 4.0.3 - EJB 3.0 - Exception caused by UNIQUE const
          jonefun Newbie

          Firstly a bit of background I have a Person entity that has a email property. The email property is marked as Unique to force an exception if two users attempt to register with the same email address.

          I have a tiered architecture with my presentation layer running on a web server (Tomcat) and my business layer running on another server on JBoss. I do not want to expose my web services layer to any underlying EJB 3.0 or JBoss specific technologies and this includes underlying JDBC exceptions. I would prefer to catch the exception in the business layer and throw a nice shiny business exception, like PersonAlreadyExistsException.

          I have read the section on Hibernate Exceptions and it states that an exception will be categories into one of four types with the least specific exception being GenericJDBCException. However I would expect that my SLSB catches this exception and not my Struts Action classes in my presentation tier.

          Please can someone comment on this as it is very easy to replicate and surely other users must be having the same problem.

          Any Hibernate / JBoss gurus reading this ???????

          Thanks in advance

          Jono

          • 2. Re: JBoss 4.0.3 - EJB 3.0 - Exception caused by UNIQUE const
            Scott Stark Master

            Moved to ejb3 forum. Try providing enough info to reproduce the issue.

            • 3. Re: JBoss 4.0.3 - EJB 3.0 - Exception caused by UNIQUE const
              jonefun Newbie

              To reproduce the problem define an Entity bean and define one if the field as unique example :-

              @Column(unique=true, length=50)
              public String getEmail()
              {
              return email;
              }

              then in a stateless session bean that has a "createPerson" method wich accepts the Person entity bean as a parameter and persists it like :-

              public void createPerson( Person person )
              throws CreateException
              {
              logger.debug( "Creating new Person : " + person );

              try
              {
              manager.persist( person );
              }
              catch( Exception e )
              {
              logger.error( "Exception occurred : " + e );

              e.printStackTrace();
              }
              }

              Then create a client that simply defines two Person objects with the same email address. The first call should work ok but the second call fails. The problem is that the SLSB does not catch the exception the client however catches a Runtime exception.

              The way I see it the SLSB should catch the Hibernate exception and wrap it up in a nice business exception for the client such as PeronAlreadyExistsException.

              Thanks for any help

              Jono

              • 4. Re: JBoss 4.0.3 - EJB 3.0 - Exception caused by UNIQUE const
                Emmanuel Bernard Master

                the actual insert is done when the Tx is commited
                execute a flush explicity in your code to catch this exception

                • 5. Re: JBoss 4.0.3 - EJB 3.0 - Exception caused by UNIQUE const
                  jonefun Newbie

                  Tried that ... still makes no difference .. my struts action class still gets a RuntimeException and the SLSB try/catch block gets nothing.

                  It looks to me like the flush is happening on a different thread detached from my slsb thread and that my slsb does not wait for successful flush before it terminates .. and this including an explicit call to EntityManager.persist.

                  • 6. Re: JBoss 4.0.3 - EJB 3.0 - Exception caused by UNIQUE const
                    jonefun Newbie

                    EntityManager.flush that should have read ...

                    forgive me it's Fri night here and I got my party pants on :)

                    • 7. Re: JBoss 4.0.3 - EJB 3.0 - Exception caused by UNIQUE const
                      jonefun Newbie

                      Went over it again with sensible head on and the flush() does indeed generate the much needed exception :)

                      Thanks for your help

                      • 8. Re: JBoss 4.0.3 - EJB 3.0 - Exception caused by UNIQUE const
                        jonefun Newbie

                        Seems that even though I can catch the underlying JDBC exception in my SLSB (when I manually flush the EntityManager) any attempts to throw a more meaningful exception fail (by fail I mean that my web application never receives it. My web application still receives the TransactionRollBack Runtime exception that is generated by the JBoss AOP Flush Interceptor.

                        So it apears that calling the flush() manually makes no difference after all.

                        I have a workaround which is to just catch the Runtime exeption and dig down into the root cause but it still means that my presentation layer is exposed to database related exceptions which just feels wrong.

                        • 9. Re: JBoss 4.0.3 - EJB 3.0 - Exception caused by UNIQUE const
                          Emmanuel Bernard Master

                          your exception is a checked one right?
                          If so try to setRollbackOnly the transaction.

                          I thnik, the app server try to redo a flush()

                          • 10. Re: JBoss 4.0.3 - EJB 3.0 - Exception caused by UNIQUE const
                            jonefun Newbie

                            Yes my exception is a checked exception based on violation of unique key constraint.

                            I tried "setRollBackOnly()" on the SessionContext but I still get the following error in my client class :-

                            WHACKO : Error : java.lang.RuntimeException: org.jboss.tm.JBossRollbackException: Unable to commit, tx=TransactionImpl:XidImpl[FormatId=257, GlobalId=tron/16, BranchQual=, localId=16] status=STATUS_NO_TRANSACTION; - nested throwable: (org.hibernate.exception.GenericJDBCException: could not insert: [com.onlineshop.entity.bean.Person])
                            Root Cause : Unable to commit, tx=TransactionImpl:XidImpl[FormatId=257, GlobalId=tron/16, BranchQual=, localId=16] status=STATUS_NO_TRANSACTION; - nested throwable: (org.hibernate.exception.GenericJDBCException: could not insert: [com.onlineshop.entity.bean.Person])
                            Jdbc Cause : could not insert: [com.onlineshop.entity.bean.Person]
                            


                            It seems to me that the flush is being intercepted by the JBoss flush interceptor aspect and any exceptions raised during that flush are thrown by the Aspect as a RuntimeException. I have tried catching this exception in my SLSB by doing a manual flush but in either case it is always my client that receives the above error.

                            I think that if the Aspect catches an Exception during the flush it should raise an exception (passing it to the SLSB) and let the SLSB deal with it as a checked exception and not a runtime exception which is what is currently happening.

                            I placed a Unique constraint on the email address field for the express purpose of being able to deal with a checked exception. However this doesn;t seem to be happening in this case.

                            Cheers

                            Jono

                            • 11. Re: JBoss 4.0.3 - EJB 3.0 - Exception caused by UNIQUE const
                              Denny Bartelt Newbie

                              I've got the same problem. I want to catch a ConstrainVoilationException within a session bean. Is there any solution meanwhile?

                              • 12. Re: JBoss 4.0.3 - EJB 3.0 - Exception caused by UNIQUE const
                                Bosquet Charles Newbie

                                Do you try to annotate your checked exception class with : @ApplicationException(rollback=true/false) ?

                                Charles

                                • 13. Re: JBoss 4.0.3 - EJB 3.0 - Exception caused by UNIQUE const
                                  jonefun Newbie

                                  I understand why you ask this but the problem is not that my Exception is not causing the transaction to roll back. I have read other threads on exceptions and they have a slightly different problem that when they raise a checked exception the transaction is still committed. In which case I agree that annotating the exception as you describe will correct the problem.

                                  This case is that the flush interceptor is catching the checked exception and always raising a RuntimeException.

                                  Ideally we would want to catch all exceptions related to the persistence layer inside our session bean. Then present more meaningful exceptions to the session bean caller.

                                  I think the problem hear lies in the AOP implementation that intercepts and calls to flush either directly or indirectly and then it (using injected classes) instigates the flush activity and also catches any exceptions on behalf of our session bean. It then raises the exception *always* as a RuntimeException which is being caught by the sessoin bean client. In my case this is a struts action class.

                                  Can anyone comment on the Flush intereceptor how it functions and why it always raises RuntimeExceptions ?

                                  • 14. Re: JBoss 4.0.3 - EJB 3.0 - Exception caused by UNIQUE const
                                    jonefun Newbie

                                     


                                    I've got the same problem. I want to catch a ConstrainVoilationException within a session bean. Is there any solution meanwhile?


                                    Unfortunately the only solution I have so far is to deal with the exception in my calling class and not my session bean class.

                                    In my client class i unravel the exception extracting the nested cause until I get to the root cause. There I see the underlying database exception and I can see the constraint violation.

                                    However I suspect that like myself you do not want to expose database related exception handling in your client code. So far I do not have a way of handling this error in the session bean where it belongs.

                                    Note: I have tried manually flushing the transaction in the session bean and this does cause an exception in the session bean but it does not prevent the RuntimeException from occurring inside the JBOSS AOP Interceptor thread. Also when I throw a checked exception inside my session bean but my client code only receives the RuntimeException detailed earlier.

                                    1 2 Previous Next