Skip to content

Commit c599514

Browse files
committed
Further improve detecttion of custom CNVR
Refine the approach of having <mvc:view-resolvers> detect and use the ContentNegotiationManager instance registered with <mvc:annotation-driven> introduced in the last commit. Issue: SPR-13559
1 parent f84a0c9 commit c599514

File tree

4 files changed

+44
-26
lines changed

4 files changed

+44
-26
lines changed

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

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import org.springframework.beans.factory.support.RootBeanDefinition;
3535
import org.springframework.beans.factory.xml.BeanDefinitionParser;
3636
import org.springframework.beans.factory.xml.ParserContext;
37+
import org.springframework.beans.factory.xml.XmlReaderContext;
3738
import org.springframework.core.convert.ConversionService;
3839
import org.springframework.format.support.DefaultFormattingConversionService;
3940
import org.springframework.format.support.FormattingConversionServiceFactoryBean;
@@ -148,6 +149,10 @@
148149
*/
149150
class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
150151

152+
public static final String HANDLER_MAPPING_BEAN_NAME = RequestMappingHandlerMapping.class.getName();
153+
154+
public static final String HANDLER_ADAPTER_BEAN_NAME = RequestMappingHandlerAdapter.class.getName();
155+
151156
public static final String CONTENT_NEGOTIATION_MANAGER_BEAN_NAME = "mvcContentNegotiationManager";
152157

153158
private static final boolean javaxValidationPresent =
@@ -173,6 +178,7 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
173178
@Override
174179
public BeanDefinition parse(Element element, ParserContext parserContext) {
175180
Object source = parserContext.extractSource(element);
181+
XmlReaderContext readerContext = parserContext.getReaderContext();
176182

177183
CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(), source);
178184
parserContext.pushContainingComponent(compDefinition);
@@ -184,7 +190,6 @@ public BeanDefinition parse(Element element, ParserContext parserContext) {
184190
handlerMappingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
185191
handlerMappingDef.getPropertyValues().add("order", 0);
186192
handlerMappingDef.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);
187-
String methodMappingName = parserContext.getReaderContext().registerWithGeneratedName(handlerMappingDef);
188193

