mirror of https://github.com/apache/openjpa.git
OPENJPA-1068 Modified exception translator to translate wrapped validation exceptions. EM operations now throw correct validation exceptions.
git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@790700 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
c2afd1cefd
commit
c24bc1d75c
|
@ -15,6 +15,7 @@ package org.apache.openjpa.integration.validation;
|
|||
|
||||
import javax.persistence.Query;
|
||||
import javax.persistence.ValidationMode;
|
||||
import javax.validation.ConstraintViolationException;
|
||||
|
||||
import org.apache.openjpa.conf.OpenJPAConfiguration;
|
||||
import org.apache.openjpa.lib.log.Log;
|
||||
|
@ -102,7 +103,7 @@ public class TestConstraints extends SingleEMFTestCase {
|
|||
em.getTransaction().commit();
|
||||
getLog().trace("testNullUpdateConstraint() Part 2 of 2 failed");
|
||||
fail("Expected a Validation exception");
|
||||
} catch (Exception e) {
|
||||
} catch (ConstraintViolationException e) {
|
||||
// expected
|
||||
getLog().trace("Caught expected exception = " + e);
|
||||
getLog().trace("testNullUpdateConstraint() Part 2 of 2 passed");
|
||||
|
@ -153,6 +154,9 @@ public class TestConstraints extends SingleEMFTestCase {
|
|||
if ((em != null) && em.isOpen()) {
|
||||
em.close();
|
||||
}
|
||||
if ((emf != null) && emf.isOpen()) {
|
||||
emf.close();
|
||||
}
|
||||
}
|
||||
|
||||
// Part 2 - Verify delete using default group does not cause Validation
|
||||
|
@ -186,6 +190,9 @@ public class TestConstraints extends SingleEMFTestCase {
|
|||
em.getTransaction().rollback();
|
||||
em.close();
|
||||
}
|
||||
if ((emf != null) && emf.isOpen()) {
|
||||
emf.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -225,6 +232,9 @@ public class TestConstraints extends SingleEMFTestCase {
|
|||
if ((em != null) && em.isOpen()) {
|
||||
em.close();
|
||||
}
|
||||
if ((emf != null) && emf.isOpen()) {
|
||||
emf.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -251,7 +261,7 @@ public class TestConstraints extends SingleEMFTestCase {
|
|||
em.getTransaction().commit();
|
||||
getLog().trace("testNullConstraint() failed");
|
||||
fail("Expected a Validation exception");
|
||||
} catch (Exception e) {
|
||||
} catch (ConstraintViolationException e) {
|
||||
// expected
|
||||
getLog().trace("Caught expected exception = " + e);
|
||||
getLog().trace("testNullConstraint() passed");
|
||||
|
@ -285,7 +295,7 @@ public class TestConstraints extends SingleEMFTestCase {
|
|||
em.getTransaction().commit();
|
||||
getLog().trace("testNotNullConstraint() failed");
|
||||
fail("Expected a Validation exception");
|
||||
} catch (Exception e) {
|
||||
} catch (ConstraintViolationException e) {
|
||||
// expected
|
||||
getLog().trace("Caught expected exception = " + e);
|
||||
getLog().trace("testNotNullConstraint() passed");
|
||||
|
@ -351,7 +361,7 @@ public class TestConstraints extends SingleEMFTestCase {
|
|||
em.getTransaction().commit();
|
||||
getLog().trace("testAssertTrueConstraint() failed");
|
||||
fail("Expected a Validation exception");
|
||||
} catch (Exception e) {
|
||||
} catch (ConstraintViolationException e) {
|
||||
// expected
|
||||
getLog().trace("Caught expected exception = " + e);
|
||||
getLog().trace("testAssertTrueConstraint() passed");
|
||||
|
@ -385,7 +395,7 @@ public class TestConstraints extends SingleEMFTestCase {
|
|||
em.getTransaction().commit();
|
||||
getLog().trace("testAssertFalseConstraint() failed");
|
||||
fail("Expected a Validation exception");
|
||||
} catch (Exception e) {
|
||||
} catch (ConstraintViolationException e) {
|
||||
// expected
|
||||
getLog().trace("Caught expected exception = " + e);
|
||||
getLog().trace("testAssertFalseConstraint() passed");
|
||||
|
|
|
@ -33,6 +33,7 @@ public interface ExceptionInfo {
|
|||
public static final int UNSUPPORTED = 3;
|
||||
public static final int USER = 4;
|
||||
public static final int WRAPPED = 5;
|
||||
public static final int UNAVAILABLE = 6;
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.openjpa.validation;
|
||||
|
||||
import org.apache.openjpa.util.OpenJPAException;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class ValidationUnavailableException extends OpenJPAException {
|
||||
|
||||
public ValidationUnavailableException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
public ValidationUnavailableException(String msg, RuntimeException e) {
|
||||
super(msg, e);
|
||||
}
|
||||
|
||||
public ValidationUnavailableException(String msg, RuntimeException e,
|
||||
boolean fatal) {
|
||||
super(msg, e);
|
||||
setFatal(fatal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return UNAVAILABLE;
|
||||
}
|
||||
}
|
|
@ -72,10 +72,12 @@ import org.apache.openjpa.meta.FieldMetaData;
|
|||
import org.apache.openjpa.meta.QueryMetaData;
|
||||
import org.apache.openjpa.meta.SequenceMetaData;
|
||||
import org.apache.openjpa.persistence.criteria.CriteriaBuilder;
|
||||
import org.apache.openjpa.persistence.validation.ValidationUtils;
|
||||
import org.apache.openjpa.util.Exceptions;
|
||||
import org.apache.openjpa.util.ImplHelper;
|
||||
import org.apache.openjpa.util.RuntimeExceptionTranslator;
|
||||
import org.apache.openjpa.util.UserException;
|
||||
import org.apache.openjpa.util.WrappedException;
|
||||
|
||||
/**
|
||||
* Implementation of {@link EntityManager} interface.
|
||||
|
@ -552,6 +554,12 @@ public class EntityManagerImpl
|
|||
} catch (IllegalStateException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
// Per JPA 2.0 spec, if the exception was due to a JSR-303
|
||||
// constraint violation, the ConstraintViolationException should be
|
||||
// thrown. Since JSR-303 is optional, the cast to RuntimeException
|
||||
// prevents the introduction of a runtime dependency on the BV API.
|
||||
if (ValidationUtils.isConstraintViolationException(e))
|
||||
throw (RuntimeException)e;
|
||||
// RollbackExceptions are special and aren't handled by the
|
||||
// normal exception translator, since the spec says they
|
||||
// should be thrown whenever the commit fails for any reason at
|
||||
|
|
|
@ -33,6 +33,7 @@ import org.apache.openjpa.util.QueryException;
|
|||
import org.apache.openjpa.util.RuntimeExceptionTranslator;
|
||||
import org.apache.openjpa.util.StoreException;
|
||||
import org.apache.openjpa.util.UserException;
|
||||
import org.apache.openjpa.util.WrappedException;
|
||||
|
||||
/**
|
||||
* Converts from OpenJPA to persistence exception types.
|
||||
|
@ -138,6 +139,8 @@ public class PersistenceExceptions
|
|||
return translateStoreException(ke);
|
||||
case OpenJPAException.USER:
|
||||
return translateUserException(ke);
|
||||
case OpenJPAException.WRAPPED:
|
||||
return translateWrappedException(ke);
|
||||
default:
|
||||
return translateGeneralException(ke);
|
||||
}
|
||||
|
@ -250,6 +253,18 @@ public class PersistenceExceptions
|
|||
return e;
|
||||
}
|
||||
|
||||
/*
|
||||
* Translate the given wrapped exception. If contains an Exception, return
|
||||
* the exception. If contains a Throwable, wrap the throwable and
|
||||
* return it.
|
||||
*/
|
||||
private static Exception translateWrappedException(OpenJPAException ke) {
|
||||
Throwable t = ke.getCause();
|
||||
if (t instanceof Exception)
|
||||
return (Exception)t;
|
||||
return translateCause(ke);
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate to a facade-level exception if the given exception
|
||||
* a) has a cause i.e. one and only nested Throwable
|
||||
|
|
|
@ -23,7 +23,9 @@ import javax.persistence.ValidationMode;
|
|||
import org.apache.openjpa.conf.OpenJPAConfiguration;
|
||||
import org.apache.openjpa.lib.log.Log;
|
||||
import org.apache.openjpa.lib.util.Localizer;
|
||||
import org.apache.openjpa.lib.util.Localizer.Message;
|
||||
import org.apache.openjpa.validation.ValidationException;
|
||||
import org.apache.openjpa.validation.ValidationUnavailableException;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -77,9 +79,11 @@ public class ValidationUtils {
|
|||
} catch (ClassNotFoundException e) {
|
||||
if (bValRequired) {
|
||||
// fatal error - ValidationMode requires a validator
|
||||
log.error(_loc.get("vlem-creation-error"), e);
|
||||
// rethrow as a WrappedException
|
||||
throw new ValidationException(
|
||||
Message msg = _loc.get("vlem-creation-error");
|
||||
log.error(msg, e);
|
||||
// rethrow as a more descriptive/identifiable exception
|
||||
throw new ValidationUnavailableException(
|
||||
msg.getMessage(),
|
||||
new RuntimeException(e), true);
|
||||
} else {
|
||||
// no optional validation provider, so just trace output
|
||||
|
@ -105,9 +109,14 @@ public class ValidationUtils {
|
|||
} catch (RuntimeException e) {
|
||||
if (bValRequired) {
|
||||
// fatal error - ValidationMode requires a validator
|
||||
log.error(_loc.get("vlem-creation-error"), e);
|
||||
// rethrow as a WrappedException
|
||||
throw new ValidationException(e, true);
|
||||
Message msg = _loc.get("vlem-creation-error");
|
||||
log.error(msg, e);
|
||||
// rethrow as a more descriptive/identifiable exception
|
||||
throw new ValidationUnavailableException(
|
||||
msg.getMessage(),
|
||||
e, true);
|
||||
|
||||
} else {
|
||||
// unexpected, but validation is optional,
|
||||
// so just log it as a warning
|
||||
|
@ -123,4 +132,21 @@ public class ValidationUtils {
|
|||
}
|
||||
return brc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether an exception is a constraint violation exception via
|
||||
* class name. Does not require JSR-303 API to be in classpath.
|
||||
* @param e exception to check
|
||||
* @return true of the exception is a constraint violation exception
|
||||
*/
|
||||
public static boolean isConstraintViolationException(Exception e) {
|
||||
if (e == null)
|
||||
return false;
|
||||
|
||||
if (e.getClass().getName().equals(
|
||||
"javax.validation.ConstraintViolationException"))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue