Nullability fine-tuning (RequestContext, LocaleResolver)

Includes page-level JSTL time zone support for JSP tags.

Issue: SPR-15720
Issue: SPR-15746
This commit is contained in:
Juergen Hoeller
2017-07-07 18:46:19 +02:00
parent 4a3ca17d3f
commit 00f4c36d7a
25 changed files with 207 additions and 227 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2017 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.
@@ -17,7 +17,6 @@
package org.springframework.web.servlet;
import java.util.Locale;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -70,6 +69,7 @@ public interface LocaleContextResolver extends LocaleResolver {
* @see org.springframework.context.i18n.SimpleLocaleContext
* @see org.springframework.context.i18n.SimpleTimeZoneAwareLocaleContext
*/
void setLocaleContext(HttpServletRequest request, HttpServletResponse response, @Nullable LocaleContext localeContext);
void setLocaleContext(HttpServletRequest request, @Nullable HttpServletResponse response,
@Nullable LocaleContext localeContext);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2017 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.
@@ -17,7 +17,6 @@
package org.springframework.web.servlet;
import java.util.Locale;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -69,6 +68,6 @@ public interface LocaleResolver {
* @throws UnsupportedOperationException if the LocaleResolver
* implementation does not support dynamic changing of the locale
*/
void setLocale(HttpServletRequest request, HttpServletResponse response, @Nullable Locale locale);
void setLocale(HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable Locale locale);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2017 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.
@@ -64,6 +64,6 @@ public interface ThemeResolver {
* @throws UnsupportedOperationException if the ThemeResolver implementation
* does not support dynamic changing of the theme
*/
void setThemeName(HttpServletRequest request, HttpServletResponse response, @Nullable String themeName);
void setThemeName(HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable String themeName);
}

View File

@@ -26,6 +26,7 @@ import org.springframework.context.i18n.LocaleContext;
import org.springframework.context.i18n.SimpleLocaleContext;
import org.springframework.context.i18n.TimeZoneAwareLocaleContext;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.LocaleContextResolver;
import org.springframework.web.servlet.LocaleResolver;
@@ -84,8 +85,10 @@ public class CookieLocaleResolver extends CookieGenerator implements LocaleConte
private boolean languageTagCompliant = false;
@Nullable
private Locale defaultLocale;
@Nullable
private TimeZone defaultTimeZone;
@@ -224,12 +227,16 @@ public class CookieLocaleResolver extends CookieGenerator implements LocaleConte
}
@Override
public void setLocale(HttpServletRequest request, HttpServletResponse response, @Nullable Locale locale) {
public void setLocale(HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable Locale locale) {
setLocaleContext(request, response, (locale != null ? new SimpleLocaleContext(locale) : null));
}
@Override
public void setLocaleContext(HttpServletRequest request, HttpServletResponse response, @Nullable LocaleContext localeContext) {
public void setLocaleContext(HttpServletRequest request, @Nullable HttpServletResponse response,
@Nullable LocaleContext localeContext) {
Assert.notNull(response, "HttpServletResponse is required for CookieLocaleResolver");
Locale locale = null;
TimeZone timeZone = null;
if (localeContext != null) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2017 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.
@@ -93,7 +93,9 @@ public class FixedLocaleResolver extends AbstractLocaleContextResolver {
}
@Override
public void setLocaleContext(HttpServletRequest request, HttpServletResponse response, @Nullable LocaleContext localeContext) {
public void setLocaleContext( HttpServletRequest request, @Nullable HttpServletResponse response,
@Nullable LocaleContext localeContext) {
throw new UnsupportedOperationException("Cannot change fixed locale - use a different locale resolution strategy");
}

View File

@@ -18,7 +18,6 @@ package org.springframework.web.servlet.i18n;
import java.util.Locale;
import java.util.TimeZone;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -139,7 +138,9 @@ public class SessionLocaleResolver extends AbstractLocaleContextResolver {
}
@Override
public void setLocaleContext(HttpServletRequest request, HttpServletResponse response, @Nullable LocaleContext localeContext) {
public void setLocaleContext(HttpServletRequest request, @Nullable HttpServletResponse response,
@Nullable LocaleContext localeContext) {
Locale locale = null;
TimeZone timeZone = null;
if (localeContext != null) {

View File

@@ -93,9 +93,7 @@ public class BindStatus {
* @param htmlEscape whether to HTML-escape error messages and string values
* @throws IllegalStateException if no corresponding Errors object found
*/
public BindStatus(RequestContext requestContext, String path, boolean htmlEscape)
throws IllegalStateException {
public BindStatus(RequestContext requestContext, String path, boolean htmlEscape) throws IllegalStateException {
this.requestContext = requestContext;
this.path = path;
this.htmlEscape = htmlEscape;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2017 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.
@@ -18,7 +18,7 @@ package org.springframework.web.servlet.support;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.PageContext;
@@ -48,7 +48,7 @@ public class JspAwareRequestContext extends RequestContext {
* @param pageContext current JSP page context
*/
public JspAwareRequestContext(PageContext pageContext) {
initContext(pageContext, null);
this(pageContext, null);
}
/**
@@ -59,23 +59,9 @@ public class JspAwareRequestContext extends RequestContext {
* (can be {@code null}, using the request attributes for Errors retrieval)
*/
public JspAwareRequestContext(PageContext pageContext, @Nullable Map<String, Object> model) {
initContext(pageContext, model);
}
/**
* Initialize this context with the given page context,
* using the given model attributes for Errors retrieval.
* @param pageContext current JSP page context
* @param model the model attributes for the current view
* (can be {@code null}, using the request attributes for Errors retrieval)
*/
protected void initContext(PageContext pageContext, @Nullable Map<String, Object> model) {
if (!(pageContext.getRequest() instanceof HttpServletRequest)) {
throw new IllegalArgumentException("RequestContext only supports HTTP requests");
}
this.pageContext = pageContext;
initContext((HttpServletRequest) pageContext.getRequest(), (HttpServletResponse) pageContext.getResponse(),
super((HttpServletRequest) pageContext.getRequest(), (HttpServletResponse) pageContext.getResponse(),
pageContext.getServletContext(), model);
this.pageContext = pageContext;
}
@@ -88,9 +74,9 @@ public class JspAwareRequestContext extends RequestContext {
}
/**
* This implementation checks for a JSTL locale attribute
* in page, request, session or application scope; if not found,
* returns the {@code HttpServletRequest.getLocale()}.
* This implementation checks for a JSTL locale attribute in page,
* request, session or application scope; if not found, returns the
* {@code HttpServletRequest.getLocale()}.
*/
@Override
protected Locale getFallbackLocale() {
@@ -103,6 +89,21 @@ public class JspAwareRequestContext extends RequestContext {
return getRequest().getLocale();
}
/**
* This implementation checks for a JSTL time zone attribute in page,
* request, session or application scope; if not found, returns {@code null}.
*/
@Override
protected TimeZone getFallbackTimeZone() {
if (jstlPresent) {
TimeZone timeZone = JstlPageLocaleResolver.getJstlTimeZone(getPageContext());
if (timeZone != null) {
return timeZone;
}
}
return null;
}
/**
* Inner class that isolates the JSTL dependency.
@@ -114,6 +115,11 @@ public class JspAwareRequestContext extends RequestContext {
Object localeObject = Config.find(pageContext, Config.FMT_LOCALE);
return (localeObject instanceof Locale ? (Locale) localeObject : null);
}
public static TimeZone getJstlTimeZone(PageContext pageContext) {
Object timeZoneObject = Config.find(pageContext, Config.FMT_TIME_ZONE);
return (timeZoneObject instanceof TimeZone ? (TimeZone) timeZoneObject : null);
}
}
}

View File

@@ -73,7 +73,6 @@ import org.springframework.web.util.WebUtils;
* @see org.springframework.web.servlet.DispatcherServlet
* @see org.springframework.web.servlet.view.AbstractView#setRequestContextAttribute
* @see org.springframework.web.servlet.view.UrlBasedViewResolver#setRequestContextAttribute
* @see #getFallbackLocale()
*/
public class RequestContext {
@@ -95,7 +94,6 @@ public class RequestContext {
protected static final boolean jstlPresent = ClassUtils.isPresent(
"javax.servlet.jsp.jstl.core.Config", RequestContext.class.getClassLoader());
@Nullable
private HttpServletRequest request;
@Nullable
@@ -104,7 +102,6 @@ public class RequestContext {
@Nullable
private Map<String, Object> model;
@Nullable
private WebApplicationContext webApplicationContext;
@Nullable
@@ -122,7 +119,6 @@ public class RequestContext {
@Nullable
private Boolean responseEncodedHtmlEscape;
@Nullable
private UrlPathHelper urlPathHelper;
@Nullable
@@ -143,7 +139,7 @@ public class RequestContext {
* @see #RequestContext(javax.servlet.http.HttpServletRequest, javax.servlet.ServletContext)
*/
public RequestContext(HttpServletRequest request) {
initContext(request, null, null, null);
this(request, null, null, null);
}
/**
@@ -158,7 +154,7 @@ public class RequestContext {
* @see #RequestContext(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, javax.servlet.ServletContext, Map)
*/
public RequestContext(HttpServletRequest request, HttpServletResponse response) {
initContext(request, response, null, null);
this(request, response, null, null);
}
/**
@@ -174,7 +170,7 @@ public class RequestContext {
* @see org.springframework.web.servlet.DispatcherServlet
*/
public RequestContext(HttpServletRequest request, @Nullable ServletContext servletContext) {
initContext(request, null, servletContext, null);
this(request, null, servletContext, null);
}
/**
@@ -189,7 +185,7 @@ public class RequestContext {
* @see #RequestContext(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, javax.servlet.ServletContext, Map)
*/
public RequestContext(HttpServletRequest request, @Nullable Map<String, Object> model) {
initContext(request, null, null, model);
this(request, null, null, model);
}
/**
@@ -206,34 +202,7 @@ public class RequestContext {
* @see org.springframework.web.context.WebApplicationContext
* @see org.springframework.web.servlet.DispatcherServlet
*/
public RequestContext(HttpServletRequest request, HttpServletResponse response, @Nullable ServletContext servletContext,
@Nullable Map<String, Object> model) {
initContext(request, response, servletContext, model);
}
/**
* Default constructor for subclasses.
*/
protected RequestContext() {
}
/**
* Initialize this context with the given request, using the given model attributes for Errors retrieval.
* <p>Delegates to {@code getFallbackLocale} and {@code getFallbackTheme} for determining the fallback
* locale and theme, respectively, if no LocaleResolver and/or ThemeResolver can be found in the request.
* @param request current HTTP request
* @param servletContext the servlet context of the web application (can be {@code null}; necessary for
* fallback to root WebApplicationContext)
* @param model the model attributes for the current view (can be {@code null}, using the request
* attributes for Errors retrieval)
* @see #getFallbackLocale
* @see #getFallbackTheme
* @see org.springframework.web.servlet.DispatcherServlet#LOCALE_RESOLVER_ATTRIBUTE
* @see org.springframework.web.servlet.DispatcherServlet#THEME_RESOLVER_ATTRIBUTE
*/
protected void initContext(HttpServletRequest request, @Nullable HttpServletResponse response,
public RequestContext(HttpServletRequest request, @Nullable HttpServletResponse response,
@Nullable ServletContext servletContext, @Nullable Map<String, Object> model) {
this.request = request;
@@ -242,36 +211,35 @@ public class RequestContext {
// Fetch WebApplicationContext, either from DispatcherServlet or the root context.
// ServletContext needs to be specified to be able to fall back to the root context!
this.webApplicationContext = (WebApplicationContext) request.getAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE);
if (this.webApplicationContext == null) {
this.webApplicationContext = RequestContextUtils.findWebApplicationContext(request, servletContext);
if (this.webApplicationContext == null) {
WebApplicationContext wac = (WebApplicationContext) request.getAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE);
if (wac == null) {
wac = RequestContextUtils.findWebApplicationContext(request, servletContext);
if (wac == null) {
throw new IllegalStateException("No WebApplicationContext found: not in a DispatcherServlet " +
"request and no ContextLoaderListener registered?");
}
}
this.webApplicationContext = wac;
Locale locale = null;
TimeZone timeZone = null;
// Determine locale to use for this RequestContext.
LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);
if (localeResolver instanceof LocaleContextResolver) {
LocaleContext localeContext = ((LocaleContextResolver) localeResolver).resolveLocaleContext(request);
this.locale = localeContext.getLocale();
locale = localeContext.getLocale();
if (localeContext instanceof TimeZoneAwareLocaleContext) {
this.timeZone = ((TimeZoneAwareLocaleContext) localeContext).getTimeZone();
timeZone = ((TimeZoneAwareLocaleContext) localeContext).getTimeZone();
}
}
else if (localeResolver != null) {
// Try LocaleResolver (we're within a DispatcherServlet request).
this.locale = localeResolver.resolveLocale(request);
locale = localeResolver.resolveLocale(request);
}
// Try JSTL fallbacks if necessary.
if (this.locale == null) {
this.locale = getFallbackLocale();
}
if (this.timeZone == null) {
this.timeZone = getFallbackTimeZone();
}
this.locale = locale;
this.timeZone = timeZone;
// Determine default HTML escape setting from the "defaultHtmlEscape"
// context-param in web.xml, if any.
@@ -290,57 +258,6 @@ public class RequestContext {
}
}
/**
* Determine the fallback locale for this context.
* <p>The default implementation checks for a JSTL locale attribute in request, session
* or application scope; if not found, returns the {@code HttpServletRequest.getLocale()}.
* @return the fallback locale (never {@code null})
* @see javax.servlet.http.HttpServletRequest#getLocale()
*/
protected Locale getFallbackLocale() {
if (jstlPresent) {
Locale locale = JstlLocaleResolver.getJstlLocale(getRequest(), getServletContext());
if (locale != null) {
return locale;
}
}
return getRequest().getLocale();
}
/**
* Determine the fallback time zone for this context.
* <p>The default implementation checks for a JSTL time zone attribute in request,
* session or application scope; returns {@code null} if not found.
* @return the fallback time zone (or {@code null} if none derivable from the request)
*/
@Nullable
protected TimeZone getFallbackTimeZone() {
if (jstlPresent) {
TimeZone timeZone = JstlLocaleResolver.getJstlTimeZone(getRequest(), getServletContext());
if (timeZone != null) {
return timeZone;
}
}
return null;
}
/**
* Determine the fallback theme for this context.
* <p>The default implementation returns the default theme (with name "theme").
* @return the fallback theme (never {@code null})
*/
protected Theme getFallbackTheme() {
ThemeSource themeSource = RequestContextUtils.getThemeSource(getRequest());
if (themeSource == null) {
themeSource = new ResourceBundleThemeSource();
}
Theme theme = themeSource.getTheme(DEFAULT_THEME_NAME);
if (theme == null) {
throw new IllegalStateException("No theme defined and no fallback theme found");
}
return theme;
}
/**
* Return the underlying HttpServletRequest. Only intended for cooperating classes in this package.
@@ -387,7 +304,7 @@ public class RequestContext {
* @see RequestContextUtils#getLocale
*/
public final Locale getLocale() {
return this.locale;
return (this.locale != null ? this.locale : getFallbackLocale());
}
/**
@@ -398,7 +315,41 @@ public class RequestContext {
*/
@Nullable
public TimeZone getTimeZone() {
return this.timeZone;
return (this.timeZone != null ? this.timeZone : getFallbackTimeZone());
}
/**
* Determine the fallback locale for this context.
* <p>The default implementation checks for a JSTL locale attribute in request, session
* or application scope; if not found, returns the {@code HttpServletRequest.getLocale()}.
* @return the fallback locale (never {@code null})
* @see javax.servlet.http.HttpServletRequest#getLocale()
*/
protected Locale getFallbackLocale() {
if (jstlPresent) {
Locale locale = JstlLocaleResolver.getJstlLocale(getRequest(), getServletContext());
if (locale != null) {
return locale;
}
}
return getRequest().getLocale();
}
/**
* Determine the fallback time zone for this context.
* <p>The default implementation checks for a JSTL time zone attribute in request,
* session or application scope; returns {@code null} if not found.
* @return the fallback time zone (or {@code null} if none derivable from the request)
*/
@Nullable
protected TimeZone getFallbackTimeZone() {
if (jstlPresent) {
TimeZone timeZone = JstlLocaleResolver.getJstlTimeZone(getRequest(), getServletContext());
if (timeZone != null) {
return timeZone;
}
}
return null;
}
/**
@@ -452,6 +403,23 @@ public class RequestContext {
return this.theme;
}
/**
* Determine the fallback theme for this context.
* <p>The default implementation returns the default theme (with name "theme").
* @return the fallback theme (never {@code null})
*/
protected Theme getFallbackTheme() {
ThemeSource themeSource = RequestContextUtils.getThemeSource(getRequest());
if (themeSource == null) {
themeSource = new ResourceBundleThemeSource();
}
Theme theme = themeSource.getTheme(DEFAULT_THEME_NAME);
if (theme == null) {
throw new IllegalStateException("No theme defined and no fallback theme found");
}
return theme;
}
/**
* Change the current theme to the specified one,
* storing the new theme name through the configured {@link ThemeResolver}.
@@ -524,6 +492,7 @@ public class RequestContext {
* @return whether default use of response encoding HTML escaping is enabled (null = no explicit default)
* @since 4.1.2
*/
@Nullable
public Boolean getResponseEncodedHtmlEscape() {
return this.responseEncodedHtmlEscape;
}
@@ -683,7 +652,7 @@ public class RequestContext {
* @return the message
*/
public String getMessage(String code, @Nullable Object[] args, String defaultMessage, boolean htmlEscape) {
String msg = this.webApplicationContext.getMessage(code, args, defaultMessage, this.locale);
String msg = this.webApplicationContext.getMessage(code, args, defaultMessage, getLocale());
return (htmlEscape ? HtmlUtils.htmlEscape(msg) : msg);
}
@@ -728,7 +697,7 @@ public class RequestContext {
* @throws org.springframework.context.NoSuchMessageException if not found
*/
public String getMessage(String code, @Nullable Object[] args, boolean htmlEscape) throws NoSuchMessageException {
String msg = this.webApplicationContext.getMessage(code, args, this.locale);
String msg = this.webApplicationContext.getMessage(code, args, getLocale());
return (htmlEscape ? HtmlUtils.htmlEscape(msg) : msg);
}
@@ -750,7 +719,7 @@ public class RequestContext {
* @throws org.springframework.context.NoSuchMessageException if not found
*/
public String getMessage(MessageSourceResolvable resolvable, boolean htmlEscape) throws NoSuchMessageException {
String msg = this.webApplicationContext.getMessage(resolvable, this.locale);
String msg = this.webApplicationContext.getMessage(resolvable, getLocale());
return (htmlEscape ? HtmlUtils.htmlEscape(msg) : msg);
}
@@ -763,7 +732,7 @@ public class RequestContext {
* @return the message
*/
public String getThemeMessage(String code, String defaultMessage) {
return getTheme().getMessageSource().getMessage(code, null, defaultMessage, this.locale);
return getTheme().getMessageSource().getMessage(code, null, defaultMessage, getLocale());
}
/**
@@ -776,7 +745,7 @@ public class RequestContext {
* @return the message
*/
public String getThemeMessage(String code, @Nullable Object[] args, String defaultMessage) {
return getTheme().getMessageSource().getMessage(code, args, defaultMessage, this.locale);
return getTheme().getMessageSource().getMessage(code, args, defaultMessage, getLocale());
}
/**
@@ -790,7 +759,7 @@ public class RequestContext {
*/
public String getThemeMessage(String code, @Nullable List<?> args, String defaultMessage) {
return getTheme().getMessageSource().getMessage(code, (args != null ? args.toArray() : null),
defaultMessage, this.locale);
defaultMessage, getLocale());
}
/**
@@ -802,7 +771,7 @@ public class RequestContext {
* @throws org.springframework.context.NoSuchMessageException if not found
*/
public String getThemeMessage(String code) throws NoSuchMessageException {
return getTheme().getMessageSource().getMessage(code, null, this.locale);
return getTheme().getMessageSource().getMessage(code, null, getLocale());
}
/**
@@ -815,7 +784,7 @@ public class RequestContext {
* @throws org.springframework.context.NoSuchMessageException if not found
*/
public String getThemeMessage(String code, @Nullable Object[] args) throws NoSuchMessageException {
return getTheme().getMessageSource().getMessage(code, args, this.locale);
return getTheme().getMessageSource().getMessage(code, args, getLocale());
}
/**
@@ -828,7 +797,7 @@ public class RequestContext {
* @throws org.springframework.context.NoSuchMessageException if not found
*/
public String getThemeMessage(String code, @Nullable List<?> args) throws NoSuchMessageException {
return getTheme().getMessageSource().getMessage(code, (args != null ? args.toArray() : null), this.locale);
return getTheme().getMessageSource().getMessage(code, (args != null ? args.toArray() : null), getLocale());
}
/**
@@ -840,7 +809,7 @@ public class RequestContext {
* @throws org.springframework.context.NoSuchMessageException if not found
*/
public String getThemeMessage(MessageSourceResolvable resolvable) throws NoSuchMessageException {
return getTheme().getMessageSource().getMessage(resolvable, this.locale);
return getTheme().getMessageSource().getMessage(resolvable, getLocale());
}
/**

View File

@@ -21,6 +21,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.ThemeResolver;
import org.springframework.web.util.CookieGenerator;
@@ -104,7 +105,11 @@ public class CookieThemeResolver extends CookieGenerator implements ThemeResolve
}
@Override
public void setThemeName(HttpServletRequest request, HttpServletResponse response, @Nullable String themeName) {
public void setThemeName(
HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable String themeName) {
Assert.notNull(response, "HttpServletResponse is required for CookieThemeResolver");
if (StringUtils.hasText(themeName)) {
// Set request attribute and add cookie.
request.setAttribute(THEME_REQUEST_ATTRIBUTE_NAME, themeName);

View File

@@ -42,7 +42,9 @@ public class FixedThemeResolver extends AbstractThemeResolver {
}
@Override
public void setThemeName(HttpServletRequest request, HttpServletResponse response, @Nullable String themeName) {
public void setThemeName(
HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable String themeName) {
throw new UnsupportedOperationException("Cannot change theme - use a different theme resolution strategy");
}

View File

@@ -58,7 +58,9 @@ public class SessionThemeResolver extends AbstractThemeResolver {
}
@Override
public void setThemeName(HttpServletRequest request, HttpServletResponse response, @Nullable String themeName) {
public void setThemeName(
HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable String themeName) {
WebUtils.setSessionAttribute(request, THEME_SESSION_ATTRIBUTE_NAME,
(StringUtils.hasText(themeName) ? themeName : null));
}