Skip to content

Commit c44afee

Browse files
committed
HHH-9905 - JPA integration property "javax.persistence.validation.factory" not passed along to TypeSafeActivator
1 parent d50258f commit c44afee

File tree

1 file changed

+88
-34
lines changed

1 file changed

+88
-34
lines changed

hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/TypeSafeActivator.java

Lines changed: 88 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import java.util.Collections;
1212
import java.util.HashSet;
1313
import java.util.Iterator;
14+
import java.util.Locale;
1415
import java.util.Map;
1516
import java.util.Set;
1617
import java.util.StringTokenizer;
@@ -31,6 +32,7 @@
3132
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
3233
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
3334
import org.hibernate.boot.spi.ClassLoaderAccess;
35+
import org.hibernate.boot.spi.SessionFactoryOptions;
3436
import org.hibernate.cfg.Environment;
3537
import org.hibernate.dialect.Dialect;
3638
import org.hibernate.engine.config.spi.ConfigurationService;
@@ -77,10 +79,9 @@ public static void validateSuppliedFactory(Object object) {
7779

7880
@SuppressWarnings("UnusedDeclaration")
7981
public static void activate(ActivationContext activationContext) {
80-
final ConfigurationService cfgService = activationContext.getServiceRegistry().getService( ConfigurationService.class );
8182
final ValidatorFactory factory;
8283
try {
83-
factory = getValidatorFactory( cfgService.getSettings() );
84+
factory = getValidatorFactory( activationContext );
8485
}
8586
catch (IntegrationException e) {
8687
if ( activationContext.getValidationModes().contains( ValidationMode.CALLBACK ) ) {
@@ -112,7 +113,7 @@ public static void applyCallbackListeners(ValidatorFactory validatorFactory, Act
112113
// de-activate not-null tracking at the core level when Bean Validation is present unless the user explicitly
113114
// asks for it
114115
if ( cfgService.getSettings().get( Environment.CHECK_NULLABILITY ) == null ) {
115-
activationContext.getSessionFactory().getSettings().setCheckNullability( false );
116+
activationContext.getSessionFactory().getSessionFactoryOptions().setCheckNullability( false );
116117
}
117118

118119
final BeanValidationEventListener listener = new BeanValidationEventListener(
@@ -151,7 +152,10 @@ private static void applyRelationalConstraints(ValidatorFactory factory, Activat
151152
activationContext.getMetadata().getEntityBindings(),
152153
cfgService.getSettings(),
153154
activationContext.getServiceRegistry().getService( JdbcServices.class ).getDialect(),
154-
new ClassLoaderAccessImpl( null, activationContext.getServiceRegistry().getService( ClassLoaderService.class ) )
155+
new ClassLoaderAccessImpl(
156+
null,
157+
activationContext.getServiceRegistry().getService( ClassLoaderService.class )
158+
)
155159
);
156160
}
157161

@@ -303,16 +307,17 @@ private static void applySQLCheck(Column col, String checkConstraint) {
303307
col.setCheckConstraint( checkConstraint );
304308
}
305309

310+
@SuppressWarnings("unchecked")
306311
private static boolean applyNotNull(Property property, ConstraintDescriptor<?> descriptor) {
307312
boolean hasNotNull = false;
308313
if ( NotNull.class.equals( descriptor.getAnnotation().annotationType() ) ) {
309314
// single table inheritance should not be forced to null due to shared state
310315
if ( !( property.getPersistentClass() instanceof SingleTableSubclass ) ) {
311316
//composite should not add not-null on all columns
312317
if ( !property.isComposite() ) {
313-
final Iterator<Selectable> iter = property.getColumnIterator();
314-
while ( iter.hasNext() ) {
315-
final Selectable selectable = iter.next();
318+
final Iterator<Selectable> itr = property.getColumnIterator();
319+
while ( itr.hasNext() ) {
320+
final Selectable selectable = itr.next();
316321
if ( Column.class.isInstance( selectable ) ) {
317322
Column.class.cast( selectable ).setNullable( false );
318323
}
@@ -371,10 +376,8 @@ private static void applyLength(Property property, ConstraintDescriptor<?> descr
371376
}
372377

373378
/**
374-
* @param associatedClass
375-
* @param propertyName
376-
* @return the property by path in a recursive way, including IdentifierProperty in the loop if propertyName is
377-
* <code>null</code>. If propertyName is <code>null</code> or empty, the IdentifierProperty is returned
379+
* Locate the property by path in a recursive way, including IdentifierProperty in the loop if propertyName is
380+
* {@code null}. If propertyName is {@code null} or empty, the IdentifierProperty is returned
378381
*/
379382
private static Property findPropertyByName(PersistentClass associatedClass, String propertyName) {
380383
Property property = null;
@@ -434,30 +437,81 @@ private static Property findPropertyByName(PersistentClass associatedClass, Stri
434437
return property;
435438
}
436439

437-
private static ValidatorFactory getValidatorFactory(Map<Object, Object> properties) {
438-
ValidatorFactory factory = null;
439-
if ( properties != null ) {
440-
Object unsafeProperty = properties.get( FACTORY_PROPERTY );
441-
if ( unsafeProperty != null ) {
442-
try {
443-
factory = ValidatorFactory.class.cast( unsafeProperty );
444-
}
445-
catch ( ClassCastException e ) {
446-
throw new IntegrationException(
447-
"Property " + FACTORY_PROPERTY
448-
+ " should contain an object of type " + ValidatorFactory.class.getName()
449-
);
450-
}
451-
}
440+
private static ValidatorFactory getValidatorFactory(ActivationContext activationContext) {
441+
// IMPL NOTE : We can either be provided a ValidatorFactory or make one. We can be provided
442+
// a ValidatorFactory in 2 different ways. So here we "get" a ValidatorFactory in the following order:
443+
// 1) Look into SessionFactoryOptions.getValidatorFactoryReference()
444+
// 2) Look into ConfigurationService
445+
// 3) build a new ValidatorFactory
446+
447+
// 1 - look in SessionFactoryOptions.getValidatorFactoryReference()
448+
ValidatorFactory factory = resolveProvidedFactory( activationContext.getSessionFactory().getSessionFactoryOptions() );
449+
if ( factory != null ) {
450+
return factory;
452451
}
453-
if ( factory == null ) {
454-
try {
455-
factory = Validation.buildDefaultValidatorFactory();
456-
}
457-
catch ( Exception e ) {
458-
throw new IntegrationException( "Unable to build the default ValidatorFactory", e );
459-
}
452+
453+
// 2 - look in ConfigurationService
454+
factory = resolveProvidedFactory( activationContext.getServiceRegistry().getService( ConfigurationService.class ) );
455+
if ( factory != null ) {
456+
return factory;
457+
}
458+
459+
// 3 - build our own
460+
try {
461+
return Validation.buildDefaultValidatorFactory();
462+
}
463+
catch ( Exception e ) {
464+
throw new IntegrationException( "Unable to build the default ValidatorFactory", e );
465+
}
466+
}
467+
468+
private static ValidatorFactory resolveProvidedFactory(SessionFactoryOptions options) {
469+
final Object validatorFactoryReference = options.getValidatorFactoryReference();
470+
471+
if ( validatorFactoryReference == null ) {
472+
return null;
473+
}
474+
475+
try {
476+
return ValidatorFactory.class.cast( validatorFactoryReference );
477+
}
478+
catch ( ClassCastException e ) {
479+
throw new IntegrationException(
480+
String.format(
481+
Locale.ENGLISH,
482+
"ValidatorFactory reference (provided via %s) was not castable to %s : %s",
483+
SessionFactoryOptions.class.getName(),
484+
ValidatorFactory.class.getName(),
485+
validatorFactoryReference.getClass().getName()
486+
)
487+
);
460488
}
461-
return factory;
489+
}
490+
491+
@SuppressWarnings("unchecked")
492+
private static ValidatorFactory resolveProvidedFactory(ConfigurationService cfgService) {
493+
return cfgService.getSetting(
494+
FACTORY_PROPERTY,
495+
new ConfigurationService.Converter<ValidatorFactory>() {
496+
@Override
497+
public ValidatorFactory convert(Object value) {
498+
try {
499+
return ValidatorFactory.class.cast( value );
500+
}
501+
catch ( ClassCastException e ) {
502+
throw new IntegrationException(
503+
String.format(
504+
Locale.ENGLISH,
505+
"ValidatorFactory reference (provided via `%s` setting) was not castable to %s : %s",
506+
FACTORY_PROPERTY,
507+
ValidatorFactory.class.getName(),
508+
value.getClass().getName()
509+
)
510+
);
511+
}
512+
}
513+
},
514+
null
515+
);
462516
}
463517
}

0 commit comments

Comments
 (0)