3

In PHP one is always able to access the current request or response from any part of their code. This concept is fundamental to PHP programming. Request data, response data, session data (etc) are always there!

This does not happen in Java Servlets! In order to have access to the HttpServletRequest, HttpServletResponse, HttpSession (etc) in your code you need to pass them around as function variables. This means that you cannot code a web framework that inherently "knows" about all these and removes the complexity of passing them around.

So, I have devised this solution:

  1. Create anf register a ServletRequestListener.
  2. Upon the requestInitialized event bind the current HttpServletRequest to the JNI context giving in the name of the current Thread (Thread.currentThread().getName());
  3. Upon the requestDestroyed event unbind the above JNI resource to cleanup.

This way one has access to the current request/response from any place of their code, since they are always there in the JNI context and can be retrieved by providing the current thread's name.

All known servlet container implement the single-thread model for each request, so there is no way for the requests to get mixed up (of course one must not forget to clean them up).

Also the JNI resources of each web application are separated by default so there are no concerns of mixing them up or of security issues that could arise from one web application having access to the requests of the others.

Kinda twisted, but nice and simple...

What do you think?

Takis Bouyouris
  • 121
  • 1
  • 7
  • Have you considered looking at an existing MVC framework instead of reinventing your own? – BalusC Aug 25 '11 at 13:42
  • Of course! But, of course, there is always room for one trying to accomplish something new and different. And you can always find reasons for this. Anyway, right here I am just discussing this particular solution, not trying to figure out whether other frameworks are better or not. – Takis Bouyouris Aug 25 '11 at 13:52
  • In the question title and tags you are talking about JNDI, in the question body about JNI. These are not the same concepts. Which one do you actually mean? – Paŭlo Ebermann Aug 27 '11 at 19:22

2 Answers2

3

I think some web frameworks (GWT, Axis) already do that, but in a much simpler way: by using a ThreadLocal static variable (or accessible from a singleton). Spring also has this possibility.

I'm not sure it works with all the containers, though. If the container uses non-blocking IO and reuses the same thread to handle multiple requests in parallel, it won't work anymore.

See Get the HttpServletRequest (request) object from Java code for a similar question (and its answers).

Community
  • 1
  • 1
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • Spring uses ThreadLocal storage for request and session scoped beans. Log4J also uses ThreadLocal storage for nested diagnostic context. Just a couple of more examples of usage of the ThreadLocal pattern in the context of java servlet applications. I'm curious if you have any hard example of containers that deviate from the "one thread, one request" paradigm (as it would break any number of frameworks out there). – pap Aug 25 '11 at 12:53
  • See http://docs.jboss.org/resteasy/docs/1.0.0.GA/userguide/html/Asynchronous_HTTP_Request_Processing.html. Asynchronous processing is standardized in Servlet 3.0. – JB Nizet Aug 25 '11 at 13:09
  • JSF also does that. See [`FacesContext`](http://download.oracle.com/javaee/6/api/javax/faces/context/FacesContext.html) and other similar question http://stackoverflow.com/questions/5753913/how-to-initialize-an-api-in-servlet-environment – BalusC Aug 25 '11 at 13:41
  • Yes, this solution depends on the container! Still, if the single-threaded request model is preserved then it should work fine. And usually it is! (I only know of Google's Node.JS as an example of a server that implements some other kind of request model - in case of Node.JS an event oriented one.) Also, such a process might prove to be useful for small frameworks, when one does not want to use solutions like Spring, or Seam or JSF, etc! Are there any speed related issues concerning this approach that you can see? – Takis Bouyouris Aug 25 '11 at 13:43
  • No speed issue. As I said, several frameworks already do this. Note though that more and more containers (and developers) will recycle threads, because asynchronous request processing is now standardized. – JB Nizet Aug 25 '11 at 13:53
  • I see your point, but even in the case of thread re-usage can we not be sure that at each given moment a single thread will be devoted to a single request/response? I mean all servers that implement the single-thread request/response model do re-use open up a number of threads when they start up and then use them and re-use them many times! – Takis Bouyouris Aug 25 '11 at 13:58
  • Yes, of course, but you would have to change the value of the request in the ThreadLocal variable each time the thread switches from one request to another one. This is easily done using a servlet filter in the "traditional" case, but I don't know if there is any hook for plugging custom code when request switching is done by the container. – JB Nizet Aug 25 '11 at 14:04
  • NIO is not a concern. It's managed at lower level. Each request has really its own `Thread` (otherwise your proposed JNDI approach and many other things would also fail). Your concern should be ensuring that the `ThreadLocal` is **always** released by end of request. E.g. in `finally` of `FilterChain#doFilter()` call. See also the similar question which I linked in previous comment. – BalusC Aug 25 '11 at 14:05
  • You can always get the events of a request initialization and request finalization and do the proper to setup and cleanup in this approach, right? – Takis Bouyouris Aug 25 '11 at 14:08
0

If you are worried about different requests getting messed up (and then think about "sub requests" like a model window), perhaps you'd rather think about using Seam? They use an abstraction called a "Session" to handle a LOT of the things that we developers try to hack around with other traditional web technology stacks. Seam is built on JSF just as an fyi. You don't have to use EJB 3 or Hibernate with it, but it does integrate nicely with both of those as well. Something to think about.

Chris Aldrich
  • 1,904
  • 1
  • 22
  • 37
  • Seam is nice, and so are any other frameworks. I was just wondering for such an approach in the case when one chooses not to use one of them. – Takis Bouyouris Aug 25 '11 at 14:00