From 563a120280e4fa484f594f42ec268bab0094ed4a Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Thu, 29 Oct 2015 18:01:00 -0400 Subject: [PATCH] Detect custom ContentNegotiationViewResolver The element now adds an alias when a ContentNegotiationManager bean is registered with a custom name. This helps to more reliably find such a custom ContentNegotiationManager. Issue: SPR-13559 --- .../AnnotationDrivenBeanDefinitionParser.java | 16 ++++++++++------ .../ViewResolversBeanDefinitionParser.java | 6 +++--- .../view/ContentNegotiatingViewResolver.java | 4 ++++ .../web/servlet/config/MvcNamespaceTests.java | 11 ++++++++++- .../mvc-config-content-negotiation-manager.xml | 4 ++++ 5 files changed, 31 insertions(+), 10 deletions(-) diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java index 588a64c3e65..3d60cea0865 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -352,7 +352,11 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser { private RuntimeBeanReference getContentNegotiationManager(Element element, Object source, ParserContext parserContext) { RuntimeBeanReference contentNegotiationManagerRef; if (element.hasAttribute("content-negotiation-manager")) { - contentNegotiationManagerRef = new RuntimeBeanReference(element.getAttribute("content-negotiation-manager")); + String name = element.getAttribute("content-negotiation-manager"); + contentNegotiationManagerRef = new RuntimeBeanReference(name); + if (!CONTENT_NEGOTIATION_MANAGER_BEAN_NAME.equals(name)) { + parserContext.getRegistry().registerAlias(name, CONTENT_NEGOTIATION_MANAGER_BEAN_NAME); + } } else { RootBeanDefinition factoryBeanDef = new RootBeanDefinition(ContentNegotiationManagerFactoryBean.class); @@ -360,10 +364,10 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser { factoryBeanDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); factoryBeanDef.getPropertyValues().add("mediaTypes", getDefaultMediaTypes()); - String beanName = CONTENT_NEGOTIATION_MANAGER_BEAN_NAME; - parserContext.getReaderContext().getRegistry().registerBeanDefinition(beanName , factoryBeanDef); - parserContext.registerComponent(new BeanComponentDefinition(factoryBeanDef, beanName)); - contentNegotiationManagerRef = new RuntimeBeanReference(beanName); + String name = CONTENT_NEGOTIATION_MANAGER_BEAN_NAME; + parserContext.getReaderContext().getRegistry().registerBeanDefinition(name , factoryBeanDef); + parserContext.registerComponent(new BeanComponentDefinition(factoryBeanDef, name)); + contentNegotiationManagerRef = new RuntimeBeanReference(name); } return contentNegotiationManagerRef; } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/ViewResolversBeanDefinitionParser.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/ViewResolversBeanDefinitionParser.java index 37ce259f926..a048a6aacee 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/ViewResolversBeanDefinitionParser.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/ViewResolversBeanDefinitionParser.java @@ -185,9 +185,9 @@ public class ViewResolversBeanDefinitionParser implements BeanDefinitionParser { if (resolverElement.hasAttribute("use-not-acceptable")) { values.add("useNotAcceptableStatusCode", resolverElement.getAttribute("use-not-acceptable")); } - String beanName = AnnotationDrivenBeanDefinitionParser.CONTENT_NEGOTIATION_MANAGER_BEAN_NAME; - if (context.getRegistry().containsBeanDefinition(beanName)) { - values.add("contentNegotiationManager", new RuntimeBeanReference(beanName)); + String name = AnnotationDrivenBeanDefinitionParser.CONTENT_NEGOTIATION_MANAGER_BEAN_NAME; + if (context.getRegistry().containsBeanDefinition(name) || context.getRegistry().isAlias(name)) { + values.add("contentNegotiationManager", new RuntimeBeanReference(name)); } return beanDef; } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/ContentNegotiatingViewResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/ContentNegotiatingViewResolver.java index bfc766aa96e..97c9d14bc4a 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/ContentNegotiatingViewResolver.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/ContentNegotiatingViewResolver.java @@ -124,6 +124,10 @@ public class ContentNegotiatingViewResolver extends WebApplicationObjectSupport this.contentNegotiationManager = contentNegotiationManager; } + public ContentNegotiationManager getContentNegotiationManager() { + return this.contentNegotiationManager; + } + /** * Indicate whether the extension of the request path should be used to determine the requested media type, * in favor of looking at the {@code Accept} header. The default value is {@code true}. diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/MvcNamespaceTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/MvcNamespaceTests.java index 0967961bd50..c24f2c73e0b 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/MvcNamespaceTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/MvcNamespaceTests.java @@ -680,7 +680,7 @@ public class MvcNamespaceTests { @Test public void testContentNegotiationManager() throws Exception { - loadBeanDefinitions("mvc-config-content-negotiation-manager.xml", 13); + loadBeanDefinitions("mvc-config-content-negotiation-manager.xml", 15); RequestMappingHandlerMapping mapping = appContext.getBean(RequestMappingHandlerMapping.class); ContentNegotiationManager manager = mapping.getContentNegotiationManager(); @@ -688,6 +688,15 @@ public class MvcNamespaceTests { MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo.xml"); NativeWebRequest webRequest = new ServletWebRequest(request); assertEquals(Arrays.asList(MediaType.valueOf("application/rss+xml")), manager.resolveMediaTypes(webRequest)); + + ViewResolverComposite compositeResolver = this.appContext.getBean(ViewResolverComposite.class); + assertNotNull(compositeResolver); + assertEquals("Actual: " + compositeResolver.getViewResolvers(), 1, compositeResolver.getViewResolvers().size()); + + ViewResolver resolver = compositeResolver.getViewResolvers().get(0); + assertEquals(ContentNegotiatingViewResolver.class, resolver.getClass()); + ContentNegotiatingViewResolver cnvr = (ContentNegotiatingViewResolver) resolver; + assertSame(manager, cnvr.getContentNegotiationManager()); } @Test diff --git a/spring-webmvc/src/test/resources/org/springframework/web/servlet/config/mvc-config-content-negotiation-manager.xml b/spring-webmvc/src/test/resources/org/springframework/web/servlet/config/mvc-config-content-negotiation-manager.xml index 34d609b65cb..f213de087ae 100644 --- a/spring-webmvc/src/test/resources/org/springframework/web/servlet/config/mvc-config-content-negotiation-manager.xml +++ b/spring-webmvc/src/test/resources/org/springframework/web/servlet/config/mvc-config-content-negotiation-manager.xml @@ -9,6 +9,10 @@ + + + +