Announcement Announcement Module
Collapse
No announcement yet.
JPA ExceptionTranslation issue-Not Translating PersistenceException:unique constrait Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • JPA ExceptionTranslation issue-Not Translating PersistenceException:unique constrait

    I am using Spring 2.0.6 and OpenJPA 1.0.My Spring application context is configured to use the PersistenceExceptionTranslationPostProcessor and all DAO classes marked with the @Repository annotation.
    The issue I have is,
    I am trying to create a new Entity with a same field value as another Entity of the same type in the database, the field has a Unique Constraint on it.
    When i do entityManager.persist(entity) i only get a org.apache.openjpa.persistence.PersistenceExceptio n:ORA-00001 unique constrait violated..... and this exception is not translated to spring's DataAccessException.
    I was hoping it to be translated to the DataIntegrityViolated Exception.
    Though some other exceptions are successfully translated to Spring Exceptions I am not sure why the unique constraint violation is not translated.

    Is any one seeing similar issue or have any possible solutions ?
    Your help will be greatly appreciated.
    Last edited by addy999; Sep 20th, 2007, 12:36 PM.

  • #2
    There was an issue where the exception was wrapped with a BatchSQLException. This has been fixed in the 2.1 branch - could you try 2.1m4 and see if you see any change in behavior.

    Comment


    • #3
      Thanks for your reply trisberg.
      I tried with Spring 2.1M4 but get the same issue.

      Comment


      • #4
        Can you post a stacktrace (call printStackTrace on the exception you get)

        Comment


        • #5
          Actually, the translateExceptionIfPossible(RuntimeException ex) method of the PersistenceExceptionTranslator interface and implemented by the LocalContainerEntityManagerFactoryBean is not invoked at all for the exception below.
          My application context has the bean defined,
          <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerE ntityManagerFactoryBean">
          I would expect the PersistenceExceptionTranslationPostProcessor to invoke the translateExceptionIfPossible() method but it does not do it only for this exception.Other exceptions i get are translated through the translateExceptionIfPossible method.I tested this by extending the LocalContainerEntityManagerFactoryBean and overriding the translateExceptionIfPossible() method.While debugging, this method was not invoked at all for the exception below.
          If I manually catch the exception and invoke the EntityManagerFactoryUtils.convertJpaAccessExceptio nIfPossible(RuntimeException ex) then i get a JpaSystemException.
          So the 2 issues now are,
          1.Why i the persistence exception not translated at all ? That is the translateIfPossible() method is not invoked.
          2.When i translate the exception using the EntityManagerFactoryUtils.convertJpaAccessExceptio nIfPossible i get the JpaSystemException instead of some finegrained DataAccessException.


          Below is the Stack Trace,
          <openjpa-0.0.0-r420667:568756 fatal general error> org.apache.openjpa.persistence.PersistenceExceptio n: The transaction has been rolled back. See the nested exceptions for details on the errors that occurred.
          at org.apache.openjpa.kernel.BrokerImpl.newFlushExcep tion(BrokerImpl.java:2099)
          at org.apache.openjpa.kernel.BrokerImpl.flush(BrokerI mpl.java:1946)
          at org.apache.openjpa.kernel.BrokerImpl.flushSafe(Bro kerImpl.java:1844)
          at org.apache.openjpa.kernel.BrokerImpl.flush(BrokerI mpl.java:1615)
          at org.apache.openjpa.kernel.DelegatingBroker.flush(D elegatingBroker.java:973)
          at org.apache.openjpa.persistence.EntityManagerImpl.f lush(EntityManagerImpl.java:488)
          at sun.reflect.NativeMethodAccessorImpl.invoke0(Nativ e Method)
          at sun.reflect.NativeMethodAccessorImpl.invoke(Native MethodAccessorImpl.java:39)
          at sun.reflect.DelegatingMethodAccessorImpl.invoke(De legatingMethodAccessorImpl.java:25)
          at org.springframework.orm.jpa.SharedEntityManagerCre ator$SharedEntityManagerInvocationHandler.invoke(S haredEntityManagerCreator.java:193)
          at $Proxy30.flush(Unknown Source)
          at com.dao.DAOTest.testCreateEntity(DAOTest.java:90)
          at sun.reflect.NativeMethodAccessorImpl.invoke0(Nativ e Method)
          at sun.reflect.NativeMethodAccessorImpl.invoke(Native MethodAccessorImpl.java:39)
          at sun.reflect.DelegatingMethodAccessorImpl.invoke(De legatingMethodAccessorImpl.java:25)
          at org.springframework.test.ConditionalTestCase.runBa re(ConditionalTestCase.java:69)
          at org.springframework.test.annotation.AbstractAnnota tionAwareTransactionalTests.access$001(AbstractAnn otationAwareTransactionalTests.java:68)
          at org.springframework.test.annotation.AbstractAnnota tionAwareTransactionalTests$1.run(AbstractAnnotati onAwareTransactionalTests.java:138)
          at org.springframework.test.annotation.AbstractAnnota tionAwareTransactionalTests.runTest(AbstractAnnota tionAwareTransactionalTests.java:258)
          at org.springframework.test.annotation.AbstractAnnota tionAwareTransactionalTests.runTestTimed(AbstractA nnotationAwareTransactionalTests.java:230)
          at org.springframework.test.annotation.AbstractAnnota tionAwareTransactionalTests.runBare(AbstractAnnota tionAwareTransactionalTests.java:133)
          at org.springframework.test.jpa.AbstractJpaTests.runB are(AbstractJpaTests.java:174)
          at org.springframework.test.jpa.AbstractJpaTests.runB are(AbstractJpaTests.java:254)
          at com.intellij.rt.execution.junit.JUnitStarter.main( JUnitStarter.java:40)
          at sun.reflect.NativeMethodAccessorImpl.invoke0(Nativ e Method)
          at sun.reflect.NativeMethodAccessorImpl.invoke(Native MethodAccessorImpl.java:39)
          at sun.reflect.DelegatingMethodAccessorImpl.invoke(De legatingMethodAccessorImpl.java:25)
          at com.intellij.rt.execution.application.AppMain.main (AppMain.java:90)
          Caused by: <openjpa-0.0.0-r420667:568756 nonfatal general error> org.apache.openjpa.persistence.PersistenceExceptio n: ORA-00001: unique constraint (NAME_UNQ) violated
          {prepstmnt 28394800 INSERT INTO table (id, name, version) VALUES (?, ?, ?, ?) [params=(long) 190, (String) TestName, (int) 1]} [code=1, state=23000]

          at org.apache.openjpa.jdbc.sql.DBDictionary.newStoreE xception(DBDictionary.java:3847)
          at org.apache.openjpa.jdbc.sql.SQLExceptions.getStore (SQLExceptions.java:97)
          at org.apache.openjpa.jdbc.sql.SQLExceptions.getStore (SQLExceptions.java:67)
          at org.apache.openjpa.jdbc.kernel.PreparedStatementMa nagerImpl.flushInternal(PreparedStatementManagerIm pl.java:108)
          at org.apache.openjpa.jdbc.kernel.PreparedStatementMa nagerImpl.flush(PreparedStatementManagerImpl.java: 73)
          at org.apache.openjpa.jdbc.kernel.ConstraintUpdateMan ager.flush(ConstraintUpdateManager.java:543)
          at org.apache.openjpa.jdbc.kernel.ConstraintUpdateMan ager.flush(ConstraintUpdateManager.java:105)
          at org.apache.openjpa.jdbc.kernel.AbstractUpdateManag er.flush(AbstractUpdateManager.java:89)
          at org.apache.openjpa.jdbc.kernel.AbstractUpdateManag er.flush(AbstractUpdateManager.java:72)
          at org.apache.openjpa.jdbc.kernel.JDBCStoreManager.fl ush(JDBCStoreManager.java:514)
          at org.apache.openjpa.kernel.DelegatingStoreManager.f lush(DelegatingStoreManager.java:130)
          ... 45 more
          Caused by: org.apache.openjpa.lib.jdbc.ReportingSQLException: ORA-00001: unique constraint (MMS.DATA_SOURCE_NAME_UNQ) violated
          {prepstmnt 28394800 INSERT INTO data_source (id, last_updated_by, name, version) VALUES (?, ?, ?, ?) [params=(long) 190, (String) User1, (String) DataSource1, (int) 1]} [code=1, state=23000]
          at org.apache.openjpa.lib.jdbc.LoggingConnectionDecor ator.wrap(LoggingConnectionDecorator.java:192)
          at org.apache.openjpa.lib.jdbc.LoggingConnectionDecor ator.access$800(LoggingConnectionDecorator.java:57 )
          at org.apache.openjpa.lib.jdbc.LoggingConnectionDecor ator$LoggingConnection$LoggingPreparedStatement.ex ecuteUpdate(LoggingConnectionDecorator.java:858)
          at org.apache.openjpa.lib.jdbc.DelegatingPreparedStat ement.executeUpdate(DelegatingPreparedStatement.ja va:269)
          at org.apache.openjpa.jdbc.kernel.JDBCStoreManager$Ca ncelPreparedStatement.executeUpdate(JDBCStoreManag er.java:1363)
          at org.apache.openjpa.jdbc.kernel.PreparedStatementMa nagerImpl.flushInternal(PreparedStatementManagerIm pl.java:97)
          ... 52 more

          Thanks for looking into this.

          Comment


          • #6
            So the issue
            1.Why i the persistence exception not translated at all ? That is the translateIfPossible() method is not invoked.
            is resolved.I was hoping for the exception to be translated but i was flushing my persistent context in the TestCase method i created.If i call the dao.flush() and the dao has @Repository the exception is translated to a JPASystemException.
            The issue still pending is that why does not Spring translate
            org.apache.openjpa.lib.jdbc.ReportingSQLException: ORA-00001: unique constraint exceptions to some DataAccessException instead of the JPASystemException.

            Comment


            • #7
              Looks like you are getting an org.apache.openjpa.persistence.PersistenceExceptio n rather than an EntityExistsException from OpenJPA. If you got the latter it would have been translated to a DataIntegrityViolationException. So why is OpenJPA throwing the more general exception?

              Comment


              • #8
                Hi,

                From the description, it doesn't sound like this should be an EntityExistsException. Is there any more indication indicating that the unique constraint violation is due to a PK constraint violation, vs. some other sort of unique constraint?

                FWIW, org.apache.openjpa.persistence.PersistenceExceptio n extends javax.persistence.PersistenceException. Ideally, the Spring code should use translate all exceptions that are instanceof PersistenceException, no?

                Incidentally, OpenJPA has its own exception translation capabilities -- what would be the value of plugging a new SpringExceptionTranslator into OpenJPA when deployed appropriately?

                -Patrick

                Comment


                • #9
                  Patrick,

                  Re-reading the original description I believe you are correct, this is a unique constraint violation on a non id field. This type of issue doesn't have a specific JPA exception so a general PersistenceException is the closest fit.

                  In this case there isn't much we can do without looking at the wrapped SQLException. We aren't doing that since the exception translator doesn't know the underlying database and won't be able to interpret the error code. So the best we can do is to translate to a generic "unknown" type exception in the Spring exception hierarchy which is JpaSystemException.

                  Comment


                  • #10
                    Incidentally, OpenJPA has its own exception translation capabilities -- what would be the value of plugging a new SpringExceptionTranslator into OpenJPA when deployed appropriately?
                    Spring's exception translation sits on top of JPA at the DAO or Repository level and is optional. The benefit is that your service layer only have to deal with exceptions from a single exception hierarchy -- Spring's DataAccessException hierarchy -- regardless of the underlying data access technology. This is definitely valuable when you mix JDBC and ORM in the DAO layer.

                    Comment


                    • #11
                      Originally posted by trisberg View Post
                      Patrick,

                      Re-reading the original description I believe you are correct, this is a unique constraint violation on a non id field. This type of issue doesn't have a specific JPA exception so a general PersistenceException is the closest fit.

                      In this case there isn't much we can do without looking at the wrapped SQLException. We aren't doing that since the exception translator doesn't know the underlying database and won't be able to interpret the error code. So the best we can do is to translate to a generic "unknown" type exception in the Spring exception hierarchy which is JpaSystemException.
                      Hi,

                      If OpenJPA were throwing an org.apache.openjpa.persistence.ReferentialIntegrit yException instead of just a PersistenceException, would that change things?

                      -Patrick

                      Comment


                      • #12
                        Originally posted by trisberg View Post
                        Spring's exception translation sits on top of JPA at the DAO or Repository level and is optional. The benefit is that your service layer only have to deal with exceptions from a single exception hierarchy -- Spring's DataAccessException hierarchy -- regardless of the underlying data access technology. This is definitely valuable when you mix JDBC and ORM in the DAO layer.
                        Hi,

                        Yes, I understand the value of Spring's exception translation facilities. I'm wondering more about implementation details. Since OpenJPA already translates 100% of the exceptions thrown (including exceptions thrown from within lazy loading and such from direct access of persistent data in a managed instance), it would seem that we could do a more optimal integration between Spring and OpenJPA, such that OpenJPA translated exceptions directly from OpenJPA-internal types to Spring types, instead of the current OpenJPA-internal => JPA spec + extensions => Spring types.

                        Does that make sense?

                        -Patrick

                        Comment


                        • #13
                          Yes, I understand the value of Spring's exception translation facilities. I'm wondering more about implementation details. Since OpenJPA already translates 100% of the exceptions thrown (including exceptions thrown from within lazy loading and such from direct access of persistent data in a managed instance), it would seem that we could do a more optimal integration between Spring and OpenJPA, such that OpenJPA translated exceptions directly from OpenJPA-internal types to Spring types, instead of the current OpenJPA-internal => JPA spec + extensions => Spring types.
                          Yes, we could translate any OpenJPA specific exceptions in the OpenJpaDialect class. That would definitely be valuable.

                          If OpenJPA were throwing an org.apache.openjpa.persistence.ReferentialIntegrit yException instead of just a PersistenceException, would that change things?
                          That would work with the above scenario and we could translate that directly into a DataIntegrityViolationException.

                          Comment

                          Working...
                          X