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.
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.
we have a JavaEE Web application that runs on Tomcat5 server (jsp, java and extjs are used on development of this tool).
We observe sometimes, particularly when the application is highly used, that some session variables or interface fields are mixed up in servlets.
This means that : when one user connects, his parameters are kept in the sessions.
After an update or insertion of data in the database ORACLE,the system returns the name of another user who was probably connected at the same time on a different navigator or a different computer.
Others times the request.getparameter gets a values from different clients or user interfaces.
Thank you to help me fix this problem.
The only way for this to happen is if you have a singleton somewhere that keeps track of the session and for some reason this singleton is mixing up the variables between sessions.
You can try this: Instead of differentiating a user only by its credentials (assuming you are not using Federation), return a token, unique amongst all sessions to the user logging in, and make the user send that unique id with every request. This way you will be able to differentiate the request/responses even if the user logs in using many different browsers.
But again, this will only happen when you do something like having a singleton connecting the session, by itself the session would not exchange variables amongst them.
I've finally understood how servlet.java works.
I works like main process that create a thread for any call
thus, all attributes of such class are common to all thread and we are not sure of the result that we get when accessing them.
If we want any client to use those variables in a private context, we must put them in the function "doGet" or "doPost" as local variables.
My problem have them been solved
I have a global variable called loginAttempt in a servlet class. What will happen to this global variable if two requests hit on the same time?What will happen is an unforeseeable event.
Is having global variables in servlet an evil ??
If i put the loginAttempt is side doPost() its initializing each time.
Yes.
Your variable is readable/writeable by any other class. You have no control to ensure that they all do sensible things with it. One of them could overwrite it/incorrectly increment it, etc
The is one instance of a servlet, per JVM. So may threads may try to access it concurrently. Because it is global, and you are not providing any synchronization/access control, it will not be thread-safe. Also, if you ever run the servlet in some kind of cluster with different JVMs, then the variable will not be shared between them and you will have multiple loginAttempt variables.
If you have to have it in the servlet, make it static but do not make it public. Provide getters/setters to access and update it. Learn about thread-safe programming so that multiple-threads can update it and read it safely.
Much better, store it in the servlet-context. This should be where you store servlet-wide data like this.
They are not evil as long as you understand that there is generally only a single instance of a servlet created and the global variable will be shared by all clients of that servlet - that is every request, on different threads at the same time and by multiple users at the same time.
I am guessing that your global variable loginAttempt is counting the number of login attempts then as long as this is done in a thread safe way it would be a reasonable way of counting the number of login attempts made on this servlet. This would be for all users though. If you want login attempts per user then you probably need to create a session and use the session context to store this sort of info.
Store it as a session attribute. Otherwise the global variable concept will screw you up totally.
Using session is a good idea as it's
1) If the web service is restarted, the session data is not lost
2) In a load balanced environment, the session data is stored in a central location, meaning any server can serve the request and have access to the session data.
So it's accessible yet it's hidden.
In a large number of concurrent access,You may want to pay attention to the thread safety problem of Servlet...and you can try the following methods to avoid this problem...
1、
public class loginAttempt extends HttpServlet implements SingleThreadModel {
...
}
2、
The second method:
Use the synchronized keyword
3、
Avoid the use of global variable
YES.
Global variables are shared with everyone
It depends, if your variable is read-only, it should be fine. But in most cases, global variables are evil. I can't give you a solution because I don't have your code but I am sure there is an alternative way.
In your usecase, it is beyond evil. loginAttempt will be shared by all threads accessing the servlet
First of all there is no terminology called global variable in Java. They are called class variable or instance variable.
Second, Yes its bad practice to have instance variable in the Servlet if you are assigning request or session scoped data as it will be shared by all threads.
You can use it for application-wide values, most often obtained from context parameters. or If the data never changes (immutable) like Constants.
I want to create a Servlet that processes input to a serial device and for that reason I want to make sure that exactly one instance of Servlet exists in the container at a time (irrespective of whether the container makes only one instance I have to make sure of it) and also the access to the serial port is either synchronised or serialised.
Any suggestions?
You don't need the servlet to be a singleton, you only need to be able to control access to the serial port. In fact even if you could enforce a single instance of the servlet class, the spec enables multiple users to access the servlet concurrently.
You could instead write a class that handles access to the port, encapsulating control by only allowing a single thread to access at a time. You'd then need to decide how you wanted concurrent requests to the servlet to behave (block, return some sort of 'serial port in use' error message, etc).
Suggestion: don't do that. Leave servlet management to the container, and use your own singleton for serial port processing.
Solution: you cannot, as you have no control over constructor. What you can do, though, (and what is a Very Bad Thing—don't tell anyone I said that) is to have a static field in a servlet, keeping a reference to the first instantiated instance. This way, all the instances of the servlet will be able to delegate the processing to this very first instance.
Again, just separating request processing from serial port processing will make things much more easier for both you and the container.
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.