Skip to content

Commit 7c285c9

Browse files
marko-bekhtagsmet
authored andcommitted
HV-1949 Delay building constraint bean info from XML until all sources contributed to available constraint validators
1 parent d3e041b commit 7c285c9

File tree

8 files changed

+329
-34
lines changed

8 files changed

+329
-34
lines changed

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

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
import org.hibernate.validator.internal.util.TypeResolutionHelper;
6161
import org.hibernate.validator.internal.util.logging.Log;
6262
import org.hibernate.validator.internal.util.logging.LoggerFactory;
63+
import org.hibernate.validator.internal.xml.mapping.MappingXmlParser;
6364
import org.hibernate.validator.spi.nodenameprovider.PropertyNodeNameProvider;
6465
import org.hibernate.validator.spi.properties.GetterPropertySelectionStrategy;
6566
import org.hibernate.validator.spi.scripting.ScriptEvaluatorFactory;
@@ -152,14 +153,11 @@ public PredefinedScopeValidatorFactoryImpl(ConfigurationState configurationState
152153
JavaBeanHelper javaBeanHelper = new JavaBeanHelper( getterPropertySelectionStrategy, propertyNodeNameProvider );
153154

154155
// HV-302; don't load XmlMappingParser if not necessary
155-
XmlMetaDataProvider xmlMetaDataProvider;
156-
if ( configurationState.getMappingStreams().isEmpty() ) {
157-
xmlMetaDataProvider = null;
158-
}
159-
else {
160-
xmlMetaDataProvider = new XmlMetaDataProvider(
161-
constraintCreationContext, javaBeanHelper, configurationState.getMappingStreams(), externalClassLoader
162-
);
156+
MappingXmlParser mappingParser = null;
157+
if ( !configurationState.getMappingStreams().isEmpty() ) {
158+
mappingParser = new MappingXmlParser( constraintCreationContext,
159+
javaBeanHelper, externalClassLoader );
160+
mappingParser.parse( configurationState.getMappingStreams() );
163161
}
164162

165163
Set<DefaultConstraintMapping> constraintMappings = Collections.unmodifiableSet(
@@ -173,6 +171,14 @@ public PredefinedScopeValidatorFactoryImpl(ConfigurationState configurationState
173171

174172
registerCustomConstraintValidators( constraintMappings, constraintHelper );
175173

174+
XmlMetaDataProvider xmlMetaDataProvider;
175+
if ( mappingParser != null && mappingParser.createConstrainedElements() ) {
176+
xmlMetaDataProvider = new XmlMetaDataProvider( mappingParser );
177+
}
178+
else {
179+
xmlMetaDataProvider = null;
180+
}
181+
176182
this.beanMetaDataManager = new PredefinedScopeBeanMetaDataManager(
177183
constraintCreationContext,
178184
executableHelper,

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

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
import org.hibernate.validator.internal.util.logging.LoggerFactory;
6464
import org.hibernate.validator.internal.util.stereotypes.Immutable;
6565
import org.hibernate.validator.internal.util.stereotypes.ThreadSafe;
66+
import org.hibernate.validator.internal.xml.mapping.MappingXmlParser;
6667
import org.hibernate.validator.metadata.BeanMetaDataClassNormalizer;
6768
import org.hibernate.validator.spi.nodenameprovider.PropertyNodeNameProvider;
6869
import org.hibernate.validator.spi.properties.GetterPropertySelectionStrategy;
@@ -184,12 +185,11 @@ public ValidatorFactoryImpl(ConfigurationState configurationState) {
184185
ValidatorFactoryConfigurationHelper.determinePropertyNodeNameProvider( hibernateSpecificConfig, properties, externalClassLoader ) );
185186
this.beanMetadataClassNormalizer = determineBeanMetaDataClassNormalizer( hibernateSpecificConfig );
186187

187-
// HV-302; don't load XmlMappingParser if not necessary
188-
if ( configurationState.getMappingStreams().isEmpty() ) {
189-
this.xmlMetaDataProvider = null;
190-
}
191-
else {
192-
this.xmlMetaDataProvider = new XmlMetaDataProvider( constraintCreationContext, javaBeanHelper, configurationState.getMappingStreams(), externalClassLoader );
188+
MappingXmlParser mappingParser = null;
189+
if ( !configurationState.getMappingStreams().isEmpty() ) {
190+
mappingParser = new MappingXmlParser( constraintCreationContext,
191+
javaBeanHelper, externalClassLoader );
192+
mappingParser.parse( configurationState.getMappingStreams() );
193193
}
194194

195195
this.constraintMappings = Collections.unmodifiableSet(
@@ -203,6 +203,14 @@ public ValidatorFactoryImpl(ConfigurationState configurationState) {
203203

204204
registerCustomConstraintValidators( constraintMappings, constraintHelper );
205205

206+
// HV-302; don't load XmlMappingParser if not necessary
207+
if ( mappingParser != null && mappingParser.createConstrainedElements() ) {
208+
this.xmlMetaDataProvider = new XmlMetaDataProvider( mappingParser );
209+
}
210+
else {
211+
this.xmlMetaDataProvider = null;
212+
}
213+
206214
if ( LOG.isDebugEnabled() ) {
207215
logValidatorFactoryScopedConfiguration( validatorFactoryScopedContext );
208216
}

engine/src/main/java/org/hibernate/validator/internal/metadata/provider/XmlMetaDataProvider.java

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,14 @@
66
*/
77
package org.hibernate.validator.internal.metadata.provider;
88

9-
import java.io.InputStream;
109
import java.util.HashMap;
1110
import java.util.Map;
1211
import java.util.Set;
1312

14-
import org.hibernate.validator.internal.engine.ConstraintCreationContext;
1513
import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptions;
1614
import org.hibernate.validator.internal.metadata.raw.BeanConfiguration;
1715
import org.hibernate.validator.internal.metadata.raw.ConfigurationSource;
1816
import org.hibernate.validator.internal.metadata.raw.ConstrainedElement;
19-
import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper;
2017
import org.hibernate.validator.internal.util.CollectionHelper;
2118
import org.hibernate.validator.internal.util.stereotypes.Immutable;
2219
import org.hibernate.validator.internal.xml.mapping.MappingXmlParser;
@@ -36,15 +33,7 @@ public class XmlMetaDataProvider implements MetaDataProvider {
3633

3734
private final AnnotationProcessingOptions annotationProcessingOptions;
3835

39-
public XmlMetaDataProvider(ConstraintCreationContext constraintCreationContext,
40-
JavaBeanHelper javaBeanHelper,
41-
Set<InputStream> mappingStreams,
42-
ClassLoader externalClassLoader) {
43-
44-
MappingXmlParser mappingParser = new MappingXmlParser( constraintCreationContext,
45-
javaBeanHelper, externalClassLoader );
46-
mappingParser.parse( mappingStreams );
47-
36+
public XmlMetaDataProvider(MappingXmlParser mappingParser) {
4837
configuredBeans = CollectionHelper.toImmutableMap( createBeanConfigurations( mappingParser ) );
4938
annotationProcessingOptions = mappingParser.getAnnotationProcessingOptions();
5039
}

engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstraintMappingsStaxBuilder.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,16 @@ private ConstraintDefinitionStaxBuilder getNewConstraintDefinitionStaxBuilder()
8787
return new ConstraintDefinitionStaxBuilder( classLoadingHelper, constraintCreationContext.getConstraintHelper(), defaultPackageStaxBuilder );
8888
}
8989

90-
public void build(Set<Class<?>> processedClasses, Map<Class<?>, Set<ConstrainedElement>> constrainedElementsByType, Set<String> alreadyProcessedConstraintDefinitions) {
90+
public void buildConstraintDefinitions(Set<String> alreadyProcessedConstraintDefinitions) {
9191
constraintDefinitionStaxBuilders.forEach( builder -> builder.build( alreadyProcessedConstraintDefinitions ) );
92+
}
93+
94+
public void buildConstrainedElements(Set<Class<?>> processedClasses, Map<Class<?>, Set<ConstrainedElement>> constrainedElementsByType) {
9295
beanStaxBuilders.forEach( builder -> builder.build( javaBeanHelper, processedClasses, constrainedElementsByType ) );
9396
}
97+
98+
public boolean hasBeanBuilders() {
99+
return !beanStaxBuilders.isEmpty();
100+
}
101+
94102
}

engine/src/main/java/org/hibernate/validator/internal/xml/mapping/MappingXmlParser.java

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ public class MappingXmlParser {
5656
private final JavaBeanHelper javaBeanHelper;
5757
private final Map<Class<?>, List<Class<?>>> defaultSequences;
5858
private final Map<Class<?>, Set<ConstrainedElement>> constrainedElements;
59+
private final Set<ConstraintMappingsStaxBuilder> mappingBuilders;
5960

6061
private final XmlParserHelper xmlParserHelper;
6162

@@ -80,6 +81,7 @@ public MappingXmlParser(ConstraintCreationContext constraintCreationContext, Jav
8081
this.javaBeanHelper = javaBeanHelper;
8182
this.defaultSequences = newHashMap();
8283
this.constrainedElements = newHashMap();
84+
this.mappingBuilders = newHashSet();
8385
this.xmlParserHelper = new XmlParserHelper();
8486
this.classLoadingHelper = new ClassLoadingHelper( externalClassLoader, run( GetClassLoader.fromContext() ) );
8587
}
@@ -130,7 +132,16 @@ public final void parse(Set<InputStream> mappingStreams) {
130132
while ( xmlEventReader.hasNext() ) {
131133
constraintMappingsStaxBuilder.process( xmlEventReader, xmlEventReader.nextEvent() );
132134
}
133-
constraintMappingsStaxBuilder.build( processedClasses, constrainedElements, alreadyProcessedConstraintDefinitions );
135+
// at this point we only build the constraint definitions.
136+
// we want to fully populate the constraint helper and get the final rules for which
137+
// validators will be applied before we build any constrained elements that contribute to
138+
// final bean metadata.
139+
constraintMappingsStaxBuilder.buildConstraintDefinitions( alreadyProcessedConstraintDefinitions );
140+
// we only add the builder to process it later if it has anything related to bean's constraints,
141+
// otherwise it was only about constraint definition, and we've processed it already.
142+
if ( constraintMappingsStaxBuilder.hasBeanBuilders() ) {
143+
mappingBuilders.add( constraintMappingsStaxBuilder );
144+
}
134145
xmlEventReader.close();
135146
in.reset();
136147
}
@@ -143,6 +154,16 @@ public final void parse(Set<InputStream> mappingStreams) {
143154
}
144155
}
145156

157+
public final boolean createConstrainedElements() {
158+
for ( ConstraintMappingsStaxBuilder builder : mappingBuilders ) {
159+
builder.buildConstrainedElements( processedClasses, constrainedElements );
160+
}
161+
162+
// If there are no mappings means that we've only got some constraint definitions passed to us through XML.
163+
// so we don't need to create an XML metadata provider since it won't contribute anything anyway.
164+
return !mappingBuilders.isEmpty();
165+
}
166+
146167
public final Set<Class<?>> getXmlConfiguredClasses() {
147168
return processedClasses;
148169
}
@@ -152,12 +173,7 @@ public final AnnotationProcessingOptions getAnnotationProcessingOptions() {
152173
}
153174

154175
public final Set<ConstrainedElement> getConstrainedElementsForClass(Class<?> beanClass) {
155-
if ( constrainedElements.containsKey( beanClass ) ) {
156-
return constrainedElements.get( beanClass );
157-
}
158-
else {
159-
return Collections.emptySet();
160-
}
176+
return constrainedElements.getOrDefault( beanClass, Collections.emptySet() );
161177
}
162178

163179
public final List<Class<?>> getDefaultSequenceForClass(Class<?> beanClass) {

0 commit comments

Comments
 (0)