Skip to content

Commit 2065108

Browse files
marko-bekhtagsmet
authored andcommitted
HV-1949 Load constraint validators from a Service Loader first
- since there's no control over them and we cannot override a validator coming from a service loader
1 parent 7c285c9 commit 2065108

File tree

4 files changed

+66
-8
lines changed

4 files changed

+66
-8
lines changed

engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineExternalClassLoader;
1818
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineFailFast;
1919
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineScriptEvaluatorFactory;
20+
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineServiceLoadedConstraintMappings;
2021
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineTemporalValidationTolerance;
2122
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineTraversableResolverResultCacheEnabled;
2223
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.logValidatorFactoryScopedConfiguration;
@@ -152,6 +153,18 @@ public PredefinedScopeValidatorFactoryImpl(ConfigurationState configurationState
152153
ExecutableHelper executableHelper = new ExecutableHelper( typeResolutionHelper );
153154
JavaBeanHelper javaBeanHelper = new JavaBeanHelper( getterPropertySelectionStrategy, propertyNodeNameProvider );
154155

156+
// first we want to register any validators coming from a service loader. Since they are just loaded and there's
157+
// no control over them (include/exclude the ones that already exists from any other sources etc.)
158+
registerCustomConstraintValidators(
159+
determineServiceLoadedConstraintMappings(
160+
typeResolutionHelper,
161+
javaBeanHelper,
162+
externalClassLoader
163+
),
164+
constraintHelper );
165+
166+
// we parse all XML mappings but only register constraint validators and delay constraint mappings building till
167+
// we collect all the constraint validators.
155168
// HV-302; don't load XmlMappingParser if not necessary
156169
MappingXmlParser mappingParser = null;
157170
if ( !configurationState.getMappingStreams().isEmpty() ) {
@@ -169,6 +182,8 @@ public PredefinedScopeValidatorFactoryImpl(ConfigurationState configurationState
169182
)
170183
);
171184

185+
// now the final step of registering any constraint validators that can come either from ConstraintMappingContributors
186+
// or from programmatic mappings
172187
registerCustomConstraintValidators( constraintMappings, constraintHelper );
173188

174189
XmlMetaDataProvider xmlMetaDataProvider;

engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryConfigurationHelper.java

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,6 @@ static Set<DefaultConstraintMapping> determineConstraintMappings(TypeResolutionH
7272
* these programmatically defined mappings into account when checking for constraint definition uniqueness
7373
*/
7474
constraintMappings.addAll( hibernateConfiguration.getProgrammaticMappings() );
75-
76-
// service loader based config
77-
ConstraintMappingContributor serviceLoaderBasedContributor = new ServiceLoaderBasedConstraintMappingContributor(
78-
typeResolutionHelper,
79-
externalClassLoader != null ? externalClassLoader : run( GetClassLoader.fromContext() ) );
80-
DefaultConstraintMappingBuilder builder = new DefaultConstraintMappingBuilder( javaBeanHelper, constraintMappings );
81-
serviceLoaderBasedContributor.createConstraintMappings( builder );
8275
}
8376

8477
// XML-defined constraint mapping contributors
@@ -93,6 +86,22 @@ static Set<DefaultConstraintMapping> determineConstraintMappings(TypeResolutionH
9386
return constraintMappings;
9487
}
9588

89+
static Set<DefaultConstraintMapping> determineServiceLoadedConstraintMappings(
90+
TypeResolutionHelper typeResolutionHelper,
91+
JavaBeanHelper javaBeanHelper, ClassLoader externalClassLoader) {
92+
Set<DefaultConstraintMapping> constraintMappings = newHashSet();
93+
94+
// service loader based config
95+
ConstraintMappingContributor serviceLoaderBasedContributor = new ServiceLoaderBasedConstraintMappingContributor(
96+
typeResolutionHelper,
97+
externalClassLoader != null ? externalClassLoader : run( GetClassLoader.fromContext() )
98+
);
99+
DefaultConstraintMappingBuilder builder = new DefaultConstraintMappingBuilder(
100+
javaBeanHelper, constraintMappings );
101+
serviceLoaderBasedContributor.createConstraintMappings( builder );
102+
return constraintMappings;
103+
}
104+
96105
static boolean checkPropertiesForBoolean(Map<String, String> properties, String propertyKey, boolean programmaticValue) {
97106
boolean value = programmaticValue;
98107
String propertyStringValue = properties.get( propertyKey );

engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineExternalClassLoader;
1818
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineFailFast;
1919
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineScriptEvaluatorFactory;
20+
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineServiceLoadedConstraintMappings;
2021
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineTemporalValidationTolerance;
2122
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineTraversableResolverResultCacheEnabled;
2223
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.logValidatorFactoryScopedConfiguration;
@@ -185,6 +186,19 @@ public ValidatorFactoryImpl(ConfigurationState configurationState) {
185186
ValidatorFactoryConfigurationHelper.determinePropertyNodeNameProvider( hibernateSpecificConfig, properties, externalClassLoader ) );
186187
this.beanMetadataClassNormalizer = determineBeanMetaDataClassNormalizer( hibernateSpecificConfig );
187188

189+
// first we want to register any validators coming from a service loader. Since they are just loaded and there's
190+
// no control over them (include/exclude the ones that already exists from any other sources etc.)
191+
registerCustomConstraintValidators(
192+
determineServiceLoadedConstraintMappings(
193+
typeResolutionHelper,
194+
javaBeanHelper,
195+
externalClassLoader
196+
),
197+
constraintHelper );
198+
199+
// we parse all XML mappings but only register constraint validators and delay constraint mappings building till
200+
// we collect all the constraint validators.
201+
// HV-302; don't load XmlMappingParser if not necessary
188202
MappingXmlParser mappingParser = null;
189203
if ( !configurationState.getMappingStreams().isEmpty() ) {
190204
mappingParser = new MappingXmlParser( constraintCreationContext,
@@ -201,9 +215,10 @@ public ValidatorFactoryImpl(ConfigurationState configurationState) {
201215
)
202216
);
203217

218+
// now the final step of registering any constraint validators that can come either from ConstraintMappingContributors
219+
// or from programmatic mappings
204220
registerCustomConstraintValidators( constraintMappings, constraintHelper );
205221

206-
// HV-302; don't load XmlMappingParser if not necessary
207222
if ( mappingParser != null && mappingParser.createConstrainedElements() ) {
208223
this.xmlMetaDataProvider = new XmlMetaDataProvider( mappingParser );
209224
}

engine/src/test/java/org/hibernate/validator/test/internal/xml/XmlMappingMixedWithServiceLoaderAndProgrammaticDefinitionTest.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,25 @@ public void constraintAppliedProgrammaticallyDefinitionIsAppliedThroughXml() {
123123
);
124124
}
125125

126+
@Test
127+
public void constraintValidatorLoadedByServiceLoaderOverriddenByProgrammaticDefinition() {
128+
final HibernateValidatorConfiguration configuration = ValidatorUtil.getConfiguration();
129+
configuration.externalClassLoader( new ServiceLoaderTestingClassLoader() );
130+
131+
ConstraintMapping constraintMapping = configuration.createConstraintMapping();
132+
configuration.addMapping( constraintMapping );
133+
134+
constraintMapping.constraintDefinition( MyOtherConstraint.class )
135+
.includeExistingValidators( false )
136+
.validatedBy( MyOtherConstraint.MyOtherOtherConstraintValidator.class );
137+
138+
final ValidatorFactory validatorFactory = configuration.buildValidatorFactory();
139+
final Validator validator = validatorFactory.getValidator();
140+
141+
assertNoViolations( validator.validate( new Foo() ) );
142+
assertNoViolations( validator.validate( new Bar() ) );
143+
}
144+
126145
public static class Foo {
127146
public String string;
128147
}

0 commit comments

Comments
 (0)