Skip to content

Commit 0f1897d

Browse files
committed
Further improve Detect 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 563a120 commit 0f1897d

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;
@@ -147,6 +148,10 @@
147148
*/
148149
class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
149150

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

152157
private static final boolean javaxValidationPresent =
@@ -172,6 +177,7 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
172177
@Override
173178
public BeanDefinition parse(Element element, ParserContext parserContext) {
174179
Object source = parserContext.extractSource(element);
180+
XmlReaderContext readerContext = parserContext.getReaderContext();
175181

176182
CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(), source);
177183
parserContext.pushContainingComponent(compDefinition);
@@ -183,7 +189,6 @@ public BeanDefinition parse(Element element, ParserContext parserContext) {
183189
handlerMappingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
184190
handlerMappingDef.getPropertyValues().add("order", 0);
185191
handlerMappingDef.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);
186-
String methodMappingName = parserContext.getReaderContext().registerWithGeneratedName(handlerMappingDef);
187192

188193
if (element.hasAttribute("enable-matrix-variables")) {
189194
Boolean enableMatrixVariables = Boolean.valueOf(element.getAttribute("enable-matrix-variables"));
@@ -195,6 +200,7 @@ else if (element.hasAttribute("enableMatrixVariables")) {
195200
}
196201

197202
configurePathMatchingProperties(handlerMappingDef, element, parserContext);
203+
readerContext.getRegistry().registerBeanDefinition(HANDLER_MAPPING_BEAN_NAME , handlerMappingDef);
198204

199205
RuntimeBeanReference conversionService = getConversionService(element, source, parserContext);
200206
RuntimeBeanReference validator = getValidator(element, source, parserContext);
@@ -248,14 +254,14 @@ else if (element.hasAttribute("ignoreDefaultModelOnRedirect")) {
248254

249255
handlerAdapterDef.getPropertyValues().add("callableInterceptors", callableInterceptors);
250256
handlerAdapterDef.getPropertyValues().add("deferredResultInterceptors", deferredResultInterceptors);
251-
String handlerAdapterName = parserContext.getReaderContext().registerWithGeneratedName(handlerAdapterDef);
257+
readerContext.getRegistry().registerBeanDefinition(HANDLER_ADAPTER_BEAN_NAME , handlerAdapterDef);
252258

253259
String uriCompContribName = MvcUriComponentsBuilder.MVC_URI_COMPONENTS_CONTRIBUTOR_BEAN_NAME;
254260
RootBeanDefinition uriCompContribDef = new RootBeanDefinition(CompositeUriComponentsContributorFactoryBean.class);
255261
uriCompContribDef.setSource(source);
256262
uriCompContribDef.getPropertyValues().addPropertyValue("handlerAdapter", handlerAdapterDef);
257263
uriCompContribDef.getPropertyValues().addPropertyValue("conversionService", conversionService);
258-
parserContext.getReaderContext().getRegistry().registerBeanDefinition(uriCompContribName, uriCompContribDef);
264+
readerContext.getRegistry().registerBeanDefinition(uriCompContribName, uriCompContribDef);
259265

260266
RootBeanDefinition csInterceptorDef = new RootBeanDefinition(ConversionServiceExposingInterceptor.class);
261267
csInterceptorDef.setSource(source);
@@ -265,7 +271,7 @@ else if (element.hasAttribute("ignoreDefaultModelOnRedirect")) {
265271
mappedCsInterceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
266272
mappedCsInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(0, (Object) null);
267273
mappedCsInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(1, csInterceptorDef);
268-
String mappedInterceptorName = parserContext.getReaderContext().registerWithGeneratedName(mappedCsInterceptorDef);
274+
String mappedInterceptorName = readerContext.registerWithGeneratedName(mappedCsInterceptorDef);
269275

270276
RootBeanDefinition exceptionHandlerExceptionResolver = new RootBeanDefinition(ExceptionHandlerExceptionResolver.class);
271277
exceptionHandlerExceptionResolver.setSource(source);
@@ -275,25 +281,24 @@ else if (element.hasAttribute("ignoreDefaultModelOnRedirect")) {
275281
exceptionHandlerExceptionResolver.getPropertyValues().add("order", 0);
276282
addResponseBodyAdvice(exceptionHandlerExceptionResolver);
277283

278-
String methodExceptionResolverName =
279-
parserContext.getReaderContext().registerWithGeneratedName(exceptionHandlerExceptionResolver);
284+
String methodExceptionResolverName = readerContext.registerWithGeneratedName(exceptionHandlerExceptionResolver);
280285

281286
RootBeanDefinition responseStatusExceptionResolver = new RootBeanDefinition(ResponseStatusExceptionResolver.class);
282287
responseStatusExceptionResolver.setSource(source);
283288
responseStatusExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
284289
responseStatusExceptionResolver.getPropertyValues().add("order", 1);
285290
String responseStatusExceptionResolverName =
286-
parserContext.getReaderContext().registerWithGeneratedName(responseStatusExceptionResolver);
291+
readerContext.registerWithGeneratedName(responseStatusExceptionResolver);
287292

288293
RootBeanDefinition defaultExceptionResolver = new RootBeanDefinition(DefaultHandlerExceptionResolver.class);
289294
defaultExceptionResolver.setSource(source);
290295
defaultExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
291296
defaultExceptionResolver.getPropertyValues().add("order", 2);
292297
String defaultExceptionResolverName =
293-
parserContext.getReaderContext().registerWithGeneratedName(defaultExceptionResolver);
298+
readerContext.registerWithGeneratedName(defaultExceptionResolver);
294299

295-
parserContext.registerComponent(new BeanComponentDefinition(handlerMappingDef, methodMappingName));
296-
parserContext.registerComponent(new BeanComponentDefinition(handlerAdapterDef, handlerAdapterName));
300+
parserContext.registerComponent(new BeanComponentDefinition(handlerMappingDef, HANDLER_MAPPING_BEAN_NAME));
301+
parserContext.registerComponent(new BeanComponentDefinition(handlerAdapterDef, HANDLER_ADAPTER_BEAN_NAME));
297302
parserContext.registerComponent(new BeanComponentDefinition(uriCompContribDef, uriCompContribName));
298303
parserContext.registerComponent(new BeanComponentDefinition(exceptionHandlerExceptionResolver, methodExceptionResolverName));
299304
parserContext.registerComponent(new BeanComponentDefinition(responseStatusExceptionResolver, responseStatusExceptionResolverName));
@@ -349,14 +354,13 @@ else if (javaxValidationPresent) {
349354
}
350355
}
351356

352-
private RuntimeBeanReference getContentNegotiationManager(Element element, Object source, ParserContext parserContext) {
353-
RuntimeBeanReference contentNegotiationManagerRef;
357+
private RuntimeBeanReference getContentNegotiationManager(Element element, Object source,
358+
ParserContext parserContext) {
359+
360+
RuntimeBeanReference beanRef;
354361
if (element.hasAttribute("content-negotiation-manager")) {
355362
String name = element.getAttribute("content-negotiation-manager");
356-
contentNegotiationManagerRef = new RuntimeBeanReference(name);
357-
if (!CONTENT_NEGOTIATION_MANAGER_BEAN_NAME.equals(name)) {
358-
parserContext.getRegistry().registerAlias(name, CONTENT_NEGOTIATION_MANAGER_BEAN_NAME);
359-
}
363+
beanRef = new RuntimeBeanReference(name);
360364
}
361365
else {
362366
RootBeanDefinition factoryBeanDef = new RootBeanDefinition(ContentNegotiationManagerFactoryBean.class);
@@ -367,13 +371,14 @@ private RuntimeBeanReference getContentNegotiationManager(Element element, Objec
367371
String name = CONTENT_NEGOTIATION_MANAGER_BEAN_NAME;
368372
parserContext.getReaderContext().getRegistry().registerBeanDefinition(name , factoryBeanDef);
369373
parserContext.registerComponent(new BeanComponentDefinition(factoryBeanDef, name));
370-
contentNegotiationManagerRef = new RuntimeBeanReference(name);
374+
beanRef = new RuntimeBeanReference(name);
371375
}
372-
return contentNegotiationManagerRef;
376+
return beanRef;
373377
}
374378

375-
private void configurePathMatchingProperties(RootBeanDefinition handlerMappingDef,
376-
Element element, ParserContext parserContext) {
379+
private void configurePathMatchingProperties(RootBeanDefinition handlerMappingDef, Element element,
380+
ParserContext parserContext) {
381+
377382
Element pathMatchingElement = DomUtils.getChildElementByTagName(element, "path-matching");
378383
if (pathMatchingElement != null) {
379384
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
@@ -185,11 +185,24 @@ private BeanDefinition createContentNegotiatingViewResolver(Element resolverElem
185185
if (resolverElement.hasAttribute("use-not-acceptable")) {
186186
values.add("useNotAcceptableStatusCode", resolverElement.getAttribute("use-not-acceptable"));
187187
}
188-
String name = AnnotationDrivenBeanDefinitionParser.CONTENT_NEGOTIATION_MANAGER_BEAN_NAME;
189-
if (context.getRegistry().containsBeanDefinition(name) || context.getRegistry().isAlias(name)) {
190-
values.add("contentNegotiationManager", new RuntimeBeanReference(name));
188+
Object manager = getContentNegotiationManager(context);
189+
if (manager != null) {
190+
values.add("contentNegotiationManager", manager);
191191
}
192192
return beanDef;
193193
}
194194

195+
private Object getContentNegotiationManager(ParserContext context) {
196+
String name = AnnotationDrivenBeanDefinitionParser.HANDLER_MAPPING_BEAN_NAME;
197+
if (context.getRegistry().containsBeanDefinition(name)) {
198+
BeanDefinition handlerMappingBeanDef = context.getRegistry().getBeanDefinition(name);
199+
return handlerMappingBeanDef.getPropertyValues().get("contentNegotiationManager");
200+
}
201+
name = AnnotationDrivenBeanDefinitionParser.CONTENT_NEGOTIATION_MANAGER_BEAN_NAME;
202+
if (context.getRegistry().containsBeanDefinition(name)) {
203+
return new RuntimeBeanReference(name);
204+
}
205+
return null;
206+
}
207+
195208
}

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
@@ -680,7 +680,7 @@ public void testViewControllersDefaultConfig() {
680680

681681
@Test
682682
public void testContentNegotiationManager() throws Exception {
683-
loadBeanDefinitions("mvc-config-content-negotiation-manager.xml", 15);
683+
loadBeanDefinitions("mvc-config-content-negotiation-manager.xml", 14);
684684

685685
RequestMappingHandlerMapping mapping = appContext.getBean(RequestMappingHandlerMapping.class);
686686
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)