diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/datacache/TestDataCacheBehavesIdentical.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/datacache/TestDataCacheBehavesIdentical.java index ac530366d..4f1121ca1 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/datacache/TestDataCacheBehavesIdentical.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/datacache/TestDataCacheBehavesIdentical.java @@ -438,9 +438,9 @@ public class TestDataCacheBehavesIdentical extends AbstractTestCase { assertEquals(useDataCache, dataCache.contains(PObject.class, oid)); /** - * refresh behavior depends on current lock. Having no lock will refresh - * the instance (wrongly) while any other lock will attempt to fetch the - * instance from database (correctly) raising EntityNotFoundException. + * refresh behavior no more depends on current lock. Refresh + * will always attempt to fetch the instance from database + * raising EntityNotFoundException. * */ em.getTransaction().begin(); @@ -448,18 +448,12 @@ public class TestDataCacheBehavesIdentical extends AbstractTestCase { em.getFetchPlan().setReadLockMode(lock); try { em.refresh(pc); - if (lock == null) { - assertEquals(useDataCache ? MARKER_DATACACHE : MARKER_CACHE, pc.getName()); - } else { - fail("expected EntityNotFoundException for PObject:" + oid); - } + fail("expected EntityNotFoundException for PObject:" + oid); + } catch (EntityNotFoundException ex) { + // we are good } catch (Exception ex) { - if (ex instanceof EntityNotFoundException || - ex instanceof org.apache.openjpa.persistence.EntityNotFoundException) { - if (lock != null) { - // we are good - } - } + ex.printStackTrace(); + fail("expected EntityNotFoundException for PObject:" + oid); } finally { em.getTransaction().rollback(); } diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceExceptions.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceExceptions.java index 78f3d54fd..55d19e61d 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceExceptions.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceExceptions.java @@ -22,7 +22,11 @@ import java.lang.reflect.InvocationTargetException; import org.apache.openjpa.kernel.Broker; import org.apache.openjpa.util.Exceptions; +import org.apache.openjpa.util.NoTransactionException; +import org.apache.openjpa.util.ObjectExistsException; +import org.apache.openjpa.util.ObjectNotFoundException; import org.apache.openjpa.util.OpenJPAException; +import org.apache.openjpa.util.OptimisticException; import org.apache.openjpa.util.RuntimeExceptionTranslator; import org.apache.openjpa.util.StoreException; import org.apache.openjpa.util.UserException; @@ -167,6 +171,12 @@ public class PersistenceExceptions /** * 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 +203,47 @@ public class PersistenceExceptions 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 if (cause instanceof NoTransactionException) { + return new TransactionRequiredException( + ke.getMessage(), getNestedThrowables(ke), + getFailedObject(ke), ke.isFatal()); + } else if (cause instanceof OptimisticException) { + return new OptimisticLockException( + ke.getMessage(), getNestedThrowables(ke), + getFailedObject(ke), ke.isFatal()); + } else { + return new org.apache.openjpa.persistence.ArgumentException( + ke.getMessage(), getNestedThrowables(ke), + getFailedObject(ke), ke.isFatal()); + } + } /** * Translate the given general exception.