HHH-7990 - Bootstrapping Hibernate fails if javax.validation API is on classpath but no provider
(cherry picked from commit 898bab28ca
)
Conflicts:
hibernate-core/src/main/java/org/hibernate/internal/CoreMessageLogger.java
This commit is contained in:
parent
3fa669831f
commit
2e18376fba
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cfg.beanvalidation;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.service.spi.SessionFactoryServiceRegistry;
|
||||
|
||||
/**
|
||||
* Defines the context needed to call the {@link TypeSafeActivator}
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface ActivationContext {
|
||||
/**
|
||||
* Access the requested validation mode(s).
|
||||
* <p/>
|
||||
* IMPL NOTE : the legacy code allowed multiple mode values to be specified, so that is why it is multi-valued here.
|
||||
* However, I cannot find any good reasoning why it was defined that way and even JPA states it should be a single
|
||||
* value. For 4.1 (in maintenance) I think it makes the most sense to not mess with it. Discuss for
|
||||
* 4.2 and beyond.
|
||||
*
|
||||
* @return The requested validation modes
|
||||
*/
|
||||
public Set<ValidationMode> getValidationModes();
|
||||
|
||||
/**
|
||||
* Access the Configuration
|
||||
*
|
||||
* @return The Hibernate Configuration object
|
||||
*/
|
||||
public Configuration getConfiguration();
|
||||
|
||||
/**
|
||||
* Access the SessionFactory being built to trigger this BV activation
|
||||
*
|
||||
* @return The SessionFactory being built
|
||||
*/
|
||||
public SessionFactoryImplementor getSessionFactory();
|
||||
|
||||
/**
|
||||
* Access the ServiceRegistry specific to the SessionFactory being built.
|
||||
*
|
||||
* @return The SessionFactoryServiceRegistry
|
||||
*/
|
||||
public SessionFactoryServiceRegistry getServiceRegistry();
|
||||
}
|
|
@ -25,23 +25,15 @@ package org.hibernate.cfg.beanvalidation;
|
|||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.event.service.spi.EventListenerRegistry;
|
||||
import org.hibernate.integrator.spi.Integrator;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||
import org.hibernate.metamodel.source.MetadataImplementor;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.service.spi.SessionFactoryServiceRegistry;
|
||||
|
@ -50,7 +42,10 @@ import org.hibernate.service.spi.SessionFactoryServiceRegistry;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class BeanValidationIntegrator implements Integrator {
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, BeanValidationIntegrator.class.getName());
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
|
||||
CoreMessageLogger.class,
|
||||
BeanValidationIntegrator.class.getName()
|
||||
);
|
||||
|
||||
public static final String APPLY_CONSTRAINTS = "hibernate.validator.apply_to_ddl";
|
||||
|
||||
|
@ -58,16 +53,22 @@ public class BeanValidationIntegrator implements Integrator {
|
|||
|
||||
public static final String MODE_PROPERTY = "javax.persistence.validation.mode";
|
||||
|
||||
private static final String ACTIVATOR_CLASS = "org.hibernate.cfg.beanvalidation.TypeSafeActivator";
|
||||
private static final String DDL_METHOD = "applyDDL";
|
||||
private static final String ACTIVATE_METHOD = "activateBeanValidation";
|
||||
private static final String VALIDATE_METHOD = "validateFactory";
|
||||
private static final String ACTIVATOR_CLASS_NAME = "org.hibernate.cfg.beanvalidation.TypeSafeActivator";
|
||||
private static final String VALIDATE_SUPPLIED_FACTORY_METHOD_NAME = "validateSuppliedFactory";
|
||||
private static final String ACTIVATE_METHOD_NAME = "activate";
|
||||
|
||||
/**
|
||||
* Used to validate the type of an explicitly passed ValidatorFactory instance
|
||||
*
|
||||
* @param object The supposed ValidatorFactory instance
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void validateFactory(Object object) {
|
||||
try {
|
||||
final Class activatorClass = BeanValidationIntegrator.class.getClassLoader().loadClass( ACTIVATOR_CLASS );
|
||||
// this direct usage of ClassLoader should be fine since the classes exist in the same jar
|
||||
final Class activatorClass = BeanValidationIntegrator.class.getClassLoader().loadClass( ACTIVATOR_CLASS_NAME );
|
||||
try {
|
||||
final Method validateMethod = activatorClass.getMethod( VALIDATE_METHOD, Object.class );
|
||||
final Method validateMethod = activatorClass.getMethod( VALIDATE_SUPPLIED_FACTORY_METHOD_NAME, Object.class );
|
||||
if ( ! validateMethod.isAccessible() ) {
|
||||
validateMethod.setAccessible( true );
|
||||
}
|
||||
|
@ -101,291 +102,114 @@ public class BeanValidationIntegrator implements Integrator {
|
|||
|
||||
@Override
|
||||
public void integrate(
|
||||
Configuration configuration,
|
||||
SessionFactoryImplementor sessionFactory,
|
||||
SessionFactoryServiceRegistry serviceRegistry) {
|
||||
// determine requested validation modes.
|
||||
final Configuration configuration,
|
||||
final SessionFactoryImplementor sessionFactory,
|
||||
final SessionFactoryServiceRegistry serviceRegistry) {
|
||||
// IMPL NOTE : see the comments on ActivationContext.getValidationModes() as to why this is multi-valued...
|
||||
final Set<ValidationMode> modes = ValidationMode.getModes( configuration.getProperties().get( MODE_PROPERTY ) );
|
||||
if ( modes.size() > 1 ) {
|
||||
LOG.multipleValidationModes( ValidationMode.loggable( modes ) );
|
||||
}
|
||||
if ( modes.size() == 1 && modes.contains( ValidationMode.NONE ) ) {
|
||||
// we have nothing to do; just return
|
||||
return;
|
||||
}
|
||||
|
||||
final ClassLoaderService classLoaderService = serviceRegistry.getService( ClassLoaderService.class );
|
||||
Dialect dialect = serviceRegistry.getService( JdbcServices.class ).getDialect();
|
||||
// try to locate a BV class to see if it is available on the classpath
|
||||
boolean isBeanValidationAvailable;
|
||||
|
||||
// see if the Bean Validation API is available on the classpath
|
||||
if ( isBeanValidationApiAvailable( classLoaderService ) ) {
|
||||
// and if so, call out to the TypeSafeActivator
|
||||
try {
|
||||
classLoaderService.classForName( BV_CHECK_CLASS );
|
||||
isBeanValidationAvailable = true;
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
isBeanValidationAvailable = false;
|
||||
}
|
||||
|
||||
// locate the type safe activator class
|
||||
final Class typeSafeActivatorClass = loadTypeSafeActivatorClass( serviceRegistry );
|
||||
|
||||
// todo : if this works out, probably better to simply alter TypeSafeActivator into a single method...
|
||||
applyRelationalConstraints(
|
||||
modes,
|
||||
isBeanValidationAvailable,
|
||||
typeSafeActivatorClass,
|
||||
configuration,
|
||||
dialect
|
||||
|
||||
);
|
||||
applyHibernateListeners(
|
||||
modes,
|
||||
isBeanValidationAvailable,
|
||||
typeSafeActivatorClass,
|
||||
configuration,
|
||||
sessionFactory,
|
||||
serviceRegistry
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see org.hibernate.integrator.spi.Integrator#integrate(org.hibernate.metamodel.source.MetadataImplementor, org.hibernate.engine.spi.SessionFactoryImplementor, org.hibernate.service.spi.SessionFactoryServiceRegistry)
|
||||
*/
|
||||
final Class typeSafeActivatorClass = loadTypeSafeActivatorClass( classLoaderService );
|
||||
@SuppressWarnings("unchecked")
|
||||
final Method activateMethod = typeSafeActivatorClass.getMethod( ACTIVATE_METHOD_NAME, ActivationContext.class );
|
||||
final ActivationContext activationContext = new ActivationContext() {
|
||||
@Override
|
||||
public void integrate( MetadataImplementor metadata,
|
||||
SessionFactoryImplementor sessionFactory,
|
||||
SessionFactoryServiceRegistry serviceRegistry ) {
|
||||
// Properties props = sessionFactory.getProperties();
|
||||
// final Set<ValidationMode> modes = ValidationMode.getModes(props.get(MODE_PROPERTY));
|
||||
// final ClassLoaderService classLoaderService = serviceRegistry.getService( ClassLoaderService.class );
|
||||
// // try to locate a BV class to see if it is available on the classpath
|
||||
// boolean isBeanValidationAvailable;
|
||||
// try {
|
||||
// classLoaderService.classForName( BV_CHECK_CLASS );
|
||||
// isBeanValidationAvailable = true;
|
||||
// } catch (Exception error) {
|
||||
// isBeanValidationAvailable = false;
|
||||
// }
|
||||
// // locate the type safe activator class
|
||||
// final Class typeSafeActivatorClass = loadTypeSafeActivatorClass(serviceRegistry);
|
||||
// // todo : if this works out, probably better to simply alter TypeSafeActivator into a single method...
|
||||
// applyRelationalConstraints(modes, isBeanValidationAvailable, typeSafeActivatorClass, props, metadata);
|
||||
// applyHibernateListeners(modes, isBeanValidationAvailable, typeSafeActivatorClass, sessionFactory, serviceRegistry);
|
||||
}
|
||||
|
||||
private Class loadTypeSafeActivatorClass(SessionFactoryServiceRegistry serviceRegistry) {
|
||||
try {
|
||||
return serviceRegistry.getService( ClassLoaderService.class ).classForName( ACTIVATOR_CLASS );
|
||||
}
|
||||
catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void applyRelationalConstraints(
|
||||
Set<ValidationMode> modes,
|
||||
boolean beanValidationAvailable,
|
||||
Class typeSafeActivatorClass,
|
||||
Configuration configuration,
|
||||
Dialect dialect) {
|
||||
if ( ! ConfigurationHelper.getBoolean( APPLY_CONSTRAINTS, configuration.getProperties(), true ) ){
|
||||
LOG.debug( "Skipping application of relational constraints from legacy Hibernate Validator" );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! ( modes.contains( ValidationMode.DDL ) || modes.contains( ValidationMode.AUTO ) ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! beanValidationAvailable ) {
|
||||
if ( modes.contains( ValidationMode.DDL ) ) {
|
||||
throw new HibernateException( "Bean Validation not available in the class path but required in " + MODE_PROPERTY );
|
||||
}
|
||||
else if (modes.contains( ValidationMode.AUTO ) ) {
|
||||
//nothing to activate
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
Method applyDDLMethod = typeSafeActivatorClass.getMethod( DDL_METHOD, Collection.class, Properties.class, Dialect.class );
|
||||
try {
|
||||
applyDDLMethod.invoke(
|
||||
null,
|
||||
configuration.createMappings().getClasses().values(),
|
||||
configuration.getProperties(),
|
||||
dialect
|
||||
);
|
||||
}
|
||||
catch (HibernateException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new HibernateException( "Error applying BeanValidation relational constraints", e );
|
||||
}
|
||||
}
|
||||
catch (HibernateException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new HibernateException( "Unable to locate TypeSafeActivator#applyDDL method", e );
|
||||
}
|
||||
}
|
||||
|
||||
// private void applyRelationalConstraints( Set<ValidationMode> modes,
|
||||
// boolean beanValidationAvailable,
|
||||
// Class typeSafeActivatorClass,
|
||||
// Properties properties,
|
||||
// MetadataImplementor metadata ) {
|
||||
// if (!ConfigurationHelper.getBoolean(APPLY_CONSTRAINTS, properties, true)){
|
||||
// LOG.debug("Skipping application of relational constraints from legacy Hibernate Validator");
|
||||
// return;
|
||||
// }
|
||||
// if (!(modes.contains(ValidationMode.DDL) || modes.contains(ValidationMode.AUTO))) return;
|
||||
// if (!beanValidationAvailable) {
|
||||
// if (modes.contains(ValidationMode.DDL))
|
||||
// throw new HibernateException("Bean Validation not available in the class path but required in " + MODE_PROPERTY);
|
||||
// if(modes.contains(ValidationMode.AUTO)) return; //nothing to activate
|
||||
// }
|
||||
// try {
|
||||
// Method applyDDLMethod = typeSafeActivatorClass.getMethod(DDL_METHOD, Iterable.class, Properties.class, ClassLoaderService.class);
|
||||
// try {
|
||||
// applyDDLMethod.invoke(null, metadata.getEntityBindings(), properties,
|
||||
// metadata.getServiceRegistry().getService(ClassLoaderService.class));
|
||||
// } catch (HibernateException error) {
|
||||
// throw error;
|
||||
// } catch (Exception error) {
|
||||
// throw new HibernateException("Error applying BeanValidation relational constraints", error);
|
||||
// }
|
||||
// } catch (HibernateException error) {
|
||||
// throw error;
|
||||
// } catch (Exception error) {
|
||||
// throw new HibernateException("Unable to locate TypeSafeActivator#applyDDL method", error);
|
||||
// }
|
||||
// }
|
||||
|
||||
private void applyHibernateListeners(
|
||||
Set<ValidationMode> modes,
|
||||
boolean beanValidationAvailable,
|
||||
Class typeSafeActivatorClass,
|
||||
Configuration configuration,
|
||||
SessionFactoryImplementor sessionFactory,
|
||||
SessionFactoryServiceRegistry serviceRegistry) {
|
||||
// de-activate not-null tracking at the core level when Bean Validation is present unless the user explicitly
|
||||
// asks for it
|
||||
if ( configuration.getProperty( Environment.CHECK_NULLABILITY ) == null ) {
|
||||
sessionFactory.getSettings().setCheckNullability( false );
|
||||
}
|
||||
|
||||
if ( ! ( modes.contains( ValidationMode.CALLBACK ) || modes.contains( ValidationMode.AUTO ) ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! beanValidationAvailable ) {
|
||||
if ( modes.contains( ValidationMode.CALLBACK ) ) {
|
||||
throw new HibernateException( "Bean Validation not available in the class path but required in " + MODE_PROPERTY );
|
||||
}
|
||||
else if (modes.contains( ValidationMode.AUTO ) ) {
|
||||
//nothing to activate
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
Method activateMethod = typeSafeActivatorClass.getMethod( ACTIVATE_METHOD, EventListenerRegistry.class, Configuration.class );
|
||||
try {
|
||||
activateMethod.invoke(
|
||||
null,
|
||||
serviceRegistry.getService( EventListenerRegistry.class ),
|
||||
configuration
|
||||
);
|
||||
}
|
||||
catch (HibernateException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new HibernateException( "Error applying BeanValidation relational constraints", e );
|
||||
}
|
||||
}
|
||||
catch (HibernateException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new HibernateException( "Unable to locate TypeSafeActivator#applyDDL method", e );
|
||||
}
|
||||
}
|
||||
|
||||
// private void applyHibernateListeners( Set<ValidationMode> modes,
|
||||
// boolean beanValidationAvailable,
|
||||
// Class typeSafeActivatorClass,
|
||||
// SessionFactoryImplementor sessionFactory,
|
||||
// SessionFactoryServiceRegistry serviceRegistry ) {
|
||||
// // de-activate not-null tracking at the core level when Bean Validation is present unless the user explicitly
|
||||
// // asks for it
|
||||
// if (sessionFactory.getProperties().getProperty(Environment.CHECK_NULLABILITY) == null)
|
||||
// sessionFactory.getSettings().setCheckNullability( false );
|
||||
// if (!(modes.contains( ValidationMode.CALLBACK) || modes.contains(ValidationMode.AUTO))) return;
|
||||
// if (!beanValidationAvailable) {
|
||||
// if (modes.contains(ValidationMode.CALLBACK))
|
||||
// throw new HibernateException("Bean Validation not available in the class path but required in " + MODE_PROPERTY);
|
||||
// if (modes.contains(ValidationMode.AUTO)) return; //nothing to activate
|
||||
// }
|
||||
// try {
|
||||
// Method activateMethod = typeSafeActivatorClass.getMethod(ACTIVATE_METHOD, EventListenerRegistry.class);
|
||||
// try {
|
||||
// activateMethod.invoke(null, serviceRegistry.getService(EventListenerRegistry.class));
|
||||
// }
|
||||
// catch (HibernateException e) {
|
||||
// throw e;
|
||||
// }
|
||||
// catch (Exception e) {
|
||||
// throw new HibernateException( "Error applying BeanValidation relational constraints", e );
|
||||
// }
|
||||
// }
|
||||
// catch (HibernateException e) {
|
||||
// throw e;
|
||||
// }
|
||||
// catch (Exception e) {
|
||||
// throw new HibernateException( "Unable to locate TypeSafeActivator#applyDDL method", e );
|
||||
// }
|
||||
// }
|
||||
|
||||
// Because the javax validation classes might not be on the runtime classpath
|
||||
private static enum ValidationMode {
|
||||
AUTO,
|
||||
CALLBACK,
|
||||
NONE,
|
||||
DDL;
|
||||
|
||||
public static Set<ValidationMode> getModes(Object modeProperty) {
|
||||
Set<ValidationMode> modes = new HashSet<ValidationMode>(3);
|
||||
if (modeProperty == null) {
|
||||
modes.add(ValidationMode.AUTO);
|
||||
}
|
||||
else {
|
||||
final String[] modesInString = modeProperty.toString().split( "," );
|
||||
for ( String modeInString : modesInString ) {
|
||||
modes.add( getMode(modeInString) );
|
||||
}
|
||||
}
|
||||
if ( modes.size() > 1 && ( modes.contains( ValidationMode.AUTO ) || modes.contains( ValidationMode.NONE ) ) ) {
|
||||
StringBuilder message = new StringBuilder( "Incompatible validation modes mixed: " );
|
||||
for (ValidationMode mode : modes) {
|
||||
message.append( mode ).append( ", " );
|
||||
}
|
||||
throw new HibernateException( message.substring( 0, message.length() - 2 ) );
|
||||
}
|
||||
public Set<ValidationMode> getValidationModes() {
|
||||
return modes;
|
||||
}
|
||||
|
||||
private static ValidationMode getMode(String modeProperty) {
|
||||
if (modeProperty == null || modeProperty.length() == 0) {
|
||||
return AUTO;
|
||||
@Override
|
||||
public Configuration getConfiguration() {
|
||||
return configuration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SessionFactoryImplementor getSessionFactory() {
|
||||
return sessionFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SessionFactoryServiceRegistry getServiceRegistry() {
|
||||
return serviceRegistry;
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
activateMethod.invoke( null, activationContext );
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
if ( HibernateException.class.isInstance( e.getTargetException() ) ) {
|
||||
throw ( (HibernateException) e.getTargetException() );
|
||||
}
|
||||
throw new IntegrationException( "Error activating Bean Validation integration", e.getTargetException() );
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new IntegrationException( "Error activating Bean Validation integration", e );
|
||||
}
|
||||
}
|
||||
catch (NoSuchMethodException e) {
|
||||
throw new HibernateException( "Unable to locate TypeSafeActivator#activate method", e );
|
||||
}
|
||||
}
|
||||
else {
|
||||
// otherwise check the validation modes
|
||||
// todo : in many ways this duplicates thew checks done on the TypeSafeActivator when a ValidatorFactory could not be obtained
|
||||
validateMissingBeanValidationApi( modes );
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isBeanValidationApiAvailable(ClassLoaderService classLoaderService) {
|
||||
try {
|
||||
return valueOf( modeProperty.trim().toUpperCase() );
|
||||
classLoaderService.classForName( BV_CHECK_CLASS );
|
||||
return true;
|
||||
}
|
||||
catch ( IllegalArgumentException e ) {
|
||||
throw new HibernateException( "Unknown validation mode in " + MODE_PROPERTY + ": " + modeProperty );
|
||||
catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to validate the case when the Bean Validation API is not available.
|
||||
*
|
||||
* @param modes The requested validation modes.
|
||||
*/
|
||||
private void validateMissingBeanValidationApi(Set<ValidationMode> modes) {
|
||||
if ( modes.contains( ValidationMode.CALLBACK ) ) {
|
||||
throw new IntegrationException( "Bean Validation API was not available, but 'callback' validation was requested" );
|
||||
}
|
||||
if ( modes.contains( ValidationMode.DDL ) ) {
|
||||
throw new IntegrationException( "Bean Validation API was not available, but 'ddl' validation was requested" );
|
||||
}
|
||||
}
|
||||
|
||||
private Class loadTypeSafeActivatorClass(ClassLoaderService classLoaderService) {
|
||||
try {
|
||||
return classLoaderService.classForName( ACTIVATOR_CLASS_NAME );
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new HibernateException( "Unable to load TypeSafeActivator class", e );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void integrate(
|
||||
MetadataImplementor metadata,
|
||||
SessionFactoryImplementor sessionFactory,
|
||||
SessionFactoryServiceRegistry serviceRegistry ) {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cfg.beanvalidation;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
|
||||
/**
|
||||
* Indicates a problem integrating Hibernate and the Bean Validation spec.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class IntegrationException extends HibernateException {
|
||||
public IntegrationException(String message) {
|
||||
super( message );
|
||||
}
|
||||
|
||||
public IntegrationException(String message, Throwable root) {
|
||||
super( message, root );
|
||||
}
|
||||
}
|
|
@ -23,15 +23,6 @@
|
|||
*/
|
||||
package org.hibernate.cfg.beanvalidation;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
import javax.validation.Validation;
|
||||
import javax.validation.ValidatorFactory;
|
||||
import javax.validation.constraints.Digits;
|
||||
|
@ -42,19 +33,29 @@ import javax.validation.constraints.Size;
|
|||
import javax.validation.metadata.BeanDescriptor;
|
||||
import javax.validation.metadata.ConstraintDescriptor;
|
||||
import javax.validation.metadata.PropertyDescriptor;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.event.service.spi.EventListenerRegistry;
|
||||
import org.hibernate.event.spi.EventType;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.ReflectHelper;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||
import org.hibernate.mapping.Column;
|
||||
import org.hibernate.mapping.Component;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
|
@ -64,6 +65,7 @@ import org.hibernate.mapping.SingleTableSubclass;
|
|||
/**
|
||||
* @author Emmanuel Bernard
|
||||
* @author Hardy Ferentschik
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
class TypeSafeActivator {
|
||||
|
||||
|
@ -71,51 +73,97 @@ class TypeSafeActivator {
|
|||
|
||||
private static final String FACTORY_PROPERTY = "javax.persistence.validation.factory";
|
||||
|
||||
/**
|
||||
* Used to validate a supplied ValidatorFactory instance as being castable to ValidatorFactory.
|
||||
*
|
||||
* @param object The supplied ValidatorFactory instance.
|
||||
*/
|
||||
@SuppressWarnings( {"UnusedDeclaration"})
|
||||
public static void validateFactory(Object object) {
|
||||
public static void validateSuppliedFactory(Object object) {
|
||||
if ( ! ValidatorFactory.class.isInstance( object ) ) {
|
||||
throw new HibernateException(
|
||||
throw new IntegrationException(
|
||||
"Given object was not an instance of " + ValidatorFactory.class.getName()
|
||||
+ "[" + object.getClass().getName() + "]"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public static void activate(ActivationContext activationContext) {
|
||||
final Properties properties = activationContext.getConfiguration().getProperties();
|
||||
final ValidatorFactory factory;
|
||||
try {
|
||||
factory = getValidatorFactory( properties );
|
||||
}
|
||||
catch (IntegrationException e) {
|
||||
if ( activationContext.getValidationModes().contains( ValidationMode.CALLBACK ) ) {
|
||||
throw new IntegrationException( "Bean Validation provider was not available, but 'callback' validation was requested", e );
|
||||
}
|
||||
if ( activationContext.getValidationModes().contains( ValidationMode.DDL ) ) {
|
||||
throw new IntegrationException( "Bean Validation provider was not available, but 'ddl' validation was requested", e );
|
||||
}
|
||||
|
||||
LOG.debug( "Unable to acquire Bean Validation ValidatorFactory, skipping activation" );
|
||||
return;
|
||||
}
|
||||
|
||||
applyRelationalConstraints( factory, activationContext );
|
||||
|
||||
applyCallbackListeners( factory, activationContext );
|
||||
}
|
||||
|
||||
@SuppressWarnings( {"UnusedDeclaration"})
|
||||
public static void activateBeanValidation(EventListenerRegistry listenerRegistry, Configuration configuration) {
|
||||
final Properties properties = configuration.getProperties();
|
||||
ValidatorFactory factory = getValidatorFactory( properties );
|
||||
BeanValidationEventListener listener = new BeanValidationEventListener(
|
||||
factory, properties
|
||||
public static void applyCallbackListeners(ValidatorFactory validatorFactory, ActivationContext activationContext) {
|
||||
final Set<ValidationMode> modes = activationContext.getValidationModes();
|
||||
if ( ! ( modes.contains( ValidationMode.CALLBACK ) || modes.contains( ValidationMode.AUTO ) ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// de-activate not-null tracking at the core level when Bean Validation is present unless the user explicitly
|
||||
// asks for it
|
||||
if ( activationContext.getConfiguration().getProperty( Environment.CHECK_NULLABILITY ) == null ) {
|
||||
activationContext.getSessionFactory().getSettings().setCheckNullability( false );
|
||||
}
|
||||
|
||||
final BeanValidationEventListener listener = new BeanValidationEventListener(
|
||||
validatorFactory,
|
||||
activationContext.getConfiguration().getProperties()
|
||||
);
|
||||
|
||||
final EventListenerRegistry listenerRegistry = activationContext.getServiceRegistry()
|
||||
.getService( EventListenerRegistry.class );
|
||||
|
||||
listenerRegistry.addDuplicationStrategy( DuplicationStrategyImpl.INSTANCE );
|
||||
|
||||
listenerRegistry.appendListeners( EventType.PRE_INSERT, listener );
|
||||
listenerRegistry.appendListeners( EventType.PRE_UPDATE, listener );
|
||||
listenerRegistry.appendListeners( EventType.PRE_DELETE, listener );
|
||||
|
||||
listener.initialize( configuration );
|
||||
listener.initialize( activationContext.getConfiguration() );
|
||||
}
|
||||
|
||||
// public static void activateBeanValidation( EventListenerRegistry listenerRegistry ) {
|
||||
// final Properties properties = configuration.getProperties();
|
||||
// ValidatorFactory factory = getValidatorFactory( properties );
|
||||
// BeanValidationEventListener listener = new BeanValidationEventListener(
|
||||
// factory, properties
|
||||
// );
|
||||
//
|
||||
// listenerRegistry.addDuplicationStrategy( DuplicationStrategyImpl.INSTANCE );
|
||||
//
|
||||
// listenerRegistry.appendListeners( EventType.PRE_INSERT, listener );
|
||||
// listenerRegistry.appendListeners( EventType.PRE_UPDATE, listener );
|
||||
// listenerRegistry.appendListeners( EventType.PRE_DELETE, listener );
|
||||
//
|
||||
// listener.initialize( configuration );
|
||||
// }
|
||||
@SuppressWarnings({"unchecked", "UnusedParameters"})
|
||||
private static void applyRelationalConstraints(ValidatorFactory factory, ActivationContext activationContext) {
|
||||
final Properties properties = activationContext.getConfiguration().getProperties();
|
||||
if ( ! ConfigurationHelper.getBoolean( BeanValidationIntegrator.APPLY_CONSTRAINTS, properties, true ) ){
|
||||
LOG.debug( "Skipping application of relational constraints from legacy Hibernate Validator" );
|
||||
return;
|
||||
}
|
||||
|
||||
final Set<ValidationMode> modes = activationContext.getValidationModes();
|
||||
if ( ! ( modes.contains( ValidationMode.DDL ) || modes.contains( ValidationMode.AUTO ) ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
applyRelationalConstraints(
|
||||
activationContext.getConfiguration().createMappings().getClasses().values(),
|
||||
properties,
|
||||
activationContext.getServiceRegistry().getService( JdbcServices.class ).getDialect()
|
||||
);
|
||||
}
|
||||
|
||||
@SuppressWarnings( {"UnusedDeclaration"})
|
||||
public static void applyDDL(Collection<PersistentClass> persistentClasses, Properties properties, Dialect dialect) {
|
||||
public static void applyRelationalConstraints(Collection<PersistentClass> persistentClasses, Properties properties, Dialect dialect) {
|
||||
ValidatorFactory factory = getValidatorFactory( properties );
|
||||
Class<?>[] groupsArray = new GroupsPerOperation( properties ).get( GroupsPerOperation.Operation.DDL );
|
||||
Set<Class<?>> groups = new HashSet<Class<?>>( Arrays.asList( groupsArray ) );
|
||||
|
@ -143,26 +191,8 @@ class TypeSafeActivator {
|
|||
}
|
||||
}
|
||||
|
||||
// public static void applyDDL( Iterable<EntityBinding> bindings,
|
||||
// Properties properties,
|
||||
// ClassLoaderService classLoaderService ) {
|
||||
// ValidatorFactory factory = getValidatorFactory(properties);
|
||||
// Class<?>[] groupsArray = new GroupsPerOperation(properties).get(GroupsPerOperation.Operation.DDL);
|
||||
// Set<Class<?>> groups = new HashSet<Class<?>>(Arrays.asList(groupsArray));
|
||||
// for (EntityBinding binding : bindings) {
|
||||
// final String className = binding.getEntity().getClassName();
|
||||
// if (className == null || className.length() == 0) continue;
|
||||
// try {
|
||||
// applyDDL("", binding, classLoaderService.classForName(className), factory, groups, true);
|
||||
// } catch (ClassLoadingException error) {
|
||||
// throw new AssertionFailure("Entity class not found", error);
|
||||
// } catch (Exception error) {
|
||||
// LOG.unableToApplyConstraints(className, error);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
private static void applyDDL(String prefix,
|
||||
private static void applyDDL(
|
||||
String prefix,
|
||||
PersistentClass persistentClass,
|
||||
Class<?> clazz,
|
||||
ValidatorFactory factory,
|
||||
|
@ -200,30 +230,13 @@ class TypeSafeActivator {
|
|||
}
|
||||
}
|
||||
|
||||
// private static void applyDDL( String prefix,
|
||||
// EntityBinding binding,
|
||||
// Class<?> clazz,
|
||||
// ValidatorFactory factory,
|
||||
// Set<Class<?>> groups,
|
||||
// boolean activateNotNull ) {
|
||||
// final BeanDescriptor descriptor = factory.getValidator().getConstraintsForClass(clazz);
|
||||
// //no bean level constraints can be applied, go to the properties
|
||||
// for (PropertyDescriptor propertyDesc : descriptor.getConstrainedProperties()) {
|
||||
// AttributeBinding attrBinding = findAttributeBindingByName(binding, prefix + propertyDesc.getPropertyName());
|
||||
// if (attrBinding != null) {
|
||||
// applyConstraints(propertyDesc.getConstraintDescriptors(), attrBinding, propertyDesc, groups, activateNotNull);
|
||||
// // TODO: Handle composite attributes when possible
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
private static boolean applyConstraints(Set<ConstraintDescriptor<?>> constraintDescriptors,
|
||||
private static boolean applyConstraints(
|
||||
Set<ConstraintDescriptor<?>> constraintDescriptors,
|
||||
Property property,
|
||||
PropertyDescriptor propertyDesc,
|
||||
Set<Class<?>> groups,
|
||||
boolean canApplyNotNull,
|
||||
Dialect dialect
|
||||
) {
|
||||
Dialect dialect) {
|
||||
boolean hasNotNull = false;
|
||||
for ( ConstraintDescriptor<?> descriptor : constraintDescriptors ) {
|
||||
if ( groups != null && Collections.disjoint( descriptor.getGroups(), groups ) ) {
|
||||
|
@ -256,37 +269,6 @@ class TypeSafeActivator {
|
|||
return hasNotNull;
|
||||
}
|
||||
|
||||
// private static boolean applyConstraints( Set<ConstraintDescriptor<?>> constraintDescriptors,
|
||||
// AttributeBinding attributeBinding,
|
||||
// PropertyDescriptor propertyDesc,
|
||||
// Set<Class<?>> groups,
|
||||
// boolean canApplyNotNull ) {
|
||||
// boolean hasNotNull = false;
|
||||
// for ( ConstraintDescriptor<?> descriptor : constraintDescriptors ) {
|
||||
// if (groups != null && Collections.disjoint(descriptor.getGroups(), groups)) continue;
|
||||
// if (canApplyNotNull) hasNotNull = hasNotNull || applyNotNull(attributeBinding, descriptor);
|
||||
//
|
||||
// // apply bean validation specific constraints
|
||||
// applyDigits( property, descriptor );
|
||||
// applySize( property, descriptor, propertyDesc );
|
||||
// applyMin( property, descriptor );
|
||||
// applyMax( property, descriptor );
|
||||
//
|
||||
// // apply hibernate validator specific constraints - we cannot import any HV specific classes though!
|
||||
// // no need to check explicitly for @Range. @Range is a composed constraint using @Min and @Max which
|
||||
// // will be taken care later
|
||||
// applyLength( property, descriptor, propertyDesc );
|
||||
//
|
||||
// // pass an empty set as composing constraints inherit the main constraint and thus are matching already
|
||||
// hasNotNull = hasNotNull || applyConstraints(
|
||||
// descriptor.getComposingConstraints(),
|
||||
// property, propertyDesc, null,
|
||||
// canApplyNotNull
|
||||
// );
|
||||
// }
|
||||
// return hasNotNull;
|
||||
// }
|
||||
|
||||
private static void applyMin(Property property, ConstraintDescriptor<?> descriptor, Dialect dialect) {
|
||||
if ( Min.class.equals( descriptor.getAnnotation().annotationType() ) ) {
|
||||
@SuppressWarnings("unchecked")
|
||||
|
@ -339,26 +321,6 @@ class TypeSafeActivator {
|
|||
return hasNotNull;
|
||||
}
|
||||
|
||||
// private static boolean applyNotNull( AttributeBinding attributeBinding,
|
||||
// ConstraintDescriptor<?> descriptor ) {
|
||||
// boolean hasNotNull = false;
|
||||
// if (NotNull.class.equals(descriptor.getAnnotation().annotationType())) {
|
||||
// if ( !( attributeBinding.getPersistentClass() instanceof SingleTableSubclass ) ) {
|
||||
// //single table should not be forced to null
|
||||
// if ( !property.isComposite() ) { //composite should not add not-null on all columns
|
||||
// @SuppressWarnings( "unchecked" )
|
||||
// Iterator<Column> iter = property.getColumnIterator();
|
||||
// while ( iter.hasNext() ) {
|
||||
// iter.next().setNullable( false );
|
||||
// hasNotNull = true;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// hasNotNull = true;
|
||||
// }
|
||||
// return hasNotNull;
|
||||
// }
|
||||
|
||||
private static void applyDigits(Property property, ConstraintDescriptor<?> descriptor) {
|
||||
if ( Digits.class.equals( descriptor.getAnnotation().annotationType() ) ) {
|
||||
@SuppressWarnings("unchecked")
|
||||
|
@ -462,44 +424,6 @@ class TypeSafeActivator {
|
|||
return property;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * @param entityBinding
|
||||
// * @param attrName
|
||||
// * @return the attribute by path in a recursive way, including EntityIdentifier in the loop if attrName is
|
||||
// * <code>null</code>. If attrName is <code>null</code> or empty, the EntityIdentifier is returned
|
||||
// */
|
||||
// private static AttributeBinding findAttributeBindingByName( EntityBinding entityBinding,
|
||||
// String attrName ) {
|
||||
// AttributeBinding attrBinding = null;
|
||||
// EntityIdentifier identifier = entityBinding.getHierarchyDetails().getEntityIdentifier();
|
||||
// BasicAttributeBinding idAttrBinding = identifier.getValueBinding();
|
||||
// String idAttrName = idAttrBinding != null ? idAttrBinding.getAttribute().getName() : null;
|
||||
// try {
|
||||
// if (attrName == null || attrName.length() == 0 || attrName.equals(idAttrName)) attrBinding = idAttrBinding; // default to id
|
||||
// else {
|
||||
// if (attrName.indexOf(idAttrName + ".") == 0) {
|
||||
// attrBinding = idAttrBinding;
|
||||
// attrName = attrName.substring(idAttrName.length() + 1);
|
||||
// }
|
||||
// for (StringTokenizer st = new StringTokenizer(attrName, "."); st.hasMoreElements();) {
|
||||
// String element = st.nextToken();
|
||||
// if (attrBinding == null) attrBinding = entityBinding.locateAttributeBinding(element);
|
||||
// else return null; // TODO: if (attrBinding.isComposite()) ...
|
||||
// }
|
||||
// }
|
||||
// } catch (MappingException error) {
|
||||
// try {
|
||||
// //if we do not find it try to check the identifier mapper
|
||||
// if (!identifier.isIdentifierMapper()) return null;
|
||||
// // TODO: finish once composite/embedded/component IDs get worked out
|
||||
// }
|
||||
// catch ( MappingException ee ) {
|
||||
// return null;
|
||||
// }
|
||||
// }
|
||||
// return attrBinding;
|
||||
// }
|
||||
|
||||
private static ValidatorFactory getValidatorFactory(Map<Object, Object> properties) {
|
||||
ValidatorFactory factory = null;
|
||||
if ( properties != null ) {
|
||||
|
@ -509,7 +433,7 @@ class TypeSafeActivator {
|
|||
factory = ValidatorFactory.class.cast( unsafeProperty );
|
||||
}
|
||||
catch ( ClassCastException e ) {
|
||||
throw new HibernateException(
|
||||
throw new IntegrationException(
|
||||
"Property " + FACTORY_PROPERTY
|
||||
+ " should contain an object of type " + ValidatorFactory.class.getName()
|
||||
);
|
||||
|
@ -521,7 +445,7 @@ class TypeSafeActivator {
|
|||
factory = Validation.buildDefaultValidatorFactory();
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
throw new HibernateException( "Unable to build the default ValidatorFactory", e );
|
||||
throw new IntegrationException( "Unable to build the default ValidatorFactory", e );
|
||||
}
|
||||
}
|
||||
return factory;
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cfg.beanvalidation;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
|
||||
/**
|
||||
* Duplicates the javax.validation enum (because javax validation might not be on the runtime classpath)
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public enum ValidationMode {
|
||||
AUTO( "auto" ),
|
||||
CALLBACK( "callback" ),
|
||||
NONE( "none" ),
|
||||
DDL( "ddl" );
|
||||
|
||||
private final String externalForm;
|
||||
|
||||
private ValidationMode(String externalForm) {
|
||||
this.externalForm = externalForm;
|
||||
}
|
||||
|
||||
public static Set<ValidationMode> getModes(Object modeProperty) {
|
||||
Set<ValidationMode> modes = new HashSet<ValidationMode>(3);
|
||||
if (modeProperty == null) {
|
||||
modes.add( ValidationMode.AUTO );
|
||||
}
|
||||
else {
|
||||
final String[] modesInString = modeProperty.toString().split( "," );
|
||||
for ( String modeInString : modesInString ) {
|
||||
modes.add( getMode(modeInString) );
|
||||
}
|
||||
}
|
||||
if ( modes.size() > 1 && ( modes.contains( ValidationMode.AUTO ) || modes.contains( ValidationMode.NONE ) ) ) {
|
||||
throw new HibernateException( "Incompatible validation modes mixed: " + loggable( modes ) );
|
||||
}
|
||||
return modes;
|
||||
}
|
||||
|
||||
private static ValidationMode getMode(String modeProperty) {
|
||||
if (modeProperty == null || modeProperty.length() == 0) {
|
||||
return AUTO;
|
||||
}
|
||||
else {
|
||||
try {
|
||||
return valueOf( modeProperty.trim().toUpperCase() );
|
||||
}
|
||||
catch ( IllegalArgumentException e ) {
|
||||
throw new HibernateException( "Unknown validation mode in " + BeanValidationIntegrator.MODE_PROPERTY + ": " + modeProperty );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static String loggable(Set<ValidationMode> modes) {
|
||||
if ( modes == null || modes.isEmpty() ) {
|
||||
return "[<empty>]";
|
||||
}
|
||||
StringBuilder buffer = new StringBuilder( "[" );
|
||||
String sep = "";
|
||||
for ( ValidationMode mode : modes ) {
|
||||
buffer.append( sep ).append( mode.externalForm );
|
||||
sep = ", ";
|
||||
}
|
||||
return buffer.append( "]" ).toString();
|
||||
}
|
||||
}
|
|
@ -1616,4 +1616,7 @@ public interface CoreMessageLogger extends BasicLogger {
|
|||
)
|
||||
void explicitSkipLockedLockCombo();
|
||||
|
||||
@LogMessage(level = INFO)
|
||||
@Message( value = "'javax.persistence.validation.mode' named multiple values : %s", id = 448 )
|
||||
void multipleValidationModes(String modes);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue