I used to have an Open Session In Conversation Filter based on cookies for a JSF 2 app. Now I want to build the same mechanism but technology-agnostic. Reusing some code, I have written this in a class that extends OncePerRequestFilter:
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
UUID conversationId = lookupConversationOrCreateIfNecessary(request,
response);
log.debug("Binding conversation '{}' to request '{}'", conversationId,
request);
bindConversation(conversationId, request);
try {
filterChain.doFilter(request, response);
} finally {
log.debug("Unbinding conversation '{}' from request '{}'",
conversationId, request);
unbindConversation(conversationId, request);
}
}
Now, when I reach bindConversation(conversationId, request) I just add a request attribute which points to the conversationId which is mapped to a Hibernate Session.
Anyways, in JSF I can access the current request by using FacesContext.getCurrentInstance().getExternalContext().getRequest() and implemented a CurrentSessionContext using this. But in plain servlets how can I access the current request programmatically?
Note: I have been reading the OncePerRequestFilter javadocs and I found this:
As of Servlet 3.0, a filter may be invoked as part of a REQUEST or
ASYNC dispatches that occur in separate threads. A filter can be
configured in web.xml whether it should be involved in async
dispatches. However, in some cases servlet containers assume different
default configuration. Therefore sub-classes can override the method
shouldNotFilterAsyncDispatch() to declare statically if they [sic] shouuld
indeed be invoked, once, during both types of dispatches in order to
provide thread initialization, logging, security, and so on. This
mechanism complements and does not replace the need to configure a
filter in web.xml with dispatcher types.
So, would it be dangerous to use a ThreadLocal to achieve what I want?
As you mention in your question: using a ThreadLocal seems a good option. I don’t see why it would be unsafe as soon as you use your filter for both REQUEST and ASYNC.
EDIT
And the ConversationHolder
Since conversationId is a local variable it won’t be shared between request.
Since ConversationHolder is a ThreadLocal, the value you get from it during doFilter(…) will be correct. (except if you create new Thread by hand during your request processing, but it is not a recommended design)