SPR-8289 Ensure BeanNameUrlHandlerMapping and default HandlerAdapters are never 'turned off' through the MVC namespaces

This commit is contained in:
Rossen Stoyanchev
2011-05-13 15:46:37 +00:00
parent 4dd5ae16b2
commit 5c0e22e7a8
10 changed files with 184 additions and 140 deletions

View File

@@ -1,57 +0,0 @@
/*
* Copyright 2002-2010 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.web.servlet.config;
import org.w3c.dom.Element;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter;
/**
* Abstract base class for {@link BeanDefinitonParser}s that register an HttpRequestHandler.
*
* @author Jeremy Grelle
* @since 3.0.4
*/
abstract class AbstractHttpRequestHandlerBeanDefinitionParser implements BeanDefinitionParser{
private static final String HANDLER_ADAPTER_BEAN_NAME = "org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter";
public BeanDefinition parse(Element element, ParserContext parserContext) {
Object source = parserContext.extractSource(element);
registerHandlerAdapterIfNecessary(parserContext, source);
doParse(element, parserContext);
return null;
}
public abstract void doParse(Element element, ParserContext parserContext);
private void registerHandlerAdapterIfNecessary(ParserContext parserContext, Object source) {
if (!parserContext.getRegistry().containsBeanDefinition(HANDLER_ADAPTER_BEAN_NAME)) {
RootBeanDefinition handlerAdapterDef = new RootBeanDefinition(HttpRequestHandlerAdapter.class);
handlerAdapterDef.setSource(source);
handlerAdapterDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
parserContext.getRegistry().registerBeanDefinition(HANDLER_ADAPTER_BEAN_NAME, handlerAdapterDef);
parserContext.registerComponent(new BeanComponentDefinition(handlerAdapterDef, HANDLER_ADAPTER_BEAN_NAME));
}
}
}

View File

@@ -45,6 +45,7 @@ import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
import org.springframework.web.bind.support.WebArgumentResolver;
import org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping;
import org.springframework.web.servlet.handler.ConversionServiceExposingInterceptor;
import org.springframework.web.servlet.handler.MappedInterceptor;
import org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver;
@@ -98,7 +99,6 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
private static boolean romePresent =
ClassUtils.isPresent("com.sun.syndication.feed.WireFeed", AnnotationDrivenBeanDefinitionParser.class.getClassLoader());
public BeanDefinition parse(Element element, ParserContext parserContext) {
Object source = parserContext.extractSource(element);
@@ -177,6 +177,13 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
parserContext.registerComponent(new BeanComponentDefinition(responseStatusExceptionResolver, responseStatusExceptionResolverName));
parserContext.registerComponent(new BeanComponentDefinition(defaultExceptionResolver, defaultExceptionResolverName));
parserContext.registerComponent(new BeanComponentDefinition(mappedCsInterceptorDef, mappedInterceptorName));
// Ensure BeanNameUrlHandlerMapping is not "turned off" (SPR-8289)
MvcNamespaceUtils.registerBeanNameUrlHandlerMapping(parserContext, source);
// Ensure default HandlerAdapters are not "turned off"
MvcNamespaceUtils.registerDefaultHandlerAdapters(parserContext, source);
parserContext.popAndRegisterContainingComponent();
return null;
@@ -317,4 +324,5 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
return result;
}
}

View File

