/*
 * Copyright 2002-2016 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
 *
 *      https://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.context.request;

import javax.faces.context.FacesContext;

import org.springframework.core.NamedInheritableThreadLocal;
import org.springframework.core.NamedThreadLocal;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;

Holder class to expose the web request in the form of a thread-bound RequestAttributes object. The request will be inherited by any child threads spawned by the current thread if the inheritable flag is set to true.

Use RequestContextListener or RequestContextFilter to expose the current web request. Note that DispatcherServlet already exposes the current request by default.

Author:Juergen Hoeller, Rod Johnson
See Also:
Since:2.0
/** * Holder class to expose the web request in the form of a thread-bound * {@link RequestAttributes} object. The request will be inherited * by any child threads spawned by the current thread if the * {@code inheritable} flag is set to {@code true}. * * <p>Use {@link RequestContextListener} or * {@link org.springframework.web.filter.RequestContextFilter} to expose * the current web request. Note that * {@link org.springframework.web.servlet.DispatcherServlet} * already exposes the current request by default. * * @author Juergen Hoeller * @author Rod Johnson * @since 2.0 * @see RequestContextListener * @see org.springframework.web.filter.RequestContextFilter * @see org.springframework.web.servlet.DispatcherServlet */
public abstract class RequestContextHolder { private static final boolean jsfPresent = ClassUtils.isPresent("javax.faces.context.FacesContext", RequestContextHolder.class.getClassLoader()); private static final ThreadLocal<RequestAttributes> requestAttributesHolder = new NamedThreadLocal<>("Request attributes"); private static final ThreadLocal<RequestAttributes> inheritableRequestAttributesHolder = new NamedInheritableThreadLocal<>("Request context");
Reset the RequestAttributes for the current thread.
/** * Reset the RequestAttributes for the current thread. */
public static void resetRequestAttributes() { requestAttributesHolder.remove(); inheritableRequestAttributesHolder.remove(); }
Bind the given RequestAttributes to the current thread, not exposing it as inheritable for child threads.
Params:
  • attributes – the RequestAttributes to expose
See Also:
/** * Bind the given RequestAttributes to the current thread, * <i>not</i> exposing it as inheritable for child threads. * @param attributes the RequestAttributes to expose * @see #setRequestAttributes(RequestAttributes, boolean) */
public static void setRequestAttributes(@Nullable RequestAttributes attributes) { setRequestAttributes(attributes, false); }
Bind the given RequestAttributes to the current thread.
Params:
  • attributes – the RequestAttributes to expose, or null to reset the thread-bound context
  • inheritable – whether to expose the RequestAttributes as inheritable for child threads (using an InheritableThreadLocal)
/** * Bind the given RequestAttributes to the current thread. * @param attributes the RequestAttributes to expose, * or {@code null} to reset the thread-bound context * @param inheritable whether to expose the RequestAttributes as inheritable * for child threads (using an {@link InheritableThreadLocal}) */
public static void setRequestAttributes(@Nullable RequestAttributes attributes, boolean inheritable) { if (attributes == null) { resetRequestAttributes(); } else { if (inheritable) { inheritableRequestAttributesHolder.set(attributes); requestAttributesHolder.remove(); } else { requestAttributesHolder.set(attributes); inheritableRequestAttributesHolder.remove(); } } }
Return the RequestAttributes currently bound to the thread.
Returns:the RequestAttributes currently bound to the thread, or null if none bound
/** * Return the RequestAttributes currently bound to the thread. * @return the RequestAttributes currently bound to the thread, * or {@code null} if none bound */
@Nullable public static RequestAttributes getRequestAttributes() { RequestAttributes attributes = requestAttributesHolder.get(); if (attributes == null) { attributes = inheritableRequestAttributesHolder.get(); } return attributes; }
Return the RequestAttributes currently bound to the thread.

Exposes the previously bound RequestAttributes instance, if any. Falls back to the current JSF FacesContext, if any.

Throws:
See Also:
Returns:the RequestAttributes currently bound to the thread
/** * Return the RequestAttributes currently bound to the thread. * <p>Exposes the previously bound RequestAttributes instance, if any. * Falls back to the current JSF FacesContext, if any. * @return the RequestAttributes currently bound to the thread * @throws IllegalStateException if no RequestAttributes object * is bound to the current thread * @see #setRequestAttributes * @see ServletRequestAttributes * @see FacesRequestAttributes * @see javax.faces.context.FacesContext#getCurrentInstance() */
public static RequestAttributes currentRequestAttributes() throws IllegalStateException { RequestAttributes attributes = getRequestAttributes(); if (attributes == null) { if (jsfPresent) { attributes = FacesRequestAttributesFactory.getFacesRequestAttributes(); } if (attributes == null) { throw new IllegalStateException("No thread-bound request found: " + "Are you referring to request attributes outside of an actual web request, " + "or processing a request outside of the originally receiving thread? " + "If you are actually operating within a web request and still receive this message, " + "your code is probably running outside of DispatcherServlet: " + "In this case, use RequestContextListener or RequestContextFilter to expose the current request."); } } return attributes; }
Inner class to avoid hard-coded JSF dependency.
/** * Inner class to avoid hard-coded JSF dependency. */
private static class FacesRequestAttributesFactory { @Nullable public static RequestAttributes getFacesRequestAttributes() { FacesContext facesContext = FacesContext.getCurrentInstance(); return (facesContext != null ? new FacesRequestAttributes(facesContext) : null); } } }