Reputation: 6450
I am using a RequestContextHolder in a filter to record a piece of data, and want to access it in a POJO (wired up via Spring) later. I'm getting an exception which suggests I'm doing something wrong here, would appreciate any guidance on what that is.
Filter code (in a doFilter() method, whose logging confirms it's being called):
RequestAttributes attrs = RequestContextHolder.getRequestAttributes();
if (attrs == null)
{
logger.info("Creating new ServletRequestAttributes");
attrs = new ServletRequestAttributes(servletRequest);
}
attrs.setAttribute("my_attr", "hello there!", RequestAttributes.SCOPE_REQUEST);
RequestContextHolder.setRequestAttributes(attrs);
POJO code:
RequestAttributes attrs = RequestContextHolder.getRequestAttributes();
if (attrs != null && attrs.getAttribute("my_attr", RequestAttributes.SCOPE_REQUEST) != null)
{
String myAttr = (String) attrs.getAttribute("my_attr", RequestAttributes.SCOPE_REQUEST);
logger.debug("Got it: ", myAttr);
}
I am seeing this exception coming from Tomcat though:
java.lang.IllegalStateException: The request object has been recycled and is no longer associated with this facade
at org.apache.catalina.connector.RequestFacade.getAttribute(RequestFacade.java:259)
at org.springframework.web.context.request.ServletRequestAttributes.getAttribute(ServletRequestAttributes.java:98)
at com.mycompany.MyClass(MyClass.java:50)
I do wonder if having the "set data" in a filter, and "get data" via the real work of the request could be in play here, but not sure how best to accommodate that, if it even is relevant?
Upvotes: 2
Views: 8894
Reputation: 5694
The error is likely caused by the fact that you're making Spring maintain a thread-local handle to a request object that is no longer valid. The details probably don't matter all that much since a different approach is in order.
One of the following will take care of automatically setting and clearing thread-local state properly: DispatcherServlet
, RequestContextListener
or RequestContextFilter
. You need to figure out which one makes the most sense for how Spring is used with your app. Your filter and POJO code shouldn't need to make use of classes like RequestContextHolder
directly. What should happen is that you declare a proxied, request-scoped bean for the attribute you want to access:
<bean id="myAttr" scope="request">
<aop:scoped-proxy/>
</bean>
Then, declare the bean for your POJO along with its dependency on the request-scoped bean:
<bean id="myPojo">
<property name="myAttr" ref="myAttr"/>
</bean>
See: Request, session, and global session scopes
Spring should take care of all the details...
Upvotes: 1