Skip to content

Commit

Permalink
Align DispatcherServlet defaults for Java and XML
Browse files Browse the repository at this point in the history
Prior to this commit some of the default strategies defined
for the DispatcherServlet weren't included in the default
configuration for both Java and XML configuration.

The following default beans have been added to the configuration
with the name as expected by the DispatcherServlet:

- org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver
- org.springframework.web.servlet.theme.FixedThemeResolver
- org.springframework.web.servlet.support.SessionFlashMapManager
- org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator

Closes gh-25209
  • Loading branch information
mdeinum authored and sdeleuze committed Jun 18, 2020
1 parent edf25ce commit bad81ce
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2020 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.
Expand Down Expand Up @@ -28,17 +28,23 @@
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping;
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver;
import org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter;
import org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter;
import org.springframework.web.servlet.support.SessionFlashMapManager;
import org.springframework.web.servlet.theme.FixedThemeResolver;
import org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator;
import org.springframework.web.util.UrlPathHelper;

/**
* Convenience methods for use in MVC namespace BeanDefinitionParsers.
*
* @author Rossen Stoyanchev
* @author Brian Clozel
* @author Marten Deinum
* @since 3.1
*/
public abstract class MvcNamespaceUtils {
Expand Down Expand Up @@ -66,6 +72,10 @@ public static void registerDefaultComponents(ParserContext parserContext, @Nulla
registerHttpRequestHandlerAdapter(parserContext, source);
registerSimpleControllerHandlerAdapter(parserContext, source);
registerHandlerMappingIntrospector(parserContext, source);
registerThemeResolver(parserContext, source);
registerLocaleResolver(parserContext, source);
registerFlashMapManager(parserContext, source);
registerViewNameTranslator(parserContext, source);
}

/**
Expand Down Expand Up @@ -205,6 +215,62 @@ private static void registerHandlerMappingIntrospector(ParserContext parserConte
}
}

/**
* Registers an {@link FixedThemeResolver} under a well-known name
* unless already registered.
*/
private static void registerThemeResolver(ParserContext parserContext, @Nullable Object source) {
if (!parserContext.getRegistry().containsBeanDefinition(DispatcherServlet.THEME_RESOLVER_BEAN_NAME)) {
RootBeanDefinition beanDef = new RootBeanDefinition(FixedThemeResolver.class);
beanDef.setSource(source);
beanDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
parserContext.getRegistry().registerBeanDefinition(DispatcherServlet.THEME_RESOLVER_BEAN_NAME, beanDef);
parserContext.registerComponent(new BeanComponentDefinition(beanDef, DispatcherServlet.THEME_RESOLVER_BEAN_NAME));
}
}

/**
* Registers an {@link AcceptHeaderLocaleResolver} under a well-known name
* unless already registered.
*/
private static void registerLocaleResolver(ParserContext parserContext, @Nullable Object source) {
if (!parserContext.getRegistry().containsBeanDefinition(DispatcherServlet.LOCALE_RESOLVER_BEAN_NAME)) {
RootBeanDefinition beanDef = new RootBeanDefinition(AcceptHeaderLocaleResolver.class);
beanDef.setSource(source);
beanDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
parserContext.getRegistry().registerBeanDefinition(DispatcherServlet.LOCALE_RESOLVER_BEAN_NAME, beanDef);
parserContext.registerComponent(new BeanComponentDefinition(beanDef, DispatcherServlet.LOCALE_RESOLVER_BEAN_NAME));
}
}

/**
* Registers an {@link SessionFlashMapManager} under a well-known name
* unless already registered.
*/
private static void registerFlashMapManager(ParserContext parserContext, @Nullable Object source) {
if (!parserContext.getRegistry().containsBeanDefinition(DispatcherServlet.FLASH_MAP_MANAGER_BEAN_NAME)) {
RootBeanDefinition beanDef = new RootBeanDefinition(SessionFlashMapManager.class);
beanDef.setSource(source);
beanDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
parserContext.getRegistry().registerBeanDefinition(DispatcherServlet.FLASH_MAP_MANAGER_BEAN_NAME, beanDef);
parserContext.registerComponent(new BeanComponentDefinition(beanDef, DispatcherServlet.FLASH_MAP_MANAGER_BEAN_NAME));
}
}

/**
* Registers an {@link DefaultRequestToViewNameTranslator} under a well-known name
* unless already registered.
*/
private static void registerViewNameTranslator(ParserContext parserContext, @Nullable Object source) {
if (!parserContext.getRegistry().containsBeanDefinition(DispatcherServlet.REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME)) {
RootBeanDefinition beanDef = new RootBeanDefinition(DefaultRequestToViewNameTranslator.class);
beanDef.setSource(source);
beanDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
parserContext.getRegistry().registerBeanDefinition(DispatcherServlet.REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME, beanDef);
parserContext.registerComponent(new BeanComponentDefinition(beanDef, DispatcherServlet.REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME));
}
}

/**
* Find the {@code ContentNegotiationManager} bean created by or registered
* with the {@code annotation-driven} element.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,13 @@
import org.springframework.web.method.support.CompositeUriComponentsContributor;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.FlashMapManager;
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.RequestToViewNameTranslator;
import org.springframework.web.servlet.ThemeResolver;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.function.support.HandlerFunctionAdapter;
import org.springframework.web.servlet.function.support.RouterFunctionMapping;
Expand All @@ -85,6 +89,7 @@
import org.springframework.web.servlet.handler.ConversionServiceExposingInterceptor;
import org.springframework.web.servlet.handler.HandlerExceptionResolverComposite;
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver;
import org.springframework.web.servlet.mvc.Controller;
import org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter;
import org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter;
Expand All @@ -97,6 +102,9 @@
import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver;
import org.springframework.web.servlet.resource.ResourceUrlProvider;
import org.springframework.web.servlet.resource.ResourceUrlProviderExposingInterceptor;
import org.springframework.web.servlet.support.SessionFlashMapManager;
import org.springframework.web.servlet.theme.FixedThemeResolver;
import org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.ViewResolverComposite;
import org.springframework.web.util.UrlPathHelper;
Expand Down Expand Up @@ -1099,6 +1107,26 @@ public HandlerMappingIntrospector mvcHandlerMappingIntrospector() {
return new HandlerMappingIntrospector();
}

@Bean
public LocaleResolver localeResolver() {
return new AcceptHeaderLocaleResolver();
}

@Bean
public ThemeResolver themeResolver() {
return new FixedThemeResolver();
}

@Bean
public FlashMapManager flashMapManager() {
return new SessionFlashMapManager();
}

@Bean
public RequestToViewNameTranslator viewNameTranslator() {
return new DefaultRequestToViewNameTranslator();
}


private static final class NoOpValidator implements Validator {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2020 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.
Expand Down Expand Up @@ -85,9 +85,13 @@
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.method.support.CompositeUriComponentsContributor;
import org.springframework.web.method.support.InvocableHandlerMethod;
import org.springframework.web.servlet.FlashMapManager;
import org.springframework.web.servlet.HandlerExecutionChain;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.RequestToViewNameTranslator;
import org.springframework.web.servlet.ThemeResolver;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.handler.AbstractHandlerMapping;
import org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping;
Expand Down Expand Up @@ -154,6 +158,7 @@
* @author Sebastien Deleuze
* @author Kazuki Shimizu
* @author Sam Brannen
* @author Marten Deinum
*/
public class MvcNamespaceTests {

Expand Down Expand Up @@ -221,6 +226,10 @@ public void testDefaultConfig() throws Exception {
assertThat(appContext.getBean(ConversionService.class)).isNotNull();
assertThat(appContext.getBean(LocalValidatorFactoryBean.class)).isNotNull();
assertThat(appContext.getBean(Validator.class)).isNotNull();
assertThat(appContext.getBean("themeResolver", ThemeResolver.class)).isNotNull();
assertThat(appContext.getBean("localeResolver", LocaleResolver.class)).isNotNull();
assertThat(appContext.getBean("flashMapManager", FlashMapManager.class)).isNotNull();
assertThat(appContext.getBean("viewNameTranslator", RequestToViewNameTranslator.class)).isNotNull();

// default web binding initializer behavior test
request = new MockHttpServletRequest("GET", "/");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,18 @@
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.FlashMapManager;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.HandlerExecutionChain;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.RequestToViewNameTranslator;
import org.springframework.web.servlet.ThemeResolver;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping;
import org.springframework.web.servlet.handler.ConversionServiceExposingInterceptor;
import org.springframework.web.servlet.handler.HandlerExceptionResolverComposite;
import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver;
import org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver;
import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver;
import org.springframework.web.servlet.mvc.method.annotation.JsonViewRequestBodyAdvice;
Expand All @@ -79,7 +84,10 @@
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver;
import org.springframework.web.servlet.resource.ResourceUrlProviderExposingInterceptor;
import org.springframework.web.servlet.support.SessionFlashMapManager;
import org.springframework.web.servlet.theme.FixedThemeResolver;
import org.springframework.web.servlet.view.BeanNameViewResolver;
import org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.ViewResolverComposite;
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
Expand All @@ -90,6 +98,10 @@
import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;
import static com.fasterxml.jackson.databind.MapperFeature.DEFAULT_VIEW_INCLUSION;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.web.servlet.DispatcherServlet.FLASH_MAP_MANAGER_BEAN_NAME;
import static org.springframework.web.servlet.DispatcherServlet.LOCALE_RESOLVER_BEAN_NAME;
import static org.springframework.web.servlet.DispatcherServlet.REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME;
import static org.springframework.web.servlet.DispatcherServlet.THEME_RESOLVER_BEAN_NAME;

/**
* Integration tests for {@link WebMvcConfigurationSupport} (imported via
Expand All @@ -99,6 +111,7 @@
* @author Juergen Hoeller
* @author Sebastien Deleuze
* @author Sam Brannen
* @author Marten Deinum
*/
public class WebMvcConfigurationSupportTests {

Expand Down Expand Up @@ -310,6 +323,44 @@ public void defaultPathMatchConfiguration() {
assertThat(pathMatcher.getClass()).isEqualTo(AntPathMatcher.class);
}

@Test
public void defaultLocaleResolverConfiguration() {
ApplicationContext context = initContext(WebConfig.class);
LocaleResolver localeResolver = context.getBean(LOCALE_RESOLVER_BEAN_NAME, LocaleResolver.class);

assertThat(localeResolver).isNotNull();
assertThat(localeResolver).isInstanceOf(AcceptHeaderLocaleResolver.class);
}

@Test
public void defaultThemeResolverfiguration() {
ApplicationContext context = initContext(WebConfig.class);
ThemeResolver themeResolver = context.getBean(THEME_RESOLVER_BEAN_NAME, ThemeResolver.class);

assertThat(themeResolver).isNotNull();
assertThat(themeResolver).isInstanceOf(FixedThemeResolver.class);
}

@Test
public void defaultFlashMapManagerConfiguration() {
ApplicationContext context = initContext(WebConfig.class);
FlashMapManager flashMapManager = context.getBean(FLASH_MAP_MANAGER_BEAN_NAME, FlashMapManager.class);

assertThat(flashMapManager).isNotNull();
assertThat(flashMapManager).isInstanceOf(SessionFlashMapManager.class);
}

@Test
public void defaultRequestToViewNameConfiguration() throws Exception {
ApplicationContext context = initContext(WebConfig.class);
RequestToViewNameTranslator requestToViewNameTranslator;
requestToViewNameTranslator = context.getBean(REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME,
RequestToViewNameTranslator.class);

assertThat(requestToViewNameTranslator).isNotNull();
assertThat(requestToViewNameTranslator).isInstanceOf(DefaultRequestToViewNameTranslator.class);
}

private ApplicationContext initContext(Class<?>... configClasses) {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.setServletContext(new MockServletContext());
Expand Down

0 comments on commit bad81ce

Please sign in to comment.