@@ -35,15 +35,15 @@ import org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler
* {@link BeanDefinitionParser} that parses a {@code default-servlet-handler} element to
* register a {@link DefaultServletHttpRequestHandler}. Will also register a
* {@link SimpleUrlHandlerMapping} for mapping resource requests, and a
* {@link HttpRequestHandlerAdapter} if necessary.
* {@link HttpRequestHandlerAdapter}.
*
* @author Jeremy Grelle
* @author Rossen Stoyanchev
* @since 3.0.4
*/
class DefaultServletHandlerBeanDefinitionParser extends AbstractHttpRequestHandlerBeanDefinitionParser {
class DefaultServletHandlerBeanDefinitionParser implements BeanDefinitionParser {
@Override
public void doParse(Element element, ParserContext parserContext) {
public BeanDefinition parse(Element element, ParserContext parserContext) {
Object source = parserContext.extractSource(element);
String defaultServletName = element.getAttribute("default-servlet-name");
@@ -68,6 +68,14 @@ class DefaultServletHandlerBeanDefinitionParser extends AbstractHttpRequestHandl
String handlerMappingBeanName = parserContext.getReaderContext().generateBeanName(handlerMappingDef);
parserContext.getRegistry().registerBeanDefinition(handlerMappingBeanName, handlerMappingDef);
parserContext.registerComponent(new BeanComponentDefinition(handlerMappingDef, handlerMappingBeanName));
// Ensure BeanNameUrlHandlerMapping is not "turned off" (SPR-8289)
MvcNamespaceUtils.registerBeanNameUrlHandlerMapping(parserContext, source);
// Register HttpRequestHandlerAdapter
MvcNamespaceUtils.registerDefaultHandlerAdapters(parserContext, source);
return null;
}
}

View File

@@ -0,0 +1,80 @@
/*
* Copyright 2002-2010 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.web.servlet.config;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping;
import org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter;
import org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter;
/**
* Convenience methods for MVC namespace handlers.
*
* @author Rossen Stoyanchev
* @since 3.1
*/
abstract class MvcNamespaceUtils {
private static final String BEAN_NAME_URL_HANDLER_MAPPING =
"org.springframework.web.servlet.handler.beanNameUrlHandlerMapping";
private static final String VIEW_CONTROLLER_HANDLER_ADAPTER =
"org.springframework.web.servlet.config.viewControllerHandlerAdapter";
private static final String HTTP_REQUEST_HANDLER_ADAPTER =
"org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter";
public static void registerDefaultHandlerAdapters(ParserContext parserContext, Object source) {
registerHttpRequestHandlerAdapter(parserContext, source);
registerSimpleControllerHandlerAdapter(parserContext, source);
}
public static void registerBeanNameUrlHandlerMapping(ParserContext parserContext, Object source) {
if (!parserContext.getRegistry().containsBeanDefinition(BEAN_NAME_URL_HANDLER_MAPPING)){
RootBeanDefinition beanNameMappingDef = new RootBeanDefinition(BeanNameUrlHandlerMapping.class);
beanNameMappingDef.setSource(source);
beanNameMappingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
beanNameMappingDef.getPropertyValues().add("order", 2); // consistent with MvcConfiguration
parserContext.getRegistry().registerBeanDefinition(BEAN_NAME_URL_HANDLER_MAPPING, beanNameMappingDef);
parserContext.registerComponent(new BeanComponentDefinition(beanNameMappingDef, BEAN_NAME_URL_HANDLER_MAPPING));
}
}
public static void registerHttpRequestHandlerAdapter(ParserContext parserContext, Object source) {
if (!parserContext.getRegistry().containsBeanDefinition(HTTP_REQUEST_HANDLER_ADAPTER)) {
RootBeanDefinition handlerAdapterDef = new RootBeanDefinition(HttpRequestHandlerAdapter.class);
handlerAdapterDef.setSource(source);
handlerAdapterDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
parserContext.getRegistry().registerBeanDefinition(HTTP_REQUEST_HANDLER_ADAPTER, handlerAdapterDef);
parserContext.registerComponent(new BeanComponentDefinition(handlerAdapterDef, HTTP_REQUEST_HANDLER_ADAPTER));
}
}
public static void registerSimpleControllerHandlerAdapter(ParserContext parserContext, Object source) {
if (!parserContext.getRegistry().containsBeanDefinition(VIEW_CONTROLLER_HANDLER_ADAPTER)) {
RootBeanDefinition handlerAdapterDef = new RootBeanDefinition(SimpleControllerHandlerAdapter.class);
handlerAdapterDef.setSource(source);
handlerAdapterDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
parserContext.getRegistry().registerBeanDefinition(VIEW_CONTROLLER_HANDLER_ADAPTER, handlerAdapterDef);
parserContext.registerComponent(new BeanComponentDefinition(handlerAdapterDef, VIEW_CONTROLLER_HANDLER_ADAPTER));
}
}
}

View File

@@ -36,31 +36,27 @@ import org.springframework.web.servlet.resource.ResourceHttpRequestHandler;
* {@link org.springframework.beans.factory.xml.BeanDefinitionParser} that parses a
* {@code resources} element to register a {@link ResourceHttpRequestHandler}.
* Will also register a {@link SimpleUrlHandlerMapping} for mapping resource requests,
* and a {@link HttpRequestHandlerAdapter} if necessary.
* and a {@link HttpRequestHandlerAdapter}.
*
* @author Keith Donald
* @author Jeremy Grelle
* @since 3.0.4
*/
class ResourcesBeanDefinitionParser extends AbstractHttpRequestHandlerBeanDefinitionParser implements BeanDefinitionParser {
class ResourcesBeanDefinitionParser implements BeanDefinitionParser {
@Override
public void doParse(Element element, ParserContext parserContext) {
public BeanDefinition parse(Element element, ParserContext parserContext) {
Object source = parserContext.extractSource(element);
registerResourceMappings(parserContext, element, source);
}
private void registerResourceMappings(ParserContext parserContext, Element element, Object source) {
String resourceHandlerName = registerResourceHandler(parserContext, element, source);
if (resourceHandlerName == null) {
return;
return null;
}
Map<String, String> urlMap = new ManagedMap<String, String>();
String resourceRequestPath = element.getAttribute("mapping");
if (!StringUtils.hasText(resourceRequestPath)) {
parserContext.getReaderContext().error("The 'mapping' attribute is required.", parserContext.extractSource(element));
return;
return null;
}
urlMap.put(resourceRequestPath, resourceHandlerName);
@@ -76,6 +72,14 @@ class ResourcesBeanDefinitionParser extends AbstractHttpRequestHandlerBeanDefini
String beanName = parserContext.getReaderContext().generateBeanName(handlerMappingDef);
parserContext.getRegistry().registerBeanDefinition(beanName, handlerMappingDef);
parserContext.registerComponent(new BeanComponentDefinition(handlerMappingDef, beanName));
// Ensure BeanNameUrlHandlerMapping is not "turned off" (SPR-8289)
MvcNamespaceUtils.registerBeanNameUrlHandlerMapping(parserContext, source);
// Register HttpRequestHandlerAdapter
MvcNamespaceUtils.registerDefaultHandlerAdapters(parserContext, source);
return null;
}
private String registerResourceHandler(ParserContext parserContext, Element element, Object source) {

View File

@@ -18,8 +18,6 @@ package org.springframework.web.servlet.config;
import java.util.Map;
import org.w3c.dom.Element;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.support.ManagedMap;
@@ -28,7 +26,7 @@ import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
import org.springframework.web.servlet.mvc.ParameterizableViewController;
import org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter;
import org.w3c.dom.Element;
/**
* {@link org.springframework.beans.factory.xml.BeanDefinitionParser} that parses a
@@ -41,9 +39,6 @@ import org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter;
*/
class ViewControllerBeanDefinitionParser implements BeanDefinitionParser {
private static final String HANDLER_ADAPTER_BEAN_NAME =
"org.springframework.web.servlet.config.viewControllerHandlerAdapter";
private static final String HANDLER_MAPPING_BEAN_NAME =
"org.springframework.web.servlet.config.viewControllerHandlerMapping";
@@ -51,12 +46,15 @@ class ViewControllerBeanDefinitionParser implements BeanDefinitionParser {
public BeanDefinition parse(Element element, ParserContext parserContext) {
Object source = parserContext.extractSource(element);
// Register handler adapter
registerHanderAdapter(parserContext, source);
// Register handler mapping
// Register SimpleUrlHandlerMapping for view controllers
BeanDefinition handlerMappingDef = registerHandlerMapping(parserContext, source);
// Ensure BeanNameUrlHandlerMapping is not "turned off" (SPR-8289)
MvcNamespaceUtils.registerBeanNameUrlHandlerMapping(parserContext, source);
// Register SimpleControllerHandlerAdapter
MvcNamespaceUtils.registerDefaultHandlerAdapters(parserContext, source);
// Create view controller bean definition
RootBeanDefinition viewControllerDef = new RootBeanDefinition(ParameterizableViewController.class);
viewControllerDef.setSource(source);
@@ -72,19 +70,10 @@ class ViewControllerBeanDefinitionParser implements BeanDefinitionParser {
handlerMappingDef.getPropertyValues().add("urlMap", urlMap);
}
urlMap.put(element.getAttribute("path"), viewControllerDef);
return null;
}
private void registerHanderAdapter(ParserContext parserContext, Object source) {
if (!parserContext.getRegistry().containsBeanDefinition(HANDLER_ADAPTER_BEAN_NAME)) {
RootBeanDefinition handlerAdapterDef = new RootBeanDefinition(SimpleControllerHandlerAdapter.class);
handlerAdapterDef.setSource(source);
handlerAdapterDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
parserContext.getRegistry().registerBeanDefinition(HANDLER_ADAPTER_BEAN_NAME, handlerAdapterDef);
parserContext.registerComponent(new BeanComponentDefinition(handlerAdapterDef, HANDLER_ADAPTER_BEAN_NAME));
}
}
private BeanDefinition registerHandlerMapping(ParserContext parserContext, Object source) {
if (!parserContext.getRegistry().containsBeanDefinition(HANDLER_MAPPING_BEAN_NAME)) {
RootBeanDefinition handlerMappingDef = new RootBeanDefinition(SimpleUrlHandlerMapping.class);
@@ -98,6 +87,7 @@ class ViewControllerBeanDefinitionParser implements BeanDefinitionParser {
else {
return parserContext.getRegistry().getBeanDefinition(HANDLER_MAPPING_BEAN_NAME);
}
}
}

View File

@@ -332,7 +332,7 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter i
}
}
public void afterPropertiesSet() throws Exception {
public void afterPropertiesSet() {
initArgumentResolvers();
initReturnValueHandlers();
initInitBinderArgumentResolvers();