Retrieving servlet context, session and request in a POJO outside container
Only and only if your POJO is running in the same thread as the HttpServletRequest
is running in, then you'll be able to achieve this with help of ThreadLocal<T>
.
Create the following class:
public final class YourContext implements AutoCloseable {
private static ThreadLocal<YourContext> instance = new ThreadLocal<>();
private HttpServletRequest request;
private HttpServletResponse response;
private YourContext(HttpServletRequest request, HttpServletResponse response) {
this.request = request;
this.response = response;
}
public static YourContext create(HttpServletRequest request, HttpServletResponse response) {
YourContext context = new YourContext(request, response);
instance.set(context);
return context;
}
public static YourContext getCurrentInstance() {
return instance.get();
}
@Override
public void close() {
instance.remove();
}
public HttpServletRequest getRequest() {
return request;
}
public HttpSession getSession() {
return request.getSession();
}
public ServletContext getServletContext() {
return request.getServletContext();
}
// ... (add if necessary more methods here which return/delegate the request/response).
}
Implement javax.servlet.Filter
which does the following in doFilter()
method and is mapped on an url-pattern
of interest, e.g. /*
or on the servlet-name
of your front controller servlet.
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
try (YourContext context = YourContext.create(request, response)) {
chain.doFilter(request, response);
}
}
Note the importance of try-with-resources statement. It guarantees that the YourContext#close()
will be called after the filter has done its job and the ThreadLocal
resource will be cleared. Otherwise the thread will still contain it when recycled for another HTTP request.
And here's how you could use it in the POJO:
YourContext context = YourContext.getCurrentInstance();
HttpSession session = context.getSession();
This all is basically also how the Context
objects of the average MVC framework works, like JSF's FacesContext
and the one in Wicket.
Said that, have you looked at CDI? Perhaps it's easier to make the artifacts CDI-managed so you can just @Inject
them in each other.
Yes, there is.
If you're using a web framework, for example Wicket, there is often a way to get the current HttpSession. From there, you can get the Spring ApplicationContext and if you have that, you can get Spring Beans from it. This works in any location, as we're using static utility methods only.
Example code:
import org.apache.wicket.protocol.http.WebApplication;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.context.WebApplicationContext;
ServletContext sc = WebApplication.getServletContext();
WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(sc);
Object bean = wac.getBean("myBeanId");
Note however that the Spring Filter and the Wicket Filter must be in place and handle the current request, otherwise the utility methods won't work.
If you didn't mean Spring Beans, than you would have to store them in the HTTP Session yourself. If you do not have a web framework, you may want to do what rfeak is suggesting and implement your own ThreadLocal.
A Pojo is a Plain Old Java Object. POJOS have nothing to do with sessions.
The https session is available on the request object.
Check out this
http://download.oracle.com/docs/cd/E17802_01/webservices/webservices/docs/1.6/api/index.html
specifically the HttpServletRequest interface, and the getSession() method.
For the 'bean' part of your question. A bean is a java class that conforms to 3 standards.
- No arg constructor
- setters and getters to access private fields
- Implements serializable.
A POJO is a bean if it follows those conventions.