ANN-827 add initial support for Bean Validation
git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@16474 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
5f5a434b34
commit
eb94cfa053
|
@ -71,7 +71,16 @@
|
||||||
<artifactId>cglib</artifactId>
|
<artifactId>cglib</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>javax.validation</groupId>
|
||||||
|
<artifactId>validation-api</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.hibernate</groupId>
|
||||||
|
<artifactId>hibernate-validator</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
|
@ -97,10 +106,20 @@
|
||||||
<version>3.4.GA</version>
|
<version>3.4.GA</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cglib</groupId>
|
<groupId>cglib</groupId>
|
||||||
<artifactId>cglib</artifactId>
|
<artifactId>cglib</artifactId>
|
||||||
<version>2.2</version>
|
<version>2.2</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.hibernate</groupId>
|
||||||
|
<artifactId>hibernate-validator</artifactId>
|
||||||
|
<version>4.0.0.Beta1</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>javax.validation</groupId>
|
||||||
|
<artifactId>validation-api</artifactId>
|
||||||
|
<version>1.0.CR2</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
|
@ -69,6 +69,7 @@ import org.hibernate.annotations.common.reflection.XClass;
|
||||||
import org.hibernate.annotations.common.reflection.java.JavaReflectionManager;
|
import org.hibernate.annotations.common.reflection.java.JavaReflectionManager;
|
||||||
import org.hibernate.cfg.annotations.Version;
|
import org.hibernate.cfg.annotations.Version;
|
||||||
import org.hibernate.cfg.annotations.reflection.JPAMetadataProvider;
|
import org.hibernate.cfg.annotations.reflection.JPAMetadataProvider;
|
||||||
|
import org.hibernate.cfg.beanvalidation.BeanValidationActivator;
|
||||||
import org.hibernate.engine.NamedQueryDefinition;
|
import org.hibernate.engine.NamedQueryDefinition;
|
||||||
import org.hibernate.engine.NamedSQLQueryDefinition;
|
import org.hibernate.engine.NamedSQLQueryDefinition;
|
||||||
import org.hibernate.engine.ResultSetMappingDefinition;
|
import org.hibernate.engine.ResultSetMappingDefinition;
|
||||||
|
@ -800,6 +801,13 @@ public class AnnotationConfiguration extends Configuration {
|
||||||
}
|
}
|
||||||
|
|
||||||
public SessionFactory buildSessionFactory() throws HibernateException {
|
public SessionFactory buildSessionFactory() throws HibernateException {
|
||||||
|
enableLegacyHibernateValidator();
|
||||||
|
enableBeanValidation();
|
||||||
|
enableHibernateSearch();
|
||||||
|
return super.buildSessionFactory();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void enableLegacyHibernateValidator() {
|
||||||
//add validator events if the jar is available
|
//add validator events if the jar is available
|
||||||
boolean enableValidatorListeners = !"false".equalsIgnoreCase( getProperty( "hibernate.validator.autoregister_listeners" ) );
|
boolean enableValidatorListeners = !"false".equalsIgnoreCase( getProperty( "hibernate.validator.autoregister_listeners" ) );
|
||||||
Class validateEventListenerClass = null;
|
Class validateEventListenerClass = null;
|
||||||
|
@ -868,10 +876,10 @@ public class AnnotationConfiguration extends Configuration {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
enableHibernateSearch();
|
|
||||||
|
private void enableBeanValidation() {
|
||||||
return super.buildSessionFactory();
|
BeanValidationActivator.activateBeanValidation( getEventListeners(), getProperties() );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
package org.hibernate.cfg.beanvalidation;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import org.hibernate.util.ReflectHelper;
|
||||||
|
import org.hibernate.HibernateException;
|
||||||
|
import org.hibernate.AssertionFailure;
|
||||||
|
import org.hibernate.event.EventListeners;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class has no hard depenmdency on Bean Validation APIs
|
||||||
|
* It must uses reflectione very time BV is required.
|
||||||
|
* @author Emmanuel Bernard
|
||||||
|
*/
|
||||||
|
public class BeanValidationActivator {
|
||||||
|
|
||||||
|
private static final String BV_DISCOVERY_CLASS = "javax.validation.Validation";
|
||||||
|
private static final String TYPE_SAFE_ACTIVATOR_CLASS = "org.hibernate.cfg.beanvalidation.TypeSafeActivator";
|
||||||
|
private static final String TYPE_SAFE_ACTIVATOR_METHOD = "activateBeanValidation";
|
||||||
|
private static final String MODE_PROPERTY = "javax.persistence.validation.mode";
|
||||||
|
|
||||||
|
public static void activateBeanValidation(EventListeners eventListeners, Properties properties) {
|
||||||
|
ValidationMode mode = ValidationMode.getMode( properties.get( MODE_PROPERTY ) );
|
||||||
|
if (mode == ValidationMode.NONE) return;
|
||||||
|
try {
|
||||||
|
//load Validation
|
||||||
|
ReflectHelper.classForName( BV_DISCOVERY_CLASS, BeanValidationActivator.class );
|
||||||
|
}
|
||||||
|
catch ( ClassNotFoundException e ) {
|
||||||
|
|
||||||
|
if (mode == ValidationMode.CALLBACK) {
|
||||||
|
throw new HibernateException( "Bean Validation not available in the class path but required in " + MODE_PROPERTY );
|
||||||
|
}
|
||||||
|
else if (mode == ValidationMode.AUTO) {
|
||||||
|
//nothing to activate
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new AssertionFailure( "Unexpected ValidationMode: " + mode );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Class<?> activator = ReflectHelper.classForName( TYPE_SAFE_ACTIVATOR_CLASS, BeanValidationActivator.class );
|
||||||
|
Method buildDefaultValidatorFactory =
|
||||||
|
activator.getMethod( TYPE_SAFE_ACTIVATOR_METHOD, EventListeners.class, Properties.class );
|
||||||
|
buildDefaultValidatorFactory.invoke( null, eventListeners, properties );
|
||||||
|
}
|
||||||
|
catch ( NoSuchMethodException e ) {
|
||||||
|
throw new HibernateException( "Unable to get the default Bean Validation factory", e);
|
||||||
|
}
|
||||||
|
catch ( IllegalAccessException e ) {
|
||||||
|
throw new HibernateException( "Unable to get the default Bean Validation factory", e);
|
||||||
|
}
|
||||||
|
catch ( InvocationTargetException e ) {
|
||||||
|
throw new HibernateException( "Unable to get the default Bean Validation factory", e);
|
||||||
|
}
|
||||||
|
catch ( ClassNotFoundException e ) {
|
||||||
|
throw new HibernateException( "Unable to get the default Bean Validation factory", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static enum ValidationMode {
|
||||||
|
AUTO,
|
||||||
|
CALLBACK,
|
||||||
|
NONE;
|
||||||
|
|
||||||
|
public static ValidationMode getMode(Object modeProperty) {
|
||||||
|
if (modeProperty == null) {
|
||||||
|
return AUTO;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
try {
|
||||||
|
return valueOf( modeProperty.toString().toUpperCase() );
|
||||||
|
}
|
||||||
|
catch ( IllegalArgumentException e ) {
|
||||||
|
throw new HibernateException( "Unknown validation mode in " + MODE_PROPERTY + ": " + modeProperty.toString() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,156 @@
|
||||||
|
package org.hibernate.cfg.beanvalidation;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import javax.validation.ValidatorFactory;
|
||||||
|
import javax.validation.ConstraintViolation;
|
||||||
|
import javax.validation.TraversableResolver;
|
||||||
|
import javax.validation.Validator;
|
||||||
|
import javax.validation.ConstraintViolationException;
|
||||||
|
import javax.validation.groups.Default;
|
||||||
|
|
||||||
|
import org.hibernate.event.PreInsertEventListener;
|
||||||
|
import org.hibernate.event.PreUpdateEventListener;
|
||||||
|
import org.hibernate.event.PreDeleteEventListener;
|
||||||
|
import org.hibernate.event.PreInsertEvent;
|
||||||
|
import org.hibernate.event.PreUpdateEvent;
|
||||||
|
import org.hibernate.event.PreDeleteEvent;
|
||||||
|
import org.hibernate.EntityMode;
|
||||||
|
import org.hibernate.HibernateException;
|
||||||
|
import org.hibernate.util.ReflectHelper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Emmanuel Bernard
|
||||||
|
*/
|
||||||
|
//FIXME review exception model
|
||||||
|
public class BeanValidationEventListener implements
|
||||||
|
PreInsertEventListener, PreUpdateEventListener, PreDeleteEventListener {
|
||||||
|
private static final String JPA_GROUP_PREFIX = "javax.persistence.validation.group.";
|
||||||
|
private static final Class<?>[] DEFAULT_GROUPS = new Class<?>[] { Default.class };
|
||||||
|
private static final Class<?>[] EMPTY_GROUPS = new Class<?>[] { };
|
||||||
|
|
||||||
|
private ValidatorFactory factory;
|
||||||
|
private TraversableResolver tr;
|
||||||
|
private Map<Operation, Class<?>[]> groupsPerOperation = new HashMap<Operation, Class<?>[]>(3);
|
||||||
|
|
||||||
|
|
||||||
|
public BeanValidationEventListener(ValidatorFactory factory, Properties properties) {
|
||||||
|
this.factory = factory;
|
||||||
|
setGroupsForOperation( Operation.INSERT, properties );
|
||||||
|
setGroupsForOperation( Operation.UPDATE, properties );
|
||||||
|
setGroupsForOperation( Operation.DELETE, properties );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setGroupsForOperation(Operation operation, Properties properties) {
|
||||||
|
Object property = properties.get( JPA_GROUP_PREFIX + operation.getGroupPropertyName() );
|
||||||
|
|
||||||
|
Class<?>[] groups;
|
||||||
|
if ( property == null ) {
|
||||||
|
groups = operation == Operation.DELETE ? EMPTY_GROUPS : DEFAULT_GROUPS;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ( property instanceof String ) {
|
||||||
|
String stringProperty = (String) property;
|
||||||
|
String[] groupNames = stringProperty.split( "," );
|
||||||
|
if ( groupNames.length == 1 && groupNames[0].equals( "" ) ) {
|
||||||
|
groups = EMPTY_GROUPS;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
List<Class<?>> groupsList = new ArrayList<Class<?>>(groupNames.length);
|
||||||
|
for (String groupName : groupNames) {
|
||||||
|
String cleanedGroupName = groupName.trim();
|
||||||
|
if ( cleanedGroupName.length() > 0) {
|
||||||
|
try {
|
||||||
|
groupsList.add( ReflectHelper.classForName( cleanedGroupName ) );
|
||||||
|
}
|
||||||
|
catch ( ClassNotFoundException e ) {
|
||||||
|
throw new HibernateException( "Unable to load class " + cleanedGroupName, e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
groups = groupsList.toArray( new Class<?>[groupsList.size()] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( property instanceof Class<?>[] ) {
|
||||||
|
groups = (Class<?>[]) property;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//null is bad and excluded by instanceof => exception is raised
|
||||||
|
throw new HibernateException( JPA_GROUP_PREFIX + operation.getGroupPropertyName() + " is of unknown type: String or Class<?>[] only");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
groupsPerOperation.put( operation, groups );
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean onPreInsert(PreInsertEvent event) {
|
||||||
|
validate( event.getEntity(), event.getSession().getEntityMode(), Operation.INSERT );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean onPreUpdate(PreUpdateEvent event) {
|
||||||
|
validate( event.getEntity(), event.getSession().getEntityMode(), Operation.UPDATE );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean onPreDelete(PreDeleteEvent event) {
|
||||||
|
validate( event.getEntity(), event.getSession().getEntityMode(), Operation.DELETE );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> void validate(T object, EntityMode mode, Operation operation) {
|
||||||
|
if ( object == null || mode != EntityMode.POJO ) return;
|
||||||
|
Validator validator = factory.usingContext()
|
||||||
|
//.traversableResolver( tr )
|
||||||
|
.getValidator();
|
||||||
|
final Class<?>[] groups = groupsPerOperation.get( operation );
|
||||||
|
if ( groups.length > 0 ) {
|
||||||
|
final Set<ConstraintViolation<T>> constraintViolations =
|
||||||
|
validator.validate( object, groups );
|
||||||
|
//FIXME CV should no longer be generics
|
||||||
|
Object unsafeViolations = constraintViolations;
|
||||||
|
if (constraintViolations.size() > 0 ) {
|
||||||
|
//FIXME add Set<ConstraintViolation<?>>
|
||||||
|
throw new ConstraintViolationException(
|
||||||
|
"Invalid object at " + operation.getName() + " time for groups " + toString( groups ),
|
||||||
|
(Set<ConstraintViolation>) unsafeViolations);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String toString(Class<?>[] groups) {
|
||||||
|
StringBuilder toString = new StringBuilder( "[");
|
||||||
|
for ( Class<?> group : groups ) {
|
||||||
|
toString.append( group.getName() ).append( ", " );
|
||||||
|
}
|
||||||
|
toString.append( "]" );
|
||||||
|
return toString.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static enum Operation {
|
||||||
|
INSERT("persist", "pre-persist"),
|
||||||
|
UPDATE("update", "pre-update"),
|
||||||
|
DELETE("remove", "pre-remove");
|
||||||
|
|
||||||
|
private String exposedName;
|
||||||
|
private String groupPropertyName;
|
||||||
|
|
||||||
|
Operation(String exposedName, String groupProperty) {
|
||||||
|
this.exposedName = exposedName;
|
||||||
|
this.groupPropertyName = groupProperty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return exposedName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGroupPropertyName() {
|
||||||
|
return groupPropertyName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
package org.hibernate.cfg.beanvalidation;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Properties;
|
||||||
|
import javax.validation.ValidatorFactory;
|
||||||
|
import javax.validation.Validation;
|
||||||
|
|
||||||
|
import org.hibernate.HibernateException;
|
||||||
|
import org.hibernate.event.EventListeners;
|
||||||
|
import org.hibernate.event.PreInsertEventListener;
|
||||||
|
import org.hibernate.event.PreUpdateEventListener;
|
||||||
|
import org.hibernate.event.PreDeleteEventListener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Emmanuel Bernard
|
||||||
|
*/
|
||||||
|
class TypeSafeActivator {
|
||||||
|
|
||||||
|
private static final String FACTORY_PROPERTY = "javax.persistence.validation.factory";
|
||||||
|
|
||||||
|
public static void activateBeanValidation(EventListeners eventListeners, Properties properties) {
|
||||||
|
ValidatorFactory factory = getValidatorFactory( properties );
|
||||||
|
BeanValidationEventListener beanValidationEventListener = new BeanValidationEventListener( factory, properties );
|
||||||
|
|
||||||
|
{
|
||||||
|
PreInsertEventListener[] listeners = eventListeners.getPreInsertEventListeners();
|
||||||
|
int length = listeners.length + 1;
|
||||||
|
PreInsertEventListener[] newListeners = new PreInsertEventListener[length];
|
||||||
|
System.arraycopy( listeners, 0, newListeners, 0, length - 1 );
|
||||||
|
newListeners[length - 1] = beanValidationEventListener;
|
||||||
|
eventListeners.setPreInsertEventListeners( newListeners );
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
PreUpdateEventListener[] listeners = eventListeners.getPreUpdateEventListeners();
|
||||||
|
int length = listeners.length + 1;
|
||||||
|
PreUpdateEventListener[] newListeners = new PreUpdateEventListener[length];
|
||||||
|
System.arraycopy( listeners, 0, newListeners, 0, length - 1 );
|
||||||
|
newListeners[length - 1] = beanValidationEventListener;
|
||||||
|
eventListeners.setPreUpdateEventListeners( newListeners );
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
PreDeleteEventListener[] listeners = eventListeners.getPreDeleteEventListeners();
|
||||||
|
int length = listeners.length + 1;
|
||||||
|
PreDeleteEventListener[] newListeners = new PreDeleteEventListener[length];
|
||||||
|
System.arraycopy( listeners, 0, newListeners, 0, length - 1 );
|
||||||
|
newListeners[length - 1] = beanValidationEventListener;
|
||||||
|
eventListeners.setPreDeleteEventListeners( newListeners );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static ValidatorFactory getValidatorFactory(Map<Object, Object> properties) {
|
||||||
|
ValidatorFactory factory = null;
|
||||||
|
if ( properties != null ) {
|
||||||
|
Object unsafeProperty = properties.get( FACTORY_PROPERTY );
|
||||||
|
if (unsafeProperty != null) {
|
||||||
|
try {
|
||||||
|
factory = ValidatorFactory.class.cast( unsafeProperty );
|
||||||
|
}
|
||||||
|
catch ( ClassCastException e ) {
|
||||||
|
throw new HibernateException( "Property " + FACTORY_PROPERTY
|
||||||
|
+ " should containt an object of type " + ValidatorFactory.class.getName() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (factory == null) {
|
||||||
|
try {
|
||||||
|
factory = Validation.buildDefaultValidatorFactory();
|
||||||
|
}
|
||||||
|
catch ( Exception e ) {
|
||||||
|
throw new HibernateException( "Unable to build the default ValidatorFactory", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package org.hibernate.test.annotations.beanvalidation;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import javax.validation.ConstraintViolationException;
|
||||||
|
|
||||||
|
import org.hibernate.Session;
|
||||||
|
import org.hibernate.Transaction;
|
||||||
|
import org.hibernate.test.annotations.TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Emmanuel Bernard
|
||||||
|
*/
|
||||||
|
public class BeanValidationAutoTest extends TestCase {
|
||||||
|
public void testListeners() {
|
||||||
|
CupHolder ch = new CupHolder();
|
||||||
|
ch.setRadius( new BigDecimal( "12" ) );
|
||||||
|
Session s = openSession( );
|
||||||
|
Transaction tx = s.beginTransaction();
|
||||||
|
try {
|
||||||
|
s.persist( ch );
|
||||||
|
s.flush();
|
||||||
|
fail("invalid object should not be persisted");
|
||||||
|
}
|
||||||
|
catch ( ConstraintViolationException e ) {
|
||||||
|
assertEquals( 1, e.getConstraintViolations().size() );
|
||||||
|
}
|
||||||
|
tx.rollback();
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Class<?>[] getMappings() {
|
||||||
|
return new Class<?>[] {
|
||||||
|
CupHolder.class
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package org.hibernate.test.annotations.beanvalidation;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import javax.validation.ConstraintViolationException;
|
||||||
|
|
||||||
|
import org.hibernate.Session;
|
||||||
|
import org.hibernate.Transaction;
|
||||||
|
import org.hibernate.cfg.Configuration;
|
||||||
|
import org.hibernate.test.annotations.TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Emmanuel Bernard
|
||||||
|
*/
|
||||||
|
public class BeanValidationDisabledTest extends TestCase {
|
||||||
|
public void testListeners() {
|
||||||
|
CupHolder ch = new CupHolder();
|
||||||
|
ch.setRadius( new BigDecimal( "12" ) );
|
||||||
|
Session s = openSession( );
|
||||||
|
Transaction tx = s.beginTransaction();
|
||||||
|
try {
|
||||||
|
s.persist( ch );
|
||||||
|
s.flush();
|
||||||
|
}
|
||||||
|
catch ( ConstraintViolationException e ) {
|
||||||
|
fail("invalid object should not be validated");
|
||||||
|
}
|
||||||
|
tx.rollback();
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure(Configuration cfg) {
|
||||||
|
super.configure( cfg );
|
||||||
|
cfg.setProperty( "javax.persistence.validation.mode", "none" );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Class<?>[] getMappings() {
|
||||||
|
return new Class<?>[] {
|
||||||
|
CupHolder.class
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
package org.hibernate.test.annotations.beanvalidation;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import javax.validation.ConstraintViolationException;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import javax.validation.groups.Default;
|
||||||
|
|
||||||
|
import org.hibernate.Session;
|
||||||
|
import org.hibernate.Transaction;
|
||||||
|
import org.hibernate.cfg.Configuration;
|
||||||
|
import org.hibernate.cfg.annotations.reflection.XMLContext;
|
||||||
|
import org.hibernate.test.annotations.TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Emmanuel Bernard
|
||||||
|
*/
|
||||||
|
public class BeanValidationGroupsTest extends TestCase {
|
||||||
|
public void testListeners() {
|
||||||
|
CupHolder ch = new CupHolder();
|
||||||
|
ch.setRadius( new BigDecimal( "12" ) );
|
||||||
|
Session s = openSession( );
|
||||||
|
Transaction tx = s.beginTransaction();
|
||||||
|
try {
|
||||||
|
s.persist( ch );
|
||||||
|
s.flush();
|
||||||
|
}
|
||||||
|
catch ( ConstraintViolationException e ) {
|
||||||
|
fail("invalid object should not be validated");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
ch.setRadius( null );
|
||||||
|
s.flush();
|
||||||
|
}
|
||||||
|
catch ( ConstraintViolationException e ) {
|
||||||
|
fail("invalid object should not be validated");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
s.delete( ch );
|
||||||
|
s.flush();
|
||||||
|
fail("invalid object should not be persisted");
|
||||||
|
}
|
||||||
|
catch ( ConstraintViolationException e ) {
|
||||||
|
assertEquals( 1, e.getConstraintViolations().size() );
|
||||||
|
assertEquals( NotNull.class,
|
||||||
|
e.getConstraintViolations().iterator().next().getConstraintDescriptor().getAnnotation().annotationType()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
tx.rollback();
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure(Configuration cfg) {
|
||||||
|
super.configure( cfg );
|
||||||
|
cfg.setProperty( "javax.persistence.validation.group.pre-persist",
|
||||||
|
"" );
|
||||||
|
cfg.setProperty( "javax.persistence.validation.group.pre-update",
|
||||||
|
"" );
|
||||||
|
cfg.setProperty( "javax.persistence.validation.group.pre-remove",
|
||||||
|
Default.class.getName() + ", " + Strict.class.getName() );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Class<?>[] getMappings() {
|
||||||
|
return new Class<?>[] {
|
||||||
|
CupHolder.class
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
package org.hibernate.test.annotations.beanvalidation;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.validation.constraints.Max;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Emmanuel Bernard
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
public class CupHolder {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private Integer id;
|
||||||
|
private BigDecimal radius;
|
||||||
|
|
||||||
|
public Integer getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Integer id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Max( value = 10, message = "Radius way out")
|
||||||
|
@NotNull(groups = Strict.class)
|
||||||
|
public BigDecimal getRadius() {
|
||||||
|
return radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRadius(BigDecimal radius) {
|
||||||
|
this.radius = radius;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package org.hibernate.test.annotations.beanvalidation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Emmanuel Bernard
|
||||||
|
*/
|
||||||
|
public interface Strict {
|
||||||
|
}
|
Loading…
Reference in New Issue