diff --git a/spring-web/src/main/java/org/springframework/web/context/support/WebApplicationObjectSupport.java b/spring-web/src/main/java/org/springframework/web/context/support/WebApplicationObjectSupport.java index 1764b6ced9..209a87ddf0 100644 --- a/spring-web/src/main/java/org/springframework/web/context/support/WebApplicationObjectSupport.java +++ b/spring-web/src/main/java/org/springframework/web/context/support/WebApplicationObjectSupport.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. @@ -125,7 +125,11 @@ public abstract class WebApplicationObjectSupport extends ApplicationObjectSuppo if (this.servletContext != null) { return this.servletContext; } - ServletContext servletContext = getWebApplicationContext().getServletContext(); + WebApplicationContext wac = getWebApplicationContext(); + if (wac == null) { + return null; + } + ServletContext servletContext = wac.getServletContext(); if (servletContext == null && isContextRequired()) { throw new IllegalStateException("WebApplicationObjectSupport instance [" + this + "] does not run within a ServletContext. Make sure the object is fully configured!"); diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/DispatcherServlet.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/DispatcherServlet.java index 6650dec708..706b3ab6a2 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/DispatcherServlet.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/DispatcherServlet.java @@ -206,7 +206,7 @@ public class DispatcherServlet extends FrameworkServlet { /** * Request attribute to hold the current web application context. * Otherwise only the global web app context is obtainable by tags etc. - * @see org.springframework.web.servlet.support.RequestContextUtils#getWebApplicationContext + * @see org.springframework.web.servlet.support.RequestContextUtils#findWebApplicationContext */ public static final String WEB_APPLICATION_CONTEXT_ATTRIBUTE = DispatcherServlet.class.getName() + ".CONTEXT"; diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/ViewRendererServlet.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/ViewRendererServlet.java index e7574d239e..f634ac805d 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/ViewRendererServlet.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/ViewRendererServlet.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 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. @@ -48,7 +48,7 @@ public class ViewRendererServlet extends HttpServlet { /** * Request attribute to hold current web application context. * Otherwise only the global web app context is obtainable by tags etc. - * @see org.springframework.web.servlet.support.RequestContextUtils#getWebApplicationContext + * @see org.springframework.web.servlet.support.RequestContextUtils#findWebApplicationContext */ public static final String WEB_APPLICATION_CONTEXT_ATTRIBUTE = DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE; diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/support/RequestContext.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/support/RequestContext.java index 71309b5170..9fae867961 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/support/RequestContext.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/support/RequestContext.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. @@ -89,12 +89,6 @@ public class RequestContext { */ public static final String WEB_APPLICATION_CONTEXT_ATTRIBUTE = RequestContext.class.getName() + ".CONTEXT"; - /** - * The name of the bean to use to look up in an implementation of - * {@link RequestDataValueProcessor} has been configured. - */ - private static final String REQUEST_DATA_VALUE_PROCESSOR_BEAN_NAME = "requestDataValueProcessor"; - protected static final boolean jstlPresent = ClassUtils.isPresent("javax.servlet.jsp.jstl.core.Config", RequestContext.class.getClassLoader()); @@ -236,7 +230,11 @@ public class RequestContext { // 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.getWebApplicationContext(request, servletContext); + this.webApplicationContext = RequestContextUtils.findWebApplicationContext(request, servletContext); + if (this.webApplicationContext == null) { + throw new IllegalStateException("No WebApplicationContext found: not in a DispatcherServlet " + + "request and no ContextLoaderListener registered?"); + } } // Determine locale to use for this RequestContext. @@ -271,9 +269,9 @@ public class RequestContext { this.urlPathHelper = new UrlPathHelper(); - if (this.webApplicationContext.containsBean(REQUEST_DATA_VALUE_PROCESSOR_BEAN_NAME)) { + if (this.webApplicationContext.containsBean(RequestContextUtils.REQUEST_DATA_VALUE_PROCESSOR_BEAN_NAME)) { this.requestDataValueProcessor = this.webApplicationContext.getBean( - REQUEST_DATA_VALUE_PROCESSOR_BEAN_NAME, RequestDataValueProcessor.class); + RequestContextUtils.REQUEST_DATA_VALUE_PROCESSOR_BEAN_NAME, RequestDataValueProcessor.class); } } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/support/RequestContextUtils.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/support/RequestContextUtils.java index e9c25b93eb..ac6e0769c2 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/support/RequestContextUtils.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/support/RequestContextUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 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. @@ -27,6 +27,7 @@ import org.springframework.context.i18n.LocaleContext; import org.springframework.context.i18n.TimeZoneAwareLocaleContext; import org.springframework.ui.context.Theme; import org.springframework.ui.context.ThemeSource; +import org.springframework.web.context.ContextLoader; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; import org.springframework.web.servlet.DispatcherServlet; @@ -51,16 +52,26 @@ import org.springframework.web.servlet.ThemeResolver; */ public abstract class RequestContextUtils { + /** + * The name of the bean to use to look up in an implementation of + * {@link RequestDataValueProcessor} has been configured. + * @since 4.2.1 + */ + public static final String REQUEST_DATA_VALUE_PROCESSOR_BEAN_NAME = "requestDataValueProcessor"; + + /** * Look for the WebApplicationContext associated with the DispatcherServlet * that has initiated request processing. * @param request current HTTP request * @return the request-specific web application context * @throws IllegalStateException if no servlet-specific context has been found + * @see #getWebApplicationContext(ServletRequest, ServletContext) + * @deprecated as of Spring 4.2.1, in favor of + * {@link #findWebApplicationContext(HttpServletRequest)} */ - public static WebApplicationContext getWebApplicationContext(ServletRequest request) - throws IllegalStateException { - + @Deprecated + public static WebApplicationContext getWebApplicationContext(ServletRequest request) throws IllegalStateException { return getWebApplicationContext(request, null); } @@ -76,7 +87,12 @@ public abstract class RequestContextUtils { * if no request-specific context has been found * @throws IllegalStateException if neither a servlet-specific nor a * global context has been found + * @see DispatcherServlet#WEB_APPLICATION_CONTEXT_ATTRIBUTE + * @see WebApplicationContextUtils#getRequiredWebApplicationContext(ServletContext) + * @deprecated as of Spring 4.2.1, in favor of + * {@link #findWebApplicationContext(HttpServletRequest, ServletContext)} */ + @Deprecated public static WebApplicationContext getWebApplicationContext( ServletRequest request, ServletContext servletContext) throws IllegalStateException { @@ -91,6 +107,57 @@ public abstract class RequestContextUtils { return webApplicationContext; } + /** + * Look for the WebApplicationContext associated with the DispatcherServlet + * that has initiated request processing, and for the global context if none + * was found associated with the current request. The global context will + * be found via the ServletContext or via ContextLoader's current context. + *

NOTE: This variant remains compatible with Servlet 2.5, explicitly + * checking a given ServletContext instead of deriving it from the request. + * @param request current HTTP request + * @param servletContext current servlet context + * @return the request-specific WebApplicationContext, or the global one + * if no request-specific context has been found, or {@code null} if none + * @since 4.2.1 + * @see DispatcherServlet#WEB_APPLICATION_CONTEXT_ATTRIBUTE + * @see WebApplicationContextUtils#getWebApplicationContext(ServletContext) + * @see ContextLoader#getCurrentWebApplicationContext() + */ + public static WebApplicationContext findWebApplicationContext( + HttpServletRequest request, ServletContext servletContext) { + + WebApplicationContext webApplicationContext = (WebApplicationContext) request.getAttribute( + DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE); + if (webApplicationContext == null) { + if (servletContext != null) { + webApplicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext); + } + if (webApplicationContext == null) { + webApplicationContext = ContextLoader.getCurrentWebApplicationContext(); + } + } + return webApplicationContext; + } + + /** + * Look for the WebApplicationContext associated with the DispatcherServlet + * that has initiated request processing, and for the global context if none + * was found associated with the current request. The global context will + * be found via the ServletContext or via ContextLoader's current context. + *

NOTE: This variant requires Servlet 3.0+ and is generally recommended + * for forward-looking custom user code. + * @param request current HTTP request + * @return the request-specific WebApplicationContext, or the global one + * if no request-specific context has been found, or {@code null} if none + * @since 4.2.1 + * @see #findWebApplicationContext(HttpServletRequest, ServletContext) + * @see ServletRequest#getServletContext() + * @see ContextLoader#getCurrentWebApplicationContext() + */ + public static WebApplicationContext findWebApplicationContext(HttpServletRequest request) { + return findWebApplicationContext(request, request.getServletContext()); + } + /** * Return the LocaleResolver that has been bound to the request by the * DispatcherServlet. diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/RedirectView.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/RedirectView.java index acccf0b296..0a188696a1 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/RedirectView.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/RedirectView.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. @@ -36,14 +36,12 @@ import org.springframework.http.HttpStatus; import org.springframework.util.CollectionUtils; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; -import org.springframework.web.context.ContextLoader; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.servlet.FlashMap; import org.springframework.web.servlet.FlashMapManager; import org.springframework.web.servlet.HandlerMapping; import org.springframework.web.servlet.SmartView; import org.springframework.web.servlet.View; -import org.springframework.web.servlet.support.RequestContext; import org.springframework.web.servlet.support.RequestContextUtils; import org.springframework.web.servlet.support.RequestDataValueProcessor; import org.springframework.web.util.UriComponents; @@ -299,7 +297,7 @@ public class RedirectView extends AbstractUrlBasedView implements SmartView { } /** - * Creates the target URL by checking if the redirect string is a URI template first, + * Create the target URL by checking if the redirect string is a URI template first, * expanding it with the given model, and then optionally appending simple type model * attributes as query String parameters. */ @@ -554,27 +552,23 @@ public class RedirectView extends AbstractUrlBasedView implements SmartView { /** * Find the registered {@link RequestDataValueProcessor}, if any, and allow * it to update the redirect target URL. + * @param targetUrl the given redirect URL * @return the updated URL or the same as URL as the one passed in */ protected String updateTargetUrl(String targetUrl, Map model, HttpServletRequest request, HttpServletResponse response) { - RequestContext requestContext = null; - if (getWebApplicationContext() != null) { - requestContext = createRequestContext(request, response, model); + WebApplicationContext wac = getWebApplicationContext(); + if (wac == null) { + wac = RequestContextUtils.findWebApplicationContext(request, getServletContext()); } - else { - WebApplicationContext wac = ContextLoader.getCurrentWebApplicationContext(); - if (wac != null && wac.getServletContext() != null) { - requestContext = new RequestContext(request, response, wac.getServletContext(), model); - } - } - if (requestContext != null) { - RequestDataValueProcessor processor = requestContext.getRequestDataValueProcessor(); - if (processor != null) { - targetUrl = processor.processUrl(request, targetUrl); - } + + if (wac != null && wac.containsBean(RequestContextUtils.REQUEST_DATA_VALUE_PROCESSOR_BEAN_NAME)) { + RequestDataValueProcessor processor = wac.getBean( + RequestContextUtils.REQUEST_DATA_VALUE_PROCESSOR_BEAN_NAME, RequestDataValueProcessor.class); + return processor.processUrl(request, targetUrl); } + return targetUrl; }