189194
if (element.hasAttribute("enable-matrix-variables")) {
190195
Boolean enableMatrixVariables = Boolean.valueOf(element.getAttribute("enable-matrix-variables"));
@@ -196,6 +201,7 @@ else if (element.hasAttribute("enableMatrixVariables")) {
196201
}
197202

198203
configurePathMatchingProperties(handlerMappingDef, element, parserContext);
204+
readerContext.getRegistry().registerBeanDefinition(HANDLER_MAPPING_BEAN_NAME , handlerMappingDef);
199205

200206
RuntimeBeanReference corsConfigurationsRef = MvcNamespaceUtils.registerCorsConfigurations(null, parserContext, source);
201207
handlerMappingDef.getPropertyValues().add("corsConfigurations", corsConfigurationsRef);
@@ -253,14 +259,14 @@ else if (element.hasAttribute("ignoreDefaultModelOnRedirect")) {
253259

254260
handlerAdapterDef.getPropertyValues().add("callableInterceptors", callableInterceptors);
255261
handlerAdapterDef.getPropertyValues().add("deferredResultInterceptors", deferredResultInterceptors);
256-
String handlerAdapterName = parserContext.getReaderContext().registerWithGeneratedName(handlerAdapterDef);
262+
readerContext.getRegistry().registerBeanDefinition(HANDLER_ADAPTER_BEAN_NAME , handlerAdapterDef);
257263

258264
String uriCompContribName = MvcUriComponentsBuilder.MVC_URI_COMPONENTS_CONTRIBUTOR_BEAN_NAME;
259265
RootBeanDefinition uriCompContribDef = new RootBeanDefinition(CompositeUriComponentsContributorFactoryBean.class);
260266
uriCompContribDef.setSource(source);
261267
uriCompContribDef.getPropertyValues().addPropertyValue("handlerAdapter", handlerAdapterDef);
262268
uriCompContribDef.getPropertyValues().addPropertyValue("conversionService", conversionService);
263-
parserContext.getReaderContext().getRegistry().registerBeanDefinition(uriCompContribName, uriCompContribDef);
269+
readerContext.getRegistry().registerBeanDefinition(uriCompContribName, uriCompContribDef);
264270

265271
RootBeanDefinition csInterceptorDef = new RootBeanDefinition(ConversionServiceExposingInterceptor.class);
266272
csInterceptorDef.setSource(source);
@@ -270,7 +276,7 @@ else if (element.hasAttribute("ignoreDefaultModelOnRedirect")) {
270276
mappedCsInterceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
271277
mappedCsInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(0, (Object) null);
272278
mappedCsInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(1, csInterceptorDef);
273-
String mappedInterceptorName = parserContext.getReaderContext().registerWithGeneratedName(mappedCsInterceptorDef);
279+
String mappedInterceptorName = readerContext.registerWithGeneratedName(mappedCsInterceptorDef);
274280

275281
RootBeanDefinition exceptionHandlerExceptionResolver = new RootBeanDefinition(ExceptionHandlerExceptionResolver.class);
276282
exceptionHandlerExceptionResolver.setSource(source);
@@ -280,25 +286,24 @@ else if (element.hasAttribute("ignoreDefaultModelOnRedirect")) {
280286
exceptionHandlerExceptionResolver.getPropertyValues().add("order", 0);
281287
addResponseBodyAdvice(exceptionHandlerExceptionResolver);
282288

283-
String methodExceptionResolverName =
284-
parserContext.getReaderContext().registerWithGeneratedName(exceptionHandlerExceptionResolver);
289+
String methodExceptionResolverName = readerContext.registerWithGeneratedName(exceptionHandlerExceptionResolver);
285290

286291
RootBeanDefinition responseStatusExceptionResolver = new RootBeanDefinition(ResponseStatusExceptionResolver.class);
287292
responseStatusExceptionResolver.setSource(source);
288293
responseStatusExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
289294
responseStatusExceptionResolver.getPropertyValues().add("order", 1);
290295
String responseStatusExceptionResolverName =
291-
parserContext.getReaderContext().registerWithGeneratedName(responseStatusExceptionResolver);
296+
readerContext.registerWithGeneratedName(responseStatusExceptionResolver);
292297

293298
RootBeanDefinition defaultExceptionResolver = new RootBeanDefinition(DefaultHandlerExceptionResolver.class);
294299
defaultExceptionResolver.setSource(source);
295300
defaultExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
296301
defaultExceptionResolver.getPropertyValues().add("order", 2);
297302
String defaultExceptionResolverName =
298-
parserContext.getReaderContext().registerWithGeneratedName(defaultExceptionResolver);
303+
readerContext.registerWithGeneratedName(defaultExceptionResolver);
299304

300-
parserContext.registerComponent(new BeanComponentDefinition(handlerMappingDef, methodMappingName));
301-
parserContext.registerComponent(new BeanComponentDefinition(handlerAdapterDef, handlerAdapterName));
305+
parserContext.registerComponent(new BeanComponentDefinition(handlerMappingDef, HANDLER_MAPPING_BEAN_NAME));
306+
parserContext.registerComponent(new BeanComponentDefinition(handlerAdapterDef, HANDLER_ADAPTER_BEAN_NAME));
302307
parserContext.registerComponent(new BeanComponentDefinition(uriCompContribDef, uriCompContribName));
303308
parserContext.registerComponent(new BeanComponentDefinition(exceptionHandlerExceptionResolver, methodExceptionResolverName));
304309
parserContext.registerComponent(new BeanComponentDefinition(responseStatusExceptionResolver, responseStatusExceptionResolverName));
@@ -361,14 +366,13 @@ else if (javaxValidationPresent) {
361366
}
362367
}
363368

364-
private RuntimeBeanReference getContentNegotiationManager(Element element, Object source, ParserContext parserContext) {
365-
RuntimeBeanReference contentNegotiationManagerRef;
369+
private RuntimeBeanReference getContentNegotiationManager(Element element, Object source,
370+
ParserContext parserContext) {
371+
372+
RuntimeBeanReference beanRef;
366373
if (element.hasAttribute("content-negotiation-manager")) {
367374
String name = element.getAttribute("content-negotiation-manager");
368-
contentNegotiationManagerRef = new RuntimeBeanReference(name);
369-
if (!CONTENT_NEGOTIATION_MANAGER_BEAN_NAME.equals(name)) {
370-
parserContext.getRegistry().registerAlias(name, CONTENT_NEGOTIATION_MANAGER_BEAN_NAME);
371-
}
375+
beanRef = new RuntimeBeanReference(name);
372376
}
373377
else {
374378
RootBeanDefinition factoryBeanDef = new RootBeanDefinition(ContentNegotiationManagerFactoryBean.class);
@@ -379,13 +383,14 @@ private RuntimeBeanReference getContentNegotiationManager(Element element, Objec
379383
String name = CONTENT_NEGOTIATION_MANAGER_BEAN_NAME;
380384
parserContext.getReaderContext().getRegistry().registerBeanDefinition(name , factoryBeanDef);
381385
parserContext.registerComponent(new BeanComponentDefinition(factoryBeanDef, name));
382-
contentNegotiationManagerRef = new RuntimeBeanReference(name);
386+
beanRef = new RuntimeBeanReference(name);
383387
}
384-
return contentNegotiationManagerRef;
388+
return beanRef;
385389
}
386390

387-
private void configurePathMatchingProperties(RootBeanDefinition handlerMappingDef,
388-
Element element, ParserContext parserContext) {
391+
private void configurePathMatchingProperties(RootBeanDefinition handlerMappingDef, Element element,
392+
ParserContext parserContext) {
393+
389394
Element pathMatchingElement = DomUtils.getChildElementByTagName(element, "path-matching");
390395
if (pathMatchingElement != null) {
391396
Object source = parserContext.extractSource(element);

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

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -192,11 +192,24 @@ private BeanDefinition createContentNegotiatingViewResolver(Element resolverElem
192192
if (resolverElement.hasAttribute("use-not-acceptable")) {
193193
values.add("useNotAcceptableStatusCode", resolverElement.getAttribute("use-not-acceptable"));
194194
}
195-
String name = AnnotationDrivenBeanDefinitionParser.CONTENT_NEGOTIATION_MANAGER_BEAN_NAME;
196-
if (context.getRegistry().containsBeanDefinition(name) || context.getRegistry().isAlias(name)) {
197-
values.add("contentNegotiationManager", new RuntimeBeanReference(name));
195+
Object manager = getContentNegotiationManager(context);
196+
if (manager != null) {
197+
values.add("contentNegotiationManager", manager);
198198
}
199199
return beanDef;
200200
}
201201

202+
private Object getContentNegotiationManager(ParserContext context) {
203+
String name = AnnotationDrivenBeanDefinitionParser.HANDLER_MAPPING_BEAN_NAME;
204+
if (context.getRegistry().containsBeanDefinition(name)) {
205+
BeanDefinition handlerMappingBeanDef = context.getRegistry().getBeanDefinition(name);
206+
return handlerMappingBeanDef.getPropertyValues().get("contentNegotiationManager");
207+
}
208+
name = AnnotationDrivenBeanDefinitionParser.CONTENT_NEGOTIATION_MANAGER_BEAN_NAME;
209+
if (context.getRegistry().containsBeanDefinition(name)) {
210+
return new RuntimeBeanReference(name);
211+
}
212+
return null;
213+
}
214+
202215
}

spring-webmvc/src/test/java/org/springframework/web/servlet/config/MvcNamespaceTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -691,7 +691,7 @@ public void testViewControllersDefaultConfig() {
691691

692692
@Test
693693
public void testContentNegotiationManager() throws Exception {
694-
loadBeanDefinitions("mvc-config-content-negotiation-manager.xml", 15);
694+
loadBeanDefinitions("mvc-config-content-negotiation-manager.xml", 14);
695695

696696
RequestMappingHandlerMapping mapping = appContext.getBean(RequestMappingHandlerMapping.class);
697697
ContentNegotiationManager manager = mapping.getContentNegotiationManager();

spring-webmvc/src/test/resources/org/springframework/web/servlet/config/mvc-config-content-negotiation-manager.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@
77
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
88

99

10-
<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager" />
10+
<mvc:annotation-driven content-negotiation-manager="mvcContentNegotiationManager" />
1111

1212
<mvc:view-resolvers>
1313
<mvc:content-negotiation/>
1414
</mvc:view-resolvers>
1515

16-
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
16+
<bean id="mvcContentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
1717
<property name="mediaTypes">
1818
<value>
1919
xml=application/rss+xml

0 commit comments

Comments
 (0)