[jboss-jira] [JBoss JIRA] (WFWIP-53) Differences in ORM exception handling in 5.1 vs 5.3

Martin Simka (JIRA) issues at jboss.org
Wed Jul 25 03:21:00 EDT 2018


    [ https://issues.jboss.org/browse/WFWIP-53?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13610166#comment-13610166 ] 

Martin Simka commented on WFWIP-53:
-----------------------------------

[~gbadner] Failures went down from 682 to 588 so it definitely helps. Remaining failures are mostly caused by changes in user types and by o.h.Transaction.begin throwing exception if transaction is already active. I'll let you know if I spot anything else related to exception handling. 

> Differences in ORM exception handling in 5.1 vs 5.3
> ---------------------------------------------------
>
>                 Key: WFWIP-53
>                 URL: https://issues.jboss.org/browse/WFWIP-53
>             Project: WildFly WIP
>          Issue Type: Bug
>          Components: JPA
>            Reporter: Martin Simka
>            Assignee: Gail Badner
>            Priority: Blocker
>
> I see tests failing because {{org.hibernate.hql.internal.ast.QuerySyntaxException}} is wrapped by {{java.lang.IllegalArgumentException}}. I know this has been discussed on hibernate-dev mailing list but without any outcome. 
> http://lists.jboss.org/pipermail/hibernate-dev/2018-May/017654.html
> {quote}
> I've been looking at differences in Hibernate exception handling for
> applications that uses "native" (non-JPA) Hibernate when moving from 5.1 to
> 5.3.
> As you know, exception handling changed in 5.2 when hibernate-entitymanager
> was merged into hibernate-core. This change is documented in the 5.2
> migration guide. [1]
> Here is the relevant text:
> "org.hibernate.HibernateException now extends
> javax.persistence.PersistenceExceptions.
> Hibernate methods that "override" methods from their JPA counterparts now
> will also throw various JDK defined RuntimeExceptions (such as
> IllegalArgumentException, IllegalStateException, etc) as required by the
> JPA contract."
> While digging into this, I see that a HibernateException thrown when using
> 5.1 may, in 5.3, be unwrapped, or may be wrapped by a PersistenceException
> (or a subclass), IllegalArgumentException, or IllegalStateException,
> depending on the particular operation being performed when the
> HibernateException is thrown.
> The reason why the exceptions may be wrapped or unwrapped is because
> Hibernate converts exceptions  (via
> AbstractSharedSessionContract#exceptionConverter)
> for JPA operations which may wrap the HibernateException or throw a
> different exception. Hibernate does not convert exceptions from strictly
> "native" operations, so those exceptions remain unwrapped.
> Here are a couple of examples to illustrate:
> 1) A HibernateException (org.hibernate.TransientObjectException) was thrown
> in 5.1. In 5.3, the same condition can result in
> org.hibernate.TransientObjectException
> that is either unwrapped, or wrapped by IllegalStateException. I've pushed
> a test to my fork to illustrate. [2]
> Thrown during Session#save, #saveOrUpdate
> In 5.1: org.hibernate.TransientObjectException (unwrapped)
> In 5.3: org.hibernate.TransientObjectException (unwrapped)
> Thrown during Session#persist, #merge, #flush
> In 5.1, org.hibernate.TransientObjectException (unwrapped)
> In 5.3, org.hibernate.TransientObjectException wrapped by
> IllegalStateException
> 2) A HibernateException thrown when using 5.1 may be wrapped by a
> PersistenceException, even though HibernateException already extends
> PersistenceException.
> For example, see TransactionTimeoutTest#testTransactionTimeoutFailure:
> https://github.com/hibernate/hibernate-orm/blob/master/
> hibernate-core/src/test/java/org/hibernate/test/tm/
> TransactionTimeoutTest.java#L60-L82
> The exception thrown by the test indicates that the transaction timed out.
> This exception is important enough that an application might retry the
> operation, or at least log for future investigation.
> Thrown during Session#persist (or when changed to use Session#merge or
> Session#flush):
> In 5.1: org.hibernate.TransactionException (unwrapped)
> In 5.3: org.hibernate.TransactionException wrapped by javax.persistence.
> PersistenceException
> Thrown if the test is changed to use Session#save or #saveOrUpdate instead:
> In 5.1: org.hibernate.TransactionException (unwrapped)
> In 5.3: org.hibernate.TransactionException (unwrapped)
> Similarly, by adding some logging, I see that HibernateException objects
> can be wrapped by PersistenceException when running the 5.3 hibernate-core
> unit tests. Depending on the context, I see that some of the following
> exceptions can be wrapped or unwrapped.
> org.hibernate.exception.ConstraintViolationException
> org.hibernate.exception.DataException
> org.hibernate.exception.GenericJDBCException
> org.hibernate.exception.SQLGrammarException
> org.hibernate.id.IdentifierGenerationException
> org.hibernate.loader.custom.NonUniqueDiscoveredSqlAliasException
> org.hibernate.PersistentObjectException
> org.hibernate.PropertyAccessException
> org.hibernate.PropertyValueException
> org.hibernate.TransactionException
> You can see an example using
> org.hibernate.exception.ConstraintViolationException
> at [3].
> In order to deal with these differences, an application could change the
> following (which was appropriate for 5.1):
> try {
>     ...
> }
> catch (HibernateException ex) {
>     procressHibernateException( ex );
> }
> to the following for 5.3:
> try {
>     ...
> }
> catch (PersistenceException | IllegalStateException |
> IllegalArgumentException ex) {
>     if ( HibernateException.class.isInstance( ex ) ) {
>         handleHibernateException( (HibernateException) ex );
>     }
>     else if ( HibernateException.class.isInstance( ex.getCause() ) ) {
>         handleHibernateException( (HibernateException) ex.getCause() );
>     }
> }
> IMO, it's a little clumsy having to deal with both wrapped and unwrapped
> exceptions. It would be better if exceptions were consistently wrapped, or
> consistently unwrapped.
> I haven't had much of a chance to think about how we can deal with this,
> but one thing that comes to mind is to allow an application to choose a
> particular ExceptionConverter implementation. Hibernate would need to be
> changed to always convert exceptions (including for strictly native
> operations) before returning to the application.
> For example, a property, hibernate.exception_converter could be added with
> the following values:
> jpa - default for JPA applications (org.hibernate.internal.
> ExceptionConverterImpl)
> native (or legacy?) - default for native applications  that does not wrap
> HibernateException
> fully-qualified class name that implements ExceptionConverter
> If users have to make changes to exception handling for 5.3, do you think
> they would be willing to change their application to use JPA exceptions
> (i.e., hibernate.exception_converter=jpa)?
> Comments?
> Regards,
> Gail
> [1] https://github.com/hibernate/hibernate-orm/blob/5.2/migration-guide.adoc
> [2] https://github.com/gbadner/hibernate-core/blob/exception-
> compatibility/orm/hibernate-orm-5/src/test/java/org/hibernate/bugs/
> ORMTransientObjectExceptionUnitTestCase.java
> [3] https://github.com/gbadner/hibernate-core/blob/exception-
> compatibility/orm/hibernate-orm-5/src/test/java/org/hibernate/bugs/
> ORMConstraintViolationExceptionUnitTestCase.java
> {quote}



--
This message was sent by Atlassian JIRA
(v7.5.0#75005)


More information about the jboss-jira mailing list