For a pilot project I want to implement a custom and distributed user session. It seems the perfect spot for a ThreadLocal binding, carefully managed by a request filter.
Such user session is going to be available both in Servlet and non-Servlet environments. In Servlet environments, it should be independent of the presence or absence of any underlying javax.servlet.http.HttpSession (that is, it won't be allowed to create or use HttpSession objects).
Unfortunately I'm not able to find exhaustive information about how to handle this scenario in a Servlet 3.0 + environment configured for asynchronous operations. I understand (at least, I think...) that a javax.servlet.Filter should add a javax.servlet.AsyncListener to the current javax.servlet.AsyncContext, but some dedicated resources / real examples would be extremely helpful (mostly for showing some nuances I would certainly miss).
I am well aware of the ThreadLocal pitfalls, but their actual benefits (in such context) make me willing to find the proper way to implement them in such an asynchronous architecture (plus, passing a session reference to inner layers is not an option).
Related
I'm running a JBoss AS 7.1.3.Final installation with a lot of applications. One of those applications provides common resources and functionallities used by all applications (let's call it framework). I'm also planning to move to WildFly 8, if this is an useful information for your answer.
All applications should only be accessible, if the framework is available (up and running). My current implementation to achive this dependency is not that nice** and as I'm currently re-designing some parts of the environment, I'm looking for a much neater solution for it. My first idea was to create some kind of a manager which will be instantiated by the application server and is available to all applications. So after an application is started, it could register itself on the manager and as soon as the framework is up, the applications will be notified.
Is this possible using the JNDI of the JVM where all applications + framework are running? How must this be implemented? It's really hard to find useful information about how the JNDI works and what is possible with it. Do you have any other, simplier ideas, how to share a class instance between applications?
Thank you.
** Currently I'm using a EJB-timer in the applications and a singleton EJB in the framework. The framework is available as soon as the EJB lookup succeeds.
--
Edit #1
Some more informations as requested by Nikos Paraskevopoulos
One functionionality that is provided by the framework is the maintenance mode. The applications will check, right after startup, if it is blocked for normal users. It will also receive notifications about planned maintenances. (central DB, the application has no rights on it)
Common stylesheets or layouts are deployed with the framework.
The user informations are provided by the framework. (central DB, the application has no rights on it)
The main problem is: How could I avoid any timers? I have no idea, how I could ensure, that the framework is up before everything else.
A few thoughts:
JBoss has the capability of ordering deployments according to their dependencies. See here and here. So, if all the "applications" depend explicitly on the "framework", your problem may be solved.
It seems you have a quite strongly coupled configuration. Would it be possible to decouple them, e.g. provide the service through web services (SOAP/REST)? Of course this introduces extra overhead for the communication and the refactoring...
JNDI can be seen (very roughly) as a name to object map shared across the applications. As such, you may share stuff through it. But I do not see how will you solve the timing problem, i.e. wait for a service to be available before using it from the "applications". The manager component you mention can be placed in JNDI.
This is not a complete answer, but it would not fit as a comment either. Maybe if you presented more details on the nature of the applications, the frameworks used etc, you could get more specific answers.
Good luck anyway
Edit #1:
Maintenance mode: This may be nice for using with JNDI. A servlet filter that intercepts every (applicable) request will check a global JNDI name; if it is not found (i.e. framework not started) or it is false, it will short-circuit the processing of the request, sending back the "maintenance mode" page. The framework will have to set a Boolean in the global JNDI name as soon as it has started and maintain its value, i.e. set it to false if maintenance mode is active.
Common stylesheets: This is really covered by the maintenance mode flag, I believe. Layouts: It depends on the view technology/layouts technology.
User information: This is a good candidate for SOAP/REST implementation. It is not expected to be called frequently, so I assume overhead will not matter.
I think OSGi is the technology you should consider. Basically you have an OSGi container with applications (called bundles) which provide or consume services. So you would have a framework service which is consumed by all applications. JBoss is an OSGi container, as far as I know.
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:
Create anf register a ServletRequestListener.
Upon the requestInitialized event bind the current HttpServletRequest to the JNI context giving in the name of the current Thread (Thread.currentThread().getName());
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?
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).
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.
When should an object (i.e. an application-wide properties file) be kept in the session, as opposed to creating a singleton to keep it? When should each of these approaches be used?
Note: I am working on a clustered environment, if that makes any difference.
If it's supposed to be application-wide, then you should not store it in the session scope, but in the application scope. With storing in the session scope, you're unnecessarily duplicating the same data for every visitor. A singleton is also not needed at all, just instantiate once during server startup with help of a ServletContextListener and store it in the application scope using ServletContext#setAttribute().
+1 to BalusC, but I suspect that was just a typo on your part.
As for singletons, it depends on what you mean by singleton. If you have an EJB annotated with #Singleton, then that's fine (other dependency-injection providers may also support this pattern).
If you're talking about the standard singleton pattern, where you keep the instance in a static variable, then that's a bad idea. You should generally avoid static variables in Java EE or servlet containers, because the class loading can be a bit tricky - you may wind up with multiple copies when you don't expect it, or you may be sharing a single copy between different applications, or you may be keeping stuff in memory when you redeploy your application. You can make an exception in cases where the variable isn't exposed outside the class, and you don't really care how many copies of it you have (for example, logger objects).
Note: I am working on a clustered environment, if that makes any difference.
I don't disagree with what Mike and BalusC have already written, but I feel you're entering territory where implementation details matter. What you do and how you do it will depend on the back-end services, what sort of clustering, and what the application requirements are. I think the question is too broad to give specific answers.
Furthermore...
All Java EE profiles share a set of common features, such as naming and resource injection, packaging rules, security requirements, etc. This guarantees a degree of uniformity across all products, and indirectly applications, that fall under the “Java EE platform” umbrella. This also ensures that developers who are familiar with a certain profile, or with the full platform, can move easily to other profiles, avoiding excessive compartmentalization of skills and experience.
Java EE specifications define a certain level of compliance but the goal isn't to make every infrastructure heterogeneous. This sort of thing adds complexity to an already nebulous problem domain.
I have a web application running on Google App Engine (GAE) for JAVA. I'm authenticating the client at the Servlet layer but would like to make the client information available to my business and data layers without having to pass the client object through the arguments of every single function.
I'm considering setting up a "session" type object using ThreadLocal. That way any function can just say something like:
CurrentUser.getRoles();
Is this a good way to do this or is there something else that is a more accepted solution?
Thanks!
This will probably work and will be utterly convenient, but usually I try to avoid ThreadLocals for similar use cases as much as I can. Reasons:
You code just suddenly starts to depend on the fact that underlying container uses different threads for different users. If the container will start using NIO, different type of threads (e.g. green threads which would not be mapped into java.lang.Thread on some exotic JVM), etc. you will be out of luck.
ThreadLocals tend to be forgotten to be cleaned up after using them. So if your server will spike in usage and one of the users will put lots of stuff into 'cache', you might run out of RAM.
As a consequence of not cleaning up after a request, ThreadLocal can expose security vulnerability assuming the other user would jump unto the same thread.
Finally, I believe ThreadLocals were designed for environments where you have an absolute control over threads in your context, and this use case is just so far beyond.
Unfortunately I don't know much about GAE to suggest a viable alternative, sorry about that!
ThreadLocals are a completely accepted way to store such information. Besides us I also know from Alfresco that they do it.
If using Spring and Spring Security works for you then you can use the code I've built as part of jappstart for your authentication/authorization. This information is then available via Spring Security.
When do we need single threded model in webapp while designing web application in java.
The single-threaded model should almost always be avoided. (I'm assuming you're talking about the SingleThreadModel interface.) Basically it was introduced in an attempt to save people from having to think about concurrency, but it was a bad idea. Concurrency is inherent in web applications - introducing a bottleneck like the single threaded model is the wrong solution. The right solution is to educate developers about concurrency better, and introduce better building blocks for handling it.
The interface is deprecated as of the Java Servlet API 2.4, with this note:
Note that SingleThreadModel does not
solve all thread safety issues. For
example, session attributes and static
variables can still be accessed by
multiple requests on multiple threads
at the same time, even when
SingleThreadModel servlets are used.
It is recommended that a developer
take other means to resolve those
issues instead of implementing this
interface, such as avoiding the usage
of an instance variable or
synchronizing the block of the code
accessing those resources. This
interface is deprecated in Servlet API
version 2.4.
When your Servlet has state (which is a bad idea) and you want to prevent multiple requests in stepping on their own toes (or data).
I would recommend you avoid it because at some point you will mess something up. Also, performance drops like a brick.
The single thread model for servlets is used to signal that the servlet cannot handle multiple concurrent threads from client connections. Setting a servlet to the single threading model results in the servlet container (application server) to create a servlet instance per client.
It is best practice not to use the single thread model for servlets. Data kept per client connection is typically stored in the client Session object.