You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@openjpa.apache.org by Pinaki Poddar <pp...@apache.org> on 2008/05/28 22:57:58 UTC

Exception translation by EntityManager facade

Hi,
  Currently, EntityManager facade translates exceptions raised by kernel
using a RuntimeExceptionTranslator that passes through any exception whose
class name starts with "org.apache.openjpa.persistence."

  This policy, thereby, produces user-visible exceptions that are not
*strictly* what JPA spec says (though loosely they are, because many of
these pass-through OpenJPA-specific exceptions inherit from their
JPA-defined counterparts). Does spec say something about the exact runtime
type of raised exception by EntityManager methods, for example, will a
subclass be spec-compliant? 
  
  I don't seem to locate any statements w.r.t. above question.

  Regards --

Pinaki     
-- 
View this message in context: http://www.nabble.com/Exception-translation-by-EntityManager-facade-tp17521307p17521307.html
Sent from the OpenJPA Developers mailing list archive at Nabble.com.


Re: Exception translation by EntityManager facade

Posted by Pinaki Poddar <pp...@apache.org>.
Hi,
Thanks everybody. I am now convinced, from the fundamental OO principles
cited by Craig, that subtypes of JPA-exceptions are acceptable.

Did any of you get a chance to review/comment on the heuristic I had used to
translate internal OpenJPA exception to user-visible exception (the patch is
available in this same thread)?

Regards --
 

-- 
View this message in context: http://www.nabble.com/Exception-translation-by-EntityManager-facade-tp17521307p17548523.html
Sent from the OpenJPA Developers mailing list archive at Nabble.com.


Re: Exception translation by EntityManager facade

Posted by Craig L Russell <Cr...@Sun.COM>.
I agree that subtypes are compliant.

In OO programming terms, strictly speaking, an instance of a subclass  
of TransactionRequiredException *is* an instance of  
TransactionRequiredException. The instance of the subclass passes the  
"instanceof" and the .isInstance() tests.

If this were not the intent of the specification, then I guess that  
TransactionRequiredException would have been marked "final".

Craig

On May 28, 2008, at 6:47 PM, Patrick Linskey wrote:

> I believe that subtypes are compliant.
>
> -Patrick
>
> On May 29, 2008, at 6:57 AM, Pinaki Poddar wrote:
>
>>
>> Hi,
>> Currently, EntityManager facade translates exceptions raised by  
>> kernel
>> using a RuntimeExceptionTranslator that passes through any  
>> exception whose
>> class name starts with "org.apache.openjpa.persistence."
>>
>> This policy, thereby, produces user-visible exceptions that are not
>> *strictly* what JPA spec says (though loosely they are, because  
>> many of
>> these pass-through OpenJPA-specific exceptions inherit from their
>> JPA-defined counterparts). Does spec say something about the exact  
>> runtime
>> type of raised exception by EntityManager methods, for example,  
>> will a
>> subclass be spec-compliant?
>>
>> I don't seem to locate any statements w.r.t. above question.
>>
>> Regards --
>>
>> Pinaki
>> -- 
>> View this message in context: http://www.nabble.com/Exception-translation-by-EntityManager-facade-tp17521307p17521307.html
>> Sent from the OpenJPA Developers mailing list archive at Nabble.com.
>>
>
> -- 
> Patrick Linskey
> 202 669 5907
>

Craig Russell
Architect, Sun Java Enterprise System http://java.sun.com/products/jdo
408 276-5638 mailto:Craig.Russell@sun.com
P.S. A good JDO? O, Gasp!


Re: Exception translation by EntityManager facade

Posted by Michael Dick <mi...@apache.org>.
+1 to Patrick and Kevin's remarks. Subclasses are fine since the application
can catch the parent class.

-mike

On Thu, May 29, 2008 at 8:16 AM, Kevin Sutter <kw...@gmail.com> wrote:

