Skip to content

Commit

Permalink
Allow overriding ThemeResolver and FlashMapManager beans
Browse files Browse the repository at this point in the history
Previously, an error would occur when a user contributed a
`ThemeResolver` or `FlashMapManager` bean because those beans would
would not properly override the default beans provided by Spring
Framework. This commit adds conditional auto-configuration of these
bean types, preferring user-provided beans and falling back to
Framework-provided defaults.

Fixes gh-24207
  • Loading branch information
scottfrederick committed Jan 7, 2021
1 parent cca8a38 commit ef7a827
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 2 deletions.
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2020 the original author or authors.
* Copyright 2012-2021 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 @@ -92,8 +92,10 @@
import org.springframework.web.filter.HiddenHttpMethodFilter;
import org.springframework.web.filter.RequestContextFilter;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.FlashMapManager;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.ThemeResolver;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer;
Expand Down Expand Up @@ -134,6 +136,7 @@
* @author Kristine Jetzke
* @author Bruce Brouwer
* @author Artsiom Yudovin
* @author Scott Frederick
* @since 2.0.0
*/
@Configuration(proxyBeanMethods = false)
Expand Down Expand Up @@ -463,6 +466,20 @@ public LocaleResolver localeResolver() {
return localeResolver;
}

@Override
@Bean
@ConditionalOnMissingBean(name = DispatcherServlet.THEME_RESOLVER_BEAN_NAME)
public ThemeResolver themeResolver() {
return super.themeResolver();
}

@Override
@Bean
@ConditionalOnMissingBean(name = DispatcherServlet.FLASH_MAP_MANAGER_BEAN_NAME)
public FlashMapManager flashMapManager() {
return super.flashMapManager();
}

private Optional<Resource> getWelcomePage() {
String[] locations = getResourceLocations(this.resourceProperties.getStaticLocations());
return Arrays.stream(locations).map(this::getIndexHtml).filter(this::isReadable).findFirst();
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2020 the original author or authors.
* Copyright 2012-2021 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 @@ -87,10 +87,13 @@
import org.springframework.web.filter.HiddenHttpMethodFilter;
import org.springframework.web.filter.RequestContextFilter;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.FlashMap;
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.ThemeResolver;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer;
Expand Down Expand Up @@ -119,6 +122,9 @@
import org.springframework.web.servlet.resource.ResourceTransformer;
import org.springframework.web.servlet.resource.VersionResourceResolver;
import org.springframework.web.servlet.resource.VersionStrategy;
import org.springframework.web.servlet.support.AbstractFlashMapManager;
import org.springframework.web.servlet.support.SessionFlashMapManager;
import org.springframework.web.servlet.theme.FixedThemeResolver;
import org.springframework.web.servlet.view.AbstractView;
import org.springframework.web.servlet.view.ContentNegotiatingViewResolver;
import org.springframework.web.util.UrlPathHelper;
Expand All @@ -137,6 +143,7 @@
* @author Eddú Meléndez
* @author Kristine Jetzke
* @author Artsiom Yudovin
* @author Scott Frederick
*/
class WebMvcAutoConfigurationTests {

Expand Down Expand Up @@ -362,6 +369,42 @@ void customLocaleResolverWithDifferentNameDoesNotReplaceAutoConfiguredLocaleReso
});
}

@Test
void customThemeResolverWithMatchingNameReplacesDefaultThemeResolver() {
this.contextRunner.withBean("themeResolver", CustomThemeResolver.class, CustomThemeResolver::new)
.run((context) -> {
assertThat(context).hasSingleBean(ThemeResolver.class);
assertThat(context.getBean("themeResolver")).isInstanceOf(CustomThemeResolver.class);
});
}

@Test
void customThemeResolverWithDifferentNameDoesNotReplaceDefaultThemeResolver() {
this.contextRunner.withBean("customThemeResolver", CustomThemeResolver.class, CustomThemeResolver::new)
.run((context) -> {
assertThat(context.getBean("customThemeResolver")).isInstanceOf(CustomThemeResolver.class);
assertThat(context.getBean("themeResolver")).isInstanceOf(FixedThemeResolver.class);
});
}

@Test
void customFlashMapManagerWithMatchingNameReplacesDefaultFlashMapManager() {
this.contextRunner.withBean("flashMapManager", CustomFlashMapManager.class, CustomFlashMapManager::new)
.run((context) -> {
assertThat(context).hasSingleBean(FlashMapManager.class);
assertThat(context.getBean("flashMapManager")).isInstanceOf(CustomFlashMapManager.class);
});
}

@Test
void customFlashMapManagerWithDifferentNameDoesNotReplaceDefaultFlashMapManager() {
this.contextRunner.withBean("customFlashMapManager", CustomFlashMapManager.class, CustomFlashMapManager::new)
.run((context) -> {
assertThat(context.getBean("customFlashMapManager")).isInstanceOf(CustomFlashMapManager.class);
assertThat(context.getBean("flashMapManager")).isInstanceOf(SessionFlashMapManager.class);
});
}

@Test
void defaultDateFormat() {
this.contextRunner.run((context) -> {
Expand Down Expand Up @@ -1407,4 +1450,33 @@ public void setLocale(HttpServletRequest request, HttpServletResponse response,

}

static class CustomThemeResolver implements ThemeResolver {

@Override
public String resolveThemeName(HttpServletRequest request) {
return "custom";
}

@Override
public void setThemeName(HttpServletRequest request, HttpServletResponse response, String themeName) {

}

}

static class CustomFlashMapManager extends AbstractFlashMapManager {

@Override
protected List<FlashMap> retrieveFlashMaps(HttpServletRequest request) {
return null;
}

@Override
protected void updateFlashMaps(List<FlashMap> flashMaps, HttpServletRequest request,
HttpServletResponse response) {

}

}

}

0 comments on commit ef7a827

Please sign in to comment.