HHH-9905 - JPA integration property "javax.persistence.validation.factory" not passed along to TypeSafeActivator

This commit is contained in:
Steve Ebersole 2015-07-08 11:01:40 -05:00
parent d50258f424
commit c44afee6dc
1 changed files with 88 additions and 34 deletions

View File

@ -11,6 +11,7 @@ import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.StringTokenizer; import java.util.StringTokenizer;
@ -31,6 +32,7 @@ import org.hibernate.boot.internal.ClassLoaderAccessImpl;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException; import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
import org.hibernate.boot.spi.ClassLoaderAccess; import org.hibernate.boot.spi.ClassLoaderAccess;
import org.hibernate.boot.spi.SessionFactoryOptions;
import org.hibernate.cfg.Environment; import org.hibernate.cfg.Environment;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.engine.config.spi.ConfigurationService; import org.hibernate.engine.config.spi.ConfigurationService;
@ -77,10 +79,9 @@ class TypeSafeActivator {
@SuppressWarnings("UnusedDeclaration") @SuppressWarnings("UnusedDeclaration")
public static void activate(ActivationContext activationContext) { public static void activate(ActivationContext activationContext) {
final ConfigurationService cfgService = activationContext.getServiceRegistry().getService( ConfigurationService.class );
final ValidatorFactory factory; final ValidatorFactory factory;
try { try {
factory = getValidatorFactory( cfgService.getSettings() ); factory = getValidatorFactory( activationContext );
} }
catch (IntegrationException e) { catch (IntegrationException e) {
if ( activationContext.getValidationModes().contains( ValidationMode.CALLBACK ) ) { if ( activationContext.getValidationModes().contains( ValidationMode.CALLBACK ) ) {
@ -112,7 +113,7 @@ class TypeSafeActivator {
// de-activate not-null tracking at the core level when Bean Validation is present unless the user explicitly // de-activate not-null tracking at the core level when Bean Validation is present unless the user explicitly
// asks for it // asks for it
if ( cfgService.getSettings().get( Environment.CHECK_NULLABILITY ) == null ) { if ( cfgService.getSettings().get( Environment.CHECK_NULLABILITY ) == null ) {
activationContext.getSessionFactory().getSettings().setCheckNullability( false ); activationContext.getSessionFactory().getSessionFactoryOptions().setCheckNullability( false );
} }
final BeanValidationEventListener listener = new BeanValidationEventListener( final BeanValidationEventListener listener = new BeanValidationEventListener(
@ -151,7 +152,10 @@ class TypeSafeActivator {
activationContext.getMetadata().getEntityBindings(), activationContext.getMetadata().getEntityBindings(),
cfgService.getSettings(), cfgService.getSettings(),
activationContext.getServiceRegistry().getService( JdbcServices.class ).getDialect(), activationContext.getServiceRegistry().getService( JdbcServices.class ).getDialect(),
new ClassLoaderAccessImpl( null, activationContext.getServiceRegistry().getService( ClassLoaderService.class ) ) new ClassLoaderAccessImpl(
null,
activationContext.getServiceRegistry().getService( ClassLoaderService.class )
)
); );
} }
@ -303,6 +307,7 @@ class TypeSafeActivator {
col.setCheckConstraint( checkConstraint ); col.setCheckConstraint( checkConstraint );
} }
@SuppressWarnings("unchecked")
private static boolean applyNotNull(Property property, ConstraintDescriptor<?> descriptor) { private static boolean applyNotNull(Property property, ConstraintDescriptor<?> descriptor) {
boolean hasNotNull = false; boolean hasNotNull = false;
if ( NotNull.class.equals( descriptor.getAnnotation().annotationType() ) ) { if ( NotNull.class.equals( descriptor.getAnnotation().annotationType() ) ) {
@ -310,9 +315,9 @@ class TypeSafeActivator {
if ( !( property.getPersistentClass() instanceof SingleTableSubclass ) ) { if ( !( property.getPersistentClass() instanceof SingleTableSubclass ) ) {
//composite should not add not-null on all columns //composite should not add not-null on all columns
if ( !property.isComposite() ) { if ( !property.isComposite() ) {
final Iterator<Selectable> iter = property.getColumnIterator(); final Iterator<Selectable> itr = property.getColumnIterator();
while ( iter.hasNext() ) { while ( itr.hasNext() ) {
final Selectable selectable = iter.next(); final Selectable selectable = itr.next();
if ( Column.class.isInstance( selectable ) ) { if ( Column.class.isInstance( selectable ) ) {
Column.class.cast( selectable ).setNullable( false ); Column.class.cast( selectable ).setNullable( false );
} }
@ -371,10 +376,8 @@ class TypeSafeActivator {
} }
/** /**
* @param associatedClass * Locate the property by path in a recursive way, including IdentifierProperty in the loop if propertyName is
* @param propertyName * {@code null}. If propertyName is {@code null} or empty, the IdentifierProperty is returned
* @return the property by path in a recursive way, including IdentifierProperty in the loop if propertyName is
* <code>null</code>. If propertyName is <code>null</code> or empty, the IdentifierProperty is returned
*/ */
private static Property findPropertyByName(PersistentClass associatedClass, String propertyName) { private static Property findPropertyByName(PersistentClass associatedClass, String propertyName) {
Property property = null; Property property = null;
@ -434,30 +437,81 @@ class TypeSafeActivator {
return property; return property;
} }
private static ValidatorFactory getValidatorFactory(Map<Object, Object> properties) { private static ValidatorFactory getValidatorFactory(ActivationContext activationContext) {
ValidatorFactory factory = null; // IMPL NOTE : We can either be provided a ValidatorFactory or make one. We can be provided
if ( properties != null ) { // a ValidatorFactory in 2 different ways. So here we "get" a ValidatorFactory in the following order:
Object unsafeProperty = properties.get( FACTORY_PROPERTY ); // 1) Look into SessionFactoryOptions.getValidatorFactoryReference()
if ( unsafeProperty != null ) { // 2) Look into ConfigurationService
try { // 3) build a new ValidatorFactory
factory = ValidatorFactory.class.cast( unsafeProperty );
} // 1 - look in SessionFactoryOptions.getValidatorFactoryReference()
catch ( ClassCastException e ) { ValidatorFactory factory = resolveProvidedFactory( activationContext.getSessionFactory().getSessionFactoryOptions() );
throw new IntegrationException( if ( factory != null ) {
"Property " + FACTORY_PROPERTY return factory;
+ " should contain an object of type " + ValidatorFactory.class.getName()
);
}
}
} }
if ( factory == null ) {
try { // 2 - look in ConfigurationService
factory = Validation.buildDefaultValidatorFactory(); factory = resolveProvidedFactory( activationContext.getServiceRegistry().getService( ConfigurationService.class ) );
} if ( factory != null ) {
catch ( Exception e ) { return factory;
throw new IntegrationException( "Unable to build the default ValidatorFactory", e );
}
} }
return factory;
// 3 - build our own
try {
return Validation.buildDefaultValidatorFactory();
}
catch ( Exception e ) {
throw new IntegrationException( "Unable to build the default ValidatorFactory", e );
}
}
private static ValidatorFactory resolveProvidedFactory(SessionFactoryOptions options) {
final Object validatorFactoryReference = options.getValidatorFactoryReference();
if ( validatorFactoryReference == null ) {
return null;
}
try {
return ValidatorFactory.class.cast( validatorFactoryReference );
}
catch ( ClassCastException e ) {
throw new IntegrationException(
String.format(
Locale.ENGLISH,
"ValidatorFactory reference (provided via %s) was not castable to %s : %s",
SessionFactoryOptions.class.getName(),
ValidatorFactory.class.getName(),
validatorFactoryReference.getClass().getName()
)
);
}
}
@SuppressWarnings("unchecked")
private static ValidatorFactory resolveProvidedFactory(ConfigurationService cfgService) {
return cfgService.getSetting(
FACTORY_PROPERTY,
new ConfigurationService.Converter<ValidatorFactory>() {
@Override
public ValidatorFactory convert(Object value) {
try {
return ValidatorFactory.class.cast( value );
}
catch ( ClassCastException e ) {
throw new IntegrationException(
String.format(
Locale.ENGLISH,
"ValidatorFactory reference (provided via `%s` setting) was not castable to %s : %s",
FACTORY_PROPERTY,
ValidatorFactory.class.getName(),
value.getClass().getName()
)
);
}
}
},
null
);
} }
} }