> I couldn't find an exact reference in the spec either that states that
> exception subtypes are allowed.  But, JPA sort of sets a precedence with
> the
> PersistenceException.  Here's the javadoc for the persist() method:
>
> /**
> * Make an instance managed and persistent.
> * @param entity
> * @throws EntityExistsException if the entity already exists.
> * (The EntityExistsException may be thrown when the persist
> * operation is invoked, or the EntityExistsException or
> * another PersistenceException may be thrown at flush or
> * commit time.)
> * @throws IllegalArgumentException if not an entity
> * @throws TransactionRequiredException if invoked on a
> * container-managed entity manager of type
> * PersistenceContextType.TRANSACTION and there is
> * no transaction.
> */
> public void persist(Object entity);
>
> This indicates that it's okay for a Persistence Provider to throw either
> EntityExistsException or another PersistenceException at flush or commit
> time.  It would seem that it's acceptable to throw a subtype of
> PersistenceException, so why wouldn't it follow that it's acceptable to
> throw a subtype of EntityExistsException?  As long as the catch clause
> still
> catches the exception, I don't see why subtypes wouldn't be accepted.
>
> Kevin
>
>
> On Wed, May 28, 2008 at 8:47 PM, Patrick Linskey <pl...@gmail.com>
> wrote:
>
> > I believe that subtypes are compliant.
> >
> > -Patrick
> >
> >
> > On May 29, 2008, at 6:57 AM, Pinaki Poddar wrote:
> >
> >
> >> Hi,
> >>  Currently, EntityManager facade translates exceptions raised by kernel
> >> using a RuntimeExceptionTranslator that passes through any exception
> whose
> >> class name starts with "org.apache.openjpa.persistence."
> >>
> >>  This policy, thereby, produces user-visible exceptions that are not
> >> *strictly* what JPA spec says (though loosely they are, because many of
> >> these pass-through OpenJPA-specific exceptions inherit from their
> >> JPA-defined counterparts). Does spec say something about the exact
> runtime
> >> type of raised exception by EntityManager methods, for example, will a
> >> subclass be spec-compliant?
> >>
> >>  I don't seem to locate any statements w.r.t. above question.
> >>
> >>  Regards --
> >>
> >> Pinaki
> >> --
> >> View this message in context:
> >>
> http://www.nabble.com/Exception-translation-by-EntityManager-facade-tp17521307p17521307.html
> >> Sent from the OpenJPA Developers mailing list archive at Nabble.com.
> >>
> >>
> > --
> > Patrick Linskey
> > 202 669 5907
> >
> >
>

Re: Exception translation by EntityManager facade

Posted by Kevin Sutter <kw...@gmail.com>.
I couldn't find an exact reference in the spec either that states that
exception subtypes are allowed.  But, JPA sort of sets a precedence with the
PersistenceException.  Here's the javadoc for the persist() method:

/**
* Make an instance managed and persistent.
* @param entity
* @throws EntityExistsException if the entity already exists.
* (The EntityExistsException may be thrown when the persist
* operation is invoked, or the EntityExistsException or
* another PersistenceException may be thrown at flush or
* commit time.)
* @throws IllegalArgumentException if not an entity
* @throws TransactionRequiredException if invoked on a
* container-managed entity manager of type
* PersistenceContextType.TRANSACTION and there is
* no transaction.
*/
public void persist(Object entity);

This indicates that it's okay for a Persistence Provider to throw either
EntityExistsException or another PersistenceException at flush or commit
time.  It would seem that it's acceptable to throw a subtype of
PersistenceException, so why wouldn't it follow that it's acceptable to
throw a subtype of EntityExistsException?  As long as the catch clause still
catches the exception, I don't see why subtypes wouldn't be accepted.

Kevin


On Wed, May 28, 2008 at 8:47 PM, Patrick Linskey <pl...@gmail.com> wrote:

> I believe that subtypes are compliant.
>
> -Patrick
>
>
> On May 29, 2008, at 6:57 AM, Pinaki Poddar wrote:
>
>
>> Hi,
>>  Currently, EntityManager facade translates exceptions raised by kernel
>> using a RuntimeExceptionTranslator that passes through any exception whose
>> class name starts with "org.apache.openjpa.persistence."
>>
>>  This policy, thereby, produces user-visible exceptions that are not
>> *strictly* what JPA spec says (though loosely they are, because many of
>> these pass-through OpenJPA-specific exceptions inherit from their
>> JPA-defined counterparts). Does spec say something about the exact runtime
>> type of raised exception by EntityManager methods, for example, will a
>> subclass be spec-compliant?
>>
>>  I don't seem to locate any statements w.r.t. above question.
>>
>>  Regards --
>>
>> Pinaki
>> --
>> View this message in context:
>> http://www.nabble.com/Exception-translation-by-EntityManager-facade-tp17521307p17521307.html
>> Sent from the OpenJPA Developers mailing list archive at Nabble.com.
>>
>>
> --
> Patrick Linskey
> 202 669 5907
>
>

Re: Exception translation by EntityManager facade

