Retrieving Servlet Context, Session and Request in a Pojo Outside Container

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.

General session handling in java

I had flagged to delete this question as I found the answer in another SO link Retrieving Web Session from a POJO Outside the Web Container . Since it has not been deleted till now , I am answering my own question.

What are servlet and why we use them ?

A Java servlet is a Java program that extends the capabilities of a server.
Although servlets can respond to any types of requests, they most commonly implement applications hosted on Web servers.
Such Web servlets are the Java counterpart to other dynamic Web content technologies such as PHP and ASP.NET.

More information about java servlet at the link https://en.wikipedia.org/wiki/Java_servlet

Servlet vs POJO/normal Java classes ( why session access only in servlet ?)

A servlet class too is a java class. Servlet is a java class which comply servlet specification, so that it can be run in a server. Java class not required to comply Java Servlet API

A servlet container (e.g. Tomcat) is designed to be able to recognise servlet classes and, if configured correctly, treat them in a particular way. There's nothing magical about this - you can always write your own application that can treat any type of class in a specific way - but there's a standard that all servlet containers follow that means you can write a servlet class and know how it will be used.

Java was designed to be a platform independent language to create software to be embedded in various consumer
electronic devices. Soon it was apparent that the Java can be used in client/server programming environment because of its inherent portability. Hence servlet and applet were introduced in java. Java applets helped create dynamic, self-executing program on client side. Java servlet is a small program that executes on the server. Just as applets dynamically extend the functionality of a web browser, servlets dynamically extend the functionality of a web server.

Since servlet part of java is used in server side programming , this has access to session. POJO classes are also used in server side programming but code which uses session is usually written in servlet.

POJO Vs PHP classes(server side)

Java is used in many development environments like desktop,mobile,embedded and Web. PHP is a server-side scripting language designed for web development.It can also be used for general purpose programming but I am limiting the discussion to class used in php in server side programming(ie .php pages). So it is better to compare php classes in php pages with servlet/JSP - server side development part of JAVA.

Again servlet puts html code inside Java code. JSP puts java code inside html code. So JSP in java is more comparable to PHP .
If we understand this then we can infer that there is no good reason to compare POJO in java to PHP classes (server side). It is like comparing applies to oranges. if you are interested in comparison between php and jsp please visit http://www.withoutbook.com/DifferenceBetweenSubjects.php?subId1=57&subId2=2&d=Difference%20between%20PHP%20and%20JSP

In modern web development we use template engines ie instead of JSP we use servlet with template engine(Freemarker,Velocity). PHP has its own template engines.

How to access session in POJO classes ? Why it is hard / Is there any easy way ?

First of all it should not be done as it would be a bad programming practice. Secondly it can be done but there is hardly any scenario where this would be necessary. Since there is no need for the same the ways to implement it are not easy.

It should not be done , If you have to there are two ways.

  1. We can pass session and request objects from servlet to POJO classes(via methods or constructors).
  2. Store the request in a ThreadLocal in a Filter (and clean it afterwards)

Also look at the SO links for sample code

get HttpSession|Request from simple java class not servlet class

Retrieving Web Session from a POJO Outside the Web Container

I asked this question when I was stuck at a particular scenario . I used to program in PHP and wondered why I never had the issue there and got confused. People who usually move from php to java , also have a hard time understanding the how it all works , so attaching one more part to the answer.

Why servlets require servlet containers like tomcat while php runs on a http server/webserver (Apache).?

The question is incorrect in assumptions made but the answer will highlight why .

A web server is software that helps to deliver web content (web pages) to the clients (e.g. web browser)
through the Internet using HTTP protocol. HTTP is a simple request /response protocol underpinning most web
applications on the Internet, regardless of whether they are written in Java. An HTTP request can correspond to
one of the seven HTTP methods: GET, POST, HEAD, OPTIONS, TRACE, PUT and DELETE

The server side technologies like JSP/Servlets, ASP, and PHP etc. will require their software libraries to be installed
at the server. Without these libraries a web server won’t be able to execute those server technologies and is just an HTTP Server.
An HTTP server can handle HTML and other client side technologies which don’t require any server capability.
The Apache HTTP Server is an example of an HTTP server.

Regarding Servet/JSP : Servlet can be run on a servlet container.Tomcat is normally called a servlet container.A Servlet container is basically a web server for Java Servlets and JSP pages. Tomcat has an HTTP listener inside it, but in addition to that it has a servlet/JSP engine. A servlet, in the end, is a Java class. JSP files (which are similar to PHP, and older ASP files) are generated into Java code (Servlet), which is then compiled to .class files by the server and executed by the Java virtual machine.

