I would like to read some parameters during servlet initializtion (in init() method), and store them among servlet context attributes (using getServletContext().setAttribute()). I would like to read these parameters later - during some request processing (using getServletContext().getAttribute()). So, the multiple threads could do this simultaneously. My question is if such an attempt is safe? Could I be sure that multi threaded calls to the getAttribute() don't mess up any internal state of the servlet context?
Please take into account that I'm not going to call the setAttribute() anywhere besides the initialization. So, only calls to the getAttribute() are going to be done from multiple threads. But depending on the internal implementation, this also could be dangerous. So, any information about Tomcat's implementation would be appreciated.
The primary implementation of ServletContext in Tomcat is the ApplicationContext class. If you look at the linked resource, you will see that the attributes are stored in a java.util.concurrent.ConcurrentHashMap instance. So, for ApplicationContext at least the getAttribute() and setAttribute() methods are thread-safe.
Related
I have a bunch of Servlets. I want all of them to instantiate a Logger, pretty much the exact same way.
Is there a proper (like a Main file) where I can bootsrap such code?
Currently what I do is created a subclass of the Servlet class, which does that in the init function and all the other Servltes inherit from it.
I don't know if it's a good idea what you are trying for the logger (i think you will lose some logger capacibilities), but well, if you want an unique instance of something in a servlet you should declare it and init it in the static way:
static final SomethingClear GLOBAL;
static{
// do tons of things to init
GLOBAL = ClassWithStaticFunc.gimmeGlobalLoaded();
}
An why is better this way? because there's another funny -or well, may be annoying :( - way to load a static (in the senses of uniqueness and that always will be an instance in memory) variable in a servlet:
Servlets dont have nothing like 'main'. They are unique instances which live in a servlet container, are instanciated by it, and its methods (doGet, doPost, doPut, doDelete) are executed by the servlet container on demand giving them request and response objects. So, in memory, there will be allways one and only one instance of each servlet, so any variable outside doGet, doPut, doDelete and doPost will be unique in memory. This was done this way in the beginings of the java-time in order to save memory...
And this is a funny way to merge sessions... :(
If you assing something to anything outside that methods in a servlet it will be assigned to all sessions of your application, and is not obvious and is not so easy to find...
So its better to mark them as static and final because they'll be always created (you have no access to objects construction) and there will be only one instance. It's not nice, but servlets are not nice...
I once did a unique servlet whose invoke my custom 'Servlets' using reflection (one object per petition, giving the name of my 'servlet' in the web.xml as initParam and setting the servlet-name always to the same servlet that was the instanciator of mines) to solve session merges and worked great.
I understand that this is normally not done, and I've found a number of instances of this question around the web with answers of the sort: "Your design is wrong if you need to do this." Let me explain my goal.
I have a web app that at one site somehow caused one servlet's init() method to be called repeatedly. I don't know how this happened and I cannot repeat it. However, from a binary heap dump (caused by an out-of-memory exception), it is very clear from objects on the heap that a specific servlet's init() method got called about 10,000 times, as that is the only place these objects are created and there were 10,000+ instances of an object that is supposed to have no more than one instance.
Since I cannot reproduce what happened at this one site, I instead want to forcefully invoke init() many times on this servlet, preferably via a JSP file, so I can test before and after a fix is applied. Testing the "after" case is easy in theory because I can change the code to (for example) stick this servlet into the context so I can get it and repeatedly call init() to prove that there is no leak of this object. But this does not help me test the "before" case with the existing code.
I cannot just "(new MyServlet()).init()" in a JSP. This fails as the servlet is created with a null context and fails to initialize. By Tomcat 5.5, it seems that ServletContext.getServlets() always returns an empty Enumeration and that ServletContext.getServlet(String) always returns null.
It seems the easiest way to test is if I can somehow programmatically (preferably from a JSP) get access to the servlet instance in question, or alternately, programmatically add new mappings to that same servlet class, which might create new instances. (?)
You've already figured out that what you are attempting is highly out of the ordinary and far from a best practice so I won't go into any detail on that subject. Having said that, if you want to invoke MyServlet.init() many times on an instance of MyServlet running within Tomcat, you could subclass MyServlet, override the doGet() or doPost() method, add a loop that simply calls this.init(); 1000 times and then call the parent classes doGet()/doPost(). Edit WEB-INF/web.xml to use your subclass in place of MyServlet. Then just hit the servlet with your web browser and see init() called 1000 times prior to serving the page normally. And you haven't modified the original MyServlet class at all, keeping your before test pure.
You can create a servlet instance like any other class object. Get hold of the servlet config by overriding the method init(ServletConfig config). And create the servlet class instance as many as u want, and call init(ServletConfig config) on all those instances created.
I'm in the situation where I need to create a cache to store certains values which need to be updated from the database. Since this cache needs to be singular, some sort of singleton implementation seems appropriate.
The problem is that this cache also needs access to the database via an EJB, which can't be injected since the cache exists outside of context (and yes, I'm looking forward to the #singleton annotation in EJB3.1).
The obvious solution is to pass the EJB into the cache as a parameter, but passing EJBs outside of context feels wrong, though I can't say why. Is it accepted practice?
Do note that you are normally not passing the EJB itself "outside of context". What you are typically passing around is a 'stub'. This stub can be passed around as any other normal object reference. Any calls on it will redirect back to an actual bean instance in the EJB container.
So if you have a cache in say the web module, have a backing bean injected with an EJB (or do a JNDI lookup) and pass that reference to a (static) cache, then I don't see a fundamental problem with that.
For all intends and purposes, the #Singleton annotation was indeed made for something like this. Hope you'll able to use it soon ;)
The main advantage of EJB is inside container. If you pass it outside you loose all the advantages which a container provide. Why don't you create a method in EJB that return the data you need. And the you can do, for example, JNDI lookup and call that method. In this way EJB will stay in the container and you will get your data.
I have a couple of global variables in a servlet. Individual servlet sessions read from and wrote to these variables. They are used to coordinate values posted to a database so it is important that the sessions remain in synch. My question is can I use synchronize key words with servlets to keep different servlet sessions from colliding with each other at these global variables?
Thank you,
I'd recommend not doing stuff like this in the servlet class itself. Have your servlet's doGet() etc. call into another object to do the real work. If this delegated class is a singleton then you have full control over initialization, state etc.
If you rely on how the app server loads the servlet class itself things can get brittle. Best to just let the server classload/share the servlet whenever it feels like and not depend on specific behavior.
I want to create a Thread safe JSP page. It is possible in Servlet by implementing SingleThreadModel interface but I don't know how to do it in JSP page.
Theoretically, JSP pages can be indicated as threadsafe via the isThreadSafe page directive attribute. Setting a value of false, will get the container to synchronize access to page level objects (and not to session and application scoped objects or objects of any other variety). Obviously, it is still the responsibility of the developer to ensure that synchronous access to thread unsafe regions of code.
Morevoer, the SingleThreadModel interface has also been deprecated in the Servlet Specification release 2.4. The SingleThreadModel interface is used to implement the supposed thread safety in JSPs as well - generated servlet classes will implement the SingleThreadModel for JSPs that use the threadsafe attribute. The specification itself outlines why the interface is deprecated:
SRV.2.2.1 Note About The Single Thread Model
The use of the SingleThreadModel
interface guarantees that only one
thread at a time will execute in a
given servlet instance’s service
method. It is important to note that
this guarantee only applies to each
servlet instance, since the container
may choose to pool such objects.
Objects that are accessible to more
than one servlet instance at a time,
such as instances of HttpSession, may
be available at any particular time to
multiple servlets, including those
that implement SingleThreadModel.
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. The
SingleThreadModel Interface is
deprecated in this version of the
specification.
First the short answer <%#page isThreadSafe="false" %>
The longer answer is don't do that.
You need to be very clear about your objective here. You haven't made a servlet truly thread-safe by using a SingleThreadModel, rather you have set things up so that only one thread at a time can get into your servlet. Presumbly you would be doing that exactly because the Servlet code is not thread safe, that is if more than one thread were to get at the code bad things would happen.
This implies to me that you have something like this in the servlet code:
doGet(/*etc/*){
// ... stuff
someExistingUnsafeClass.doSomething();
// .. more stuff
}
After all, your serlvet code itself cannot be thread-unsafe, surely? You would fix it, right? So it must be some legacy code that's thread-unsafe?
If this is the scenario, with your JSP needing to use that existing legacy code, somewhere in your JSP you have a call that unsafe stuff:
<%
someExistingUnsafeClass.doSomething();
%>
So you just need to protect this unsafe call:
<%
synchronized(this){
someExistingUnsafeClass.doSomething();
};
%>
Allowing the bulk of your JSP to run properly threaded will perform much better.
I should also say, that if you structure your application as MVC then all thread-unsafe code is called from the controller and the view (the JSP) never needs to be unsafe.
By not having any state information in your JSP page. (No instance variables, that can change accross different requests). If you do not have any state in your JSP or servlet, they are threadsafe
Talking about thread-safety with JSP is wrong - JSP is a view technology and it only displays results - it doesn't do any processing. (it can do processing, but it must not)
Thread-safety with servlets is achieved by having no private fields in the servlet - the servlet instance is one for the whole container and each request is a new thread invoking the service(..) method.
You should specify exactly what you mean by "thread-safety" in your case - i.e. what do you expect to fail.
In JSP, just use variables in scriplets and you can be confident that they are thread safe because they will be translated into local variable in service().
You don't.
JSP is basically a single method in a servlet. As you may know already, methods are thread safe, the the sense, that two threads invoking the same method of the same object at the same time, will execute each one in its own stack.
So, you don't really need to make a thread safe JSP, because, it is trade safe already.
If you declare a variable a in a JSP, there is no way, another request sees that variable.
What you must be aware of, is, objects put into the session, or the context may be accessed by multiple threads at the same time, or pretty much not thread safe code. Then what you must synchronize or take care of, are those objects!, and not the JSP page it self.