Posted by Patrick Linskey <pl...@gmail.com>.
I believe that subtypes are compliant.

-Patrick

On May 29, 2008, at 6:57 AM, Pinaki Poddar wrote:

>
> Hi,
>  Currently, EntityManager facade translates exceptions raised by  
> kernel
> using a RuntimeExceptionTranslator that passes through any exception  
> whose
> class name starts with "org.apache.openjpa.persistence."
>
>  This policy, thereby, produces user-visible exceptions that are not
> *strictly* what JPA spec says (though loosely they are, because many  
> of
> these pass-through OpenJPA-specific exceptions inherit from their
> JPA-defined counterparts). Does spec say something about the exact  
> runtime
> type of raised exception by EntityManager methods, for example, will a
> subclass be spec-compliant?
>
>  I don't seem to locate any statements w.r.t. above question.
>
>  Regards --
>
> Pinaki
> -- 
> View this message in context: http://www.nabble.com/Exception-translation-by-EntityManager-facade-tp17521307p17521307.html
> Sent from the OpenJPA Developers mailing list archive at Nabble.com.
>

-- 
Patrick Linskey
202 669 5907


Re: Exception translation by EntityManager facade

Posted by Pinaki Poddar <pp...@apache.org>.
Hi,
  Please find the following suggested change on exception translation in
PersistenceExceptions class. The idea is to apply further heuristics on
available exception to translate, failing which results in existing
behavior.

   Because this is heuristic by nature, your comment will be much
appreciated (and required for me to commit the changes):



Index:
openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceExceptions.java
===================================================================
---
openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceExceptions.java
(revision 657964)
+++
openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceExceptions.java
(working copy)
@@ -22,6 +22,8 @@

 import org.apache.openjpa.kernel.Broker;
 import org.apache.openjpa.util.Exceptions;
+import org.apache.openjpa.util.ObjectExistsException;
+import org.apache.openjpa.util.ObjectNotFoundException;
 import org.apache.openjpa.util.OpenJPAException;
 import org.apache.openjpa.util.RuntimeExceptionTranslator;
 import org.apache.openjpa.util.StoreException;
@@ -167,6 +169,12 @@

     /**
      * Translate the given user exception.
+     * If a {link {@link OpenJPAException#getSubtype() sub type} is set on
the
+     * given exception then a corresponding facade-level exception i.e. the
+     * exceptions that inherit JPA-defined exceptions is generated.
+     * If given exception is not further classified to a sub type, then
+     * an [@link {@link #translateInternalException(OpenJPAException)}
attempt}
+     * is made to translate the given OpenJPAException by its internal
cause.
      */
     private static Exception translateUserException(OpenJPAException ke) {
         Exception e;
@@ -193,13 +201,39 @@
                         getFailedObject(ke), ke.isFatal());
                 break;
             default:
-                e = new org.apache.openjpa.persistence.ArgumentException
-                    (ke.getMessage(), getNestedThrowables(ke),
-                        getFailedObject(ke), ke.isFatal());
+               e = translateCause(ke);
         }
         e.setStackTrace(ke.getStackTrace());
         return e;
     }
+
+    /**
+     * Translate to a facade-level exception if the given exception
+     *     a) has a cause i.e. one and only nested Throwable
+     * and b) that cause is one of the known internal exception which has a
+     *        direct facade-level counterpart
+     *        (for example, ObjectNotFoundException can be translated to
+     *         EntityNotFoundException).
+     * If the above conditions are not met then return generic
ArgumentException.
+     *
+     * In either case, preserve all the details.
+     */
+    private static Exception translateCause(OpenJPAException ke) {
+       Throwable cause = ke.getCause();
+       if (cause instanceof ObjectNotFoundException) {
+               return new EntityNotFoundException(
+                       ke.getMessage(), getNestedThrowables(ke),
+               getFailedObject(ke), ke.isFatal());
+       } else if (cause instanceof ObjectExistsException) {
+               return new EntityExistsException(
+                       ke.getMessage(), getNestedThrowables(ke),
+               getFailedObject(ke), ke.isFatal());
+       } else {
+               return new org.apache.openjpa.persistence.ArgumentException(
+                       ke.getMessage(), getNestedThrowables(ke),
+                       getFailedObject(ke), ke.isFatal());
+       }
+    }

-- 
View this message in context: http://www.nabble.com/Exception-translation-by-EntityManager-facade-tp17521307p17523862.html
Sent from the OpenJPA Developers mailing list archive at Nabble.com.