Skip to content

Commit 8d1e55d

Browse files
committed
Avoid hard reference to LocalValidatorFactoryBean in <mvc:annotation-driven> parser
Issue: SPR-11272 (cherry picked from commit c48da0d)
1 parent 6aabb5f commit 8d1e55d

File tree

2 files changed

+57
-43
lines changed

2 files changed

+57
-43
lines changed

spring-context/src/main/java/org/springframework/validation/beanvalidation/LocalValidatorFactoryBean.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@
7171
* a {@link ValidatorFactory} and call {@link #getValidator()} on it, then {@code #forExecutables}
7272
* on the returned native {@link Validator} reference instead of directly on this class.
7373
*
74+
* <p>This class is also being used by Spring's MVC configuration namespace, in case of the
75+
* {@code javax.validation} API being present but no explicit Validator having been configured.
76+
*
7477
* @author Juergen Hoeller
7578
* @since 3.0
7679
* @see javax.validation.ValidatorFactory
@@ -170,7 +173,7 @@ public void setParameterNameDiscoverer(ParameterNameDiscoverer parameterNameDisc
170173
/**
171174
* Specify resource locations to load XML constraint mapping files from, if any.
172175
*/
173-
public void setMappingLocations(Resource[] mappingLocations) {
176+
public void setMappingLocations(Resource... mappingLocations) {
174177
this.mappingLocations = mappingLocations;
175178
}
176179

spring-webmvc/src/main/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java

Lines changed: 53 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2013 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -19,6 +19,8 @@
1919
import java.util.List;
2020
import java.util.Properties;
2121

22+
import org.w3c.dom.Element;
23+
2224
import org.springframework.beans.factory.FactoryBean;
2325
import org.springframework.beans.factory.InitializingBean;
2426
import org.springframework.beans.factory.config.BeanDefinition;
@@ -71,7 +73,6 @@
7173
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
7274
import org.springframework.web.servlet.mvc.method.annotation.ServletWebArgumentResolverAdapter;
7375
import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver;
74-
import org.w3c.dom.Element;
7576

7677
/**
7778
* A {@link BeanDefinitionParser} that provides the configuration for the
@@ -129,7 +130,7 @@
129130
*/
130131
class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
131132

132-
private static final boolean jsr303Present = ClassUtils.isPresent(
133+
private static final boolean javaxValidationPresent = ClassUtils.isPresent(
133134
"javax.validation.Validator", AnnotationDrivenBeanDefinitionParser.class.getClassLoader());
134135

135136
private static final boolean jaxb2Present =
@@ -146,6 +147,7 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
146147
private static boolean romePresent =
147148
ClassUtils.isPresent("com.sun.syndication.feed.WireFeed", AnnotationDrivenBeanDefinitionParser.class.getClassLoader());
148149

150+
149151
@Override
150152
public BeanDefinition parse(Element element, ParserContext parserContext) {
151153
Object source = parserContext.extractSource(element);
@@ -161,9 +163,13 @@ public BeanDefinition parse(Element element, ParserContext parserContext) {
161163
handlerMappingDef.getPropertyValues().add("order", 0);
162164
handlerMappingDef.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);
163165
String methodMappingName = parserContext.getReaderContext().registerWithGeneratedName(handlerMappingDef);
164-
if (element.hasAttribute("enable-matrix-variables") || element.hasAttribute("enableMatrixVariables")) {
165-
Boolean enableMatrixVariables = Boolean.valueOf(element.getAttribute(
166-
element.hasAttribute("enable-matrix-variables") ? "enable-matrix-variables" : "enableMatrixVariables"));
166+
167+
if (element.hasAttribute("enable-matrix-variables")) {
168+
Boolean enableMatrixVariables = Boolean.valueOf(element.getAttribute("enable-matrix-variables"));
169+
handlerMappingDef.getPropertyValues().add("removeSemicolonContent", !enableMatrixVariables);
170+
}
171+
else if (element.hasAttribute("enableMatrixVariables")) {
172+
Boolean enableMatrixVariables = Boolean.valueOf(element.getAttribute("enableMatrixVariables"));
167173
handlerMappingDef.getPropertyValues().add("removeSemicolonContent", !enableMatrixVariables);
168174
}
169175

@@ -179,7 +185,7 @@ public BeanDefinition parse(Element element, ParserContext parserContext) {
179185
bindingDef.getPropertyValues().add("messageCodesResolver", messageCodesResolver);
180186

181187
ManagedList<?> messageConverters = getMessageConverters(element, source, parserContext);
182-
ManagedList<?> argumentResolvers = getArgumentResolvers(element, source, parserContext);
188+
ManagedList<?> argumentResolvers = getArgumentResolvers(element, parserContext);
183189
ManagedList<?> returnValueHandlers = getReturnValueHandlers(element, source, parserContext);
184190
String asyncTimeout = getAsyncTimeout(element, source, parserContext);
185191
RuntimeBeanReference asyncExecutor = getAsyncExecutor(element, source, parserContext);
@@ -192,11 +198,17 @@ public BeanDefinition parse(Element element, ParserContext parserContext) {
192198
handlerAdapterDef.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);
193199
handlerAdapterDef.getPropertyValues().add("webBindingInitializer", bindingDef);
194200
handlerAdapterDef.getPropertyValues().add("messageConverters", messageConverters);
195-
if (element.hasAttribute("ignore-default-model-on-redirect") || element.hasAttribute("ignoreDefaultModelOnRedirect")) {
196-
Boolean ignoreDefaultModel = Boolean.valueOf(element.getAttribute(
197-
element.hasAttribute("ignore-default-model-on-redirect") ? "ignore-default-model-on-redirect" : "ignoreDefaultModelOnRedirect"));
201+
202+
if (element.hasAttribute("ignore-default-model-on-redirect")) {
203+
Boolean ignoreDefaultModel = Boolean.valueOf(element.getAttribute("ignore-default-model-on-redirect"));
204+
handlerAdapterDef.getPropertyValues().add("ignoreDefaultModelOnRedirect", ignoreDefaultModel);
205+
}
206+
else if (element.hasAttribute("ignoreDefaultModelOnRedirect")) {
207+
// "ignoreDefaultModelOnRedirect" spelling is deprecated
208+
Boolean ignoreDefaultModel = Boolean.valueOf(element.getAttribute("ignoreDefaultModelOnRedirect"));
198209
handlerAdapterDef.getPropertyValues().add("ignoreDefaultModelOnRedirect", ignoreDefaultModel);
199210
}
211+
200212
if (argumentResolvers != null) {
201213
handlerAdapterDef.getPropertyValues().add("customArgumentResolvers", argumentResolvers);
202214
}
@@ -209,6 +221,7 @@ public BeanDefinition parse(Element element, ParserContext parserContext) {
209221
if (asyncExecutor != null) {
210222
handlerAdapterDef.getPropertyValues().add("taskExecutor", asyncExecutor);
211223
}
224+
212225
handlerAdapterDef.getPropertyValues().add("callableInterceptors", callableInterceptors);
213226
handlerAdapterDef.getPropertyValues().add("deferredResultInterceptors", deferredResultInterceptors);
214227
String handlerAdapterName = parserContext.getReaderContext().registerWithGeneratedName(handlerAdapterDef);
@@ -289,8 +302,9 @@ private RuntimeBeanReference getValidator(Element element, Object source, Parser
289302
if (element.hasAttribute("validator")) {
290303
return new RuntimeBeanReference(element.getAttribute("validator"));
291304
}
292-
else if (jsr303Present) {
293-
RootBeanDefinition validatorDef = new RootBeanDefinition(LocalValidatorFactoryBean.class);
305+
else if (javaxValidationPresent) {
306+
RootBeanDefinition validatorDef = new RootBeanDefinition(
307+
"org.springframework.validation.beanvalidation.LocalValidatorFactoryBean");
294308
validatorDef.setSource(source);
295309
validatorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
296310
String validatorName = parserContext.getReaderContext().registerWithGeneratedName(validatorDef);
@@ -339,7 +353,8 @@ private Properties getDefaultMediaTypes() {
339353
private RuntimeBeanReference getMessageCodesResolver(Element element, Object source, ParserContext parserContext) {
340354
if (element.hasAttribute("message-codes-resolver")) {
341355
return new RuntimeBeanReference(element.getAttribute("message-codes-resolver"));
342-
} else {
356+
}
357+
else {
343358
return null;
344359
}
345360
}
@@ -393,11 +408,11 @@ private ManagedList<?> getDeferredResultInterceptors(Element element, Object sou
393408
return interceptors;
394409
}
395410

396-
private ManagedList<?> getArgumentResolvers(Element element, Object source, ParserContext parserContext) {
411+
private ManagedList<?> getArgumentResolvers(Element element, ParserContext parserContext) {
397412
Element resolversElement = DomUtils.getChildElementByTagName(element, "argument-resolvers");
398413
if (resolversElement != null) {
399414
ManagedList<BeanDefinitionHolder> argumentResolvers = extractBeanSubElements(resolversElement, parserContext);
400-
return wrapWebArgumentResolverBeanDefs(argumentResolvers);
415+
return wrapWebArgumentResolverBeanDefs(argumentResolvers, parserContext);
401416
}
402417
return null;
403418
}
@@ -424,41 +439,39 @@ private ManagedList<?> getMessageConverters(Element element, Object source, Pars
424439

425440
if (convertersElement == null || Boolean.valueOf(convertersElement.getAttribute("register-defaults"))) {
426441
messageConverters.setSource(source);
427-
messageConverters.add(createConverterBeanDefinition(ByteArrayHttpMessageConverter.class, source));
442+
messageConverters.add(createConverterDefinition(ByteArrayHttpMessageConverter.class, source));
428443

429-
RootBeanDefinition stringConverterDef = createConverterBeanDefinition(StringHttpMessageConverter.class, source);
444+
RootBeanDefinition stringConverterDef = createConverterDefinition(StringHttpMessageConverter.class, source);
430445
stringConverterDef.getPropertyValues().add("writeAcceptCharset", false);
431446
messageConverters.add(stringConverterDef);
432447

433-
messageConverters.add(createConverterBeanDefinition(ResourceHttpMessageConverter.class, source));
434-
messageConverters.add(createConverterBeanDefinition(SourceHttpMessageConverter.class, source));
435-
messageConverters.add(createConverterBeanDefinition(AllEncompassingFormHttpMessageConverter.class, source));
448+
messageConverters.add(createConverterDefinition(ResourceHttpMessageConverter.class, source));
449+
messageConverters.add(createConverterDefinition(SourceHttpMessageConverter.class, source));
450+
messageConverters.add(createConverterDefinition(AllEncompassingFormHttpMessageConverter.class, source));
451+
436452
if (romePresent) {
437-
messageConverters.add(createConverterBeanDefinition(AtomFeedHttpMessageConverter.class, source));
438-
messageConverters.add(createConverterBeanDefinition(RssChannelHttpMessageConverter.class, source));
453+
messageConverters.add(createConverterDefinition(AtomFeedHttpMessageConverter.class, source));
454+
messageConverters.add(createConverterDefinition(RssChannelHttpMessageConverter.class, source));
439455
}
440456
if (jaxb2Present) {
441-
messageConverters
442-
.add(createConverterBeanDefinition(Jaxb2RootElementHttpMessageConverter.class, source));
457+
messageConverters.add(createConverterDefinition(Jaxb2RootElementHttpMessageConverter.class, source));
443458
}
459+
444460
if (jackson2Present) {
445-
messageConverters.add(createConverterBeanDefinition(MappingJackson2HttpMessageConverter.class, source));
461+
messageConverters.add(createConverterDefinition(MappingJackson2HttpMessageConverter.class, source));
446462
}
447463
else if (jacksonPresent) {
448-
messageConverters.add(createConverterBeanDefinition(org.springframework.http.converter.json.MappingJacksonHttpMessageConverter.class, source));
464+
messageConverters.add(createConverterDefinition(
465+
org.springframework.http.converter.json.MappingJacksonHttpMessageConverter.class, source));
449466
}
450467
}
451468
return messageConverters;
452469
}
453-
454470
@SuppressWarnings("rawtypes")
455-
private RootBeanDefinition createConverterBeanDefinition(
456-
Class<? extends HttpMessageConverter> converterClass, Object source) {
457-
471+
private RootBeanDefinition createConverterDefinition(Class<? extends HttpMessageConverter> converterClass, Object source) {
458472
RootBeanDefinition beanDefinition = new RootBeanDefinition(converterClass);
459473
beanDefinition.setSource(source);
460474
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
461-
462475
return beanDefinition;
463476
}
464477

@@ -473,22 +486,22 @@ private ManagedList<BeanDefinitionHolder> extractBeanSubElements(Element parentE
473486
return list;
474487
}
475488

476-
private ManagedList<BeanDefinitionHolder> wrapWebArgumentResolverBeanDefs(List<BeanDefinitionHolder> beanDefs) {
477-
ManagedList<BeanDefinitionHolder> result = new ManagedList<BeanDefinitionHolder>();
489+
private ManagedList<BeanDefinitionHolder> wrapWebArgumentResolverBeanDefs(
490+
List<BeanDefinitionHolder> beanDefs, ParserContext parserContext) {
478491

492+
ManagedList<BeanDefinitionHolder> result = new ManagedList<BeanDefinitionHolder>();
479493
for (BeanDefinitionHolder beanDef : beanDefs) {
480494
String className = beanDef.getBeanDefinition().getBeanClassName();
481-
Class<?> clazz = ClassUtils.resolveClassName(className, ClassUtils.getDefaultClassLoader());
482-
495+
Class<?> clazz = ClassUtils.resolveClassName(className, parserContext.getReaderContext().getBeanClassLoader());
483496
if (WebArgumentResolver.class.isAssignableFrom(clazz)) {
484497
RootBeanDefinition adapter = new RootBeanDefinition(ServletWebArgumentResolverAdapter.class);
485498
adapter.getConstructorArgumentValues().addIndexedArgumentValue(0, beanDef);
486499
result.add(new BeanDefinitionHolder(adapter, beanDef.getBeanName() + "Adapter"));
487-
} else {
500+
}
501+
else {
488502
result.add(beanDef);
489503
}
490504
}
491-
492505
return result;
493506
}
494507

@@ -498,17 +511,15 @@ private ManagedList<BeanDefinitionHolder> wrapWebArgumentResolverBeanDefs(List<B
498511
* HandlerMethodArgumentResolver's configured in RequestMappingHandlerAdapter
499512
* after it is fully initialized.
500513
*/
501-
@SuppressWarnings("unused")
502-
private static class CompositeUriComponentsContributorFactoryBean
503-
implements InitializingBean, FactoryBean<CompositeUriComponentsContributor> {
514+
static class CompositeUriComponentsContributorFactoryBean
515+
implements FactoryBean<CompositeUriComponentsContributor>, InitializingBean {
504516

505517
private RequestMappingHandlerAdapter handlerAdapter;
506518

507519
private ConversionService conversionService;
508520

509521
private CompositeUriComponentsContributor uriComponentsContributor;
510522

511-
512523
public void setHandlerAdapter(RequestMappingHandlerAdapter handlerAdapter) {
513524
this.handlerAdapter = handlerAdapter;
514525
}
@@ -518,7 +529,7 @@ public void setConversionService(ConversionService conversionService) {
518529
}
519530

520531
@Override
521-
public void afterPropertiesSet() throws Exception {
532+
public void afterPropertiesSet() {
522533
this.uriComponentsContributor = new CompositeUriComponentsContributor(
523534
this.handlerAdapter.getArgumentResolvers(), this.conversionService);
524535
}

0 commit comments

Comments
 (0)