Regarding PHP : PHP will not work in pure Apache or any HTTP server. We are able to run php in apache because it is linked to Apache(SAPI - server API) Using mod_php5.so(or similar) modules. We do not normally start any php daemon. Apache starts the php interpreter along with itself.

If oracle wants, it can develop a module similar to PHP module which will make it easier to host Java code on an HTTP server. But using a servlet container model has many benefits compared to the PHP interpreter model even with the disadvantage of increase in complexity.

Servlet and JSF page within same context shows different sessions

As to how sessions work, carefully read this: How do servlets work? Instantiation, sessions, shared variables and multithreading.

In fact, the external application should have sent the very same session cookie as the JSF application is using. An alternative would have been to provide a callback URL including the jsessionid path fragment, which is composed as follows:

String url = "http://example.com/context/servlet;jsessionid=" + session.getId();

Again another alternative would be to generate an unique ID (with java.util.UUID) referencing an entry in application scope or even the DB and set it as request parameter in the callback URL. You should only manually cleanup it when the session is destroyed. You can use a HTTP session listener for that.

Sharing a static object between a servlet and a webservice

You can share things across the webapp by storing them as attributes in the ServletContext (using setAttribute / getAttribute). You could create the object in an impelementation of ServletContextListener, store it in the ServletContext, and then retrieve it and use it from your web service and servlet.

Is there a generic RequestContext in Java servlet API?

There isn't in the servlet API, but you can make your own pretty easily. (Some frameworks like spring-mvc, struts provide such functionality)

Just use a public static ThreadLocal to store and retrieve the object. You can even store the HttpServletRequest itself in the threadlocal and use its setAttribute()/getAttribute() methods, or you can store a threadlocal Map, to be agnostic of the servlet API. An important note is that you should clean the threadlocal after the request (with a Filter, for example).

Also note that passing the object as parameter is considered a better practice, because you usually pass it from the web layer to a service layer, which should not be dependent on web-related object, like a HttpContext.

If you decide that it is fine to store them in a thread-local, rather than passing them around:

public class RequestContext {
private static ThreadLocal<Map<Object, Object>> attributes = new ThreadLocal<>();
public static void initialize() {
attributes.set(new HashMap<Map<Object, Object>>());
}
public static void cleanup() {
attributes.set(null);
}
public static <T> T getAttribute(Object key) {
return (T) attributes.get().get(key);
}
public static void setAttribute(Object key, Object value) {
attributes.get().put(key, value);
}
}

And a necessary filter:

@WebFilter(urlPatterns="/")
public class RequestContextFilter implements Filter {
public void doFilter(..) {
RequestContext.initialize();
try {
chain.doFilter(request, response);
} finally {
RequestContext.cleanup();
}
}
}

Is ThreadLocal preferable to HttpServletRequest.setAttribute(key, value)?

Is ThreadLocal preferable to HttpServletRequest.setAttribute(“key”, “value”)?

Depends on the concrete functional requirement.

JSF, for example, stores the FacesContext in a ThreadLocal. This enables you to access all of the JSF artifacts, including the "raw" HttpServletRequest and HttpServletResponse anywhere in the code which is executed by the FacesServlet, such as managed beans. Most other Java based MVC frameworks follow the same example.

As per your comment,

I primarily need to transport the User and EntityManager objects from the user and database Filters to the Servlet. I also find that these are frequently and unexpectedly needed in code further down the line and I am tempted to use them well beyond the Servlet (i. e. in nested code called by doGet). I feel there may be a better way for deeper code - suggestions?

As to the User example for which I assume that this is a session attribute, I'd rather follow the same approach as JSF. Create a ThreadLocal<Context> where the Context is your custom wrapper class holding references to the current HttpServletRequest and maybe also HttpServletResponse so that you can access them anywhere down in your code. If necessary provide convenience methods to get among others the User directly from the Context class.

As to the EntityManager example, you could follow the same approach, but I'd personally not put it in the same ThreadLocal<Context>, but rather a different one. Or, better, just obtain it from JNDI in the service layer, which would allow you more finer grained control over transactions. In any case, please make absolutely sure that you handle the commit/close properly. Taking over the persistence and transaction management from the container should be done with extreme care. I'd really reconsider the aversion against using the existing and well-designed APIs/frameworks like EJB/JPA, otherwise you'll risk a complete waste of time of reinventing all the already-standardized APIs and stuffs.

See also:

  • Retrieving Web Session from a POJO Outside the Web Container
  • Design Patterns web based applications


Related Topics



Leave a reply



Submit