I have a web application where multiple servlets use a certain amount of identical logic for pre-initialization (setting up logging, session tracking, etc.). What I did was to introduce an intermediary level between javax.servlet.http.HttpServlet and my concrete servlet class:
public abstract class AbstractHttpServlet extends HttpServlet {
// ... some common things ...
}
and then:
public class MyServlet extends AbstractHttpServlet {
// ... specialized logic ...
}
One of the things I do in AbstractHttpServlet's default (and only) constructor is to set a few private member variables. In this case it is a UUID, which serves as a session identifier:
public abstract class AbstractHttpServlet extends HttpServlet {
private UUID sessionUuid;
public AbstractHttpServlet() {
super();
this.sessionUuid = UUID.randomUUID();
// ... there's more, but snipped for brevity ...
}
protected UUID getSessionUuid() {
return this.sessionUuid;
}
}
I then use getSessionUuid() in MyServlet to provide for session tracking within the request. This is very useful e.g. in logging, to be able to sift through a large log file and get all entries relating to a single HTTP request. In principle the session identifier could be anything; I just picked using a UUID because it is easy to generate a random one and there's no need to worry about collisions between different servers, seed issues, searching through the log file turning up a match as a portion of a longer string, etc etc.
I don't see any reason why multiple executions should get the same value in the sessionUuid member variable, but in practice, it appears that they do. It's as if the instance of the class is being reused for multiple requests even over a long period of time (seemingly until the server process is restarted).
In my case, class instantiation overhead is minor compared to the useful work done by the class, so ideally I'd like Tomcat to always create new class instances for each request and thus force it to execute the constructor separately each time. Is it possible to perhaps annotate the class to ensure that it is instantiated per request? Answers that don't require server configuration changes are much preferred.
Failing that, is there a way (other than doing so separately in each do*() method such as doGet(), doPost(), etc.) to ensure that some sort of initialization is done per HTTP request which results in execution of a particular servlet?
It's as if the instance of the class is being reused for multiple requests even over a long period of time (seemingly until the server process is restarted).
Yes, that's exactly what will be happening, and what you should expect.
A servlet isn't meant to be a session - it's just meant to be the handler.
If you want to do "something" on each request, no matter what the method, you can override the service method, take whatever action, and then call super.service(). However, you shouldn't change the state of the servlet itself - bear in mind that multiple requests may execute in the same servlet at the same time.
Basically, what you're asking for goes against the design of servlets - you should work with the design rather than against it. You could modify the request itself (using setAttribute) to store some information related to just this request - but I'd probably do that at a higher level than HTTP anyway. (I'd try to make the servlet itself very small, just delegating to non-servlet-aware classes as far as possible, which makes them easier to test.)
This code is not threadsafe. The servlet container will generally create one instance of the servlet and all requests will use it.This means that the sessionUUID will be shared by all requests and will be continually overwritten.
If you need to keep this value on a per request basis, consider using a ThreadLocal object and putting the UUID in there.
It's as if the instance of the class is being reused for multiple requests even over a long period of time.
There is always one instance of a Servlet class at any given point in time per JVM. Hence instance variables are not thread safe in Servlet. Each request for the Servlet will be processed by a thread. Local variables declared inside the service(),doPost() and doGet() will be thread safe .
Hence you can move your logic to some other class , instantiate it inside the service methods and use it in thread safe fashion.You can even use ThreadLocal objects.
There is a provision to implement the SingleThreadModel ,it is deprecated, it is not only bad but ridiculous to do so.
Ensures that servlets handle only one request at a time. This interface has no methods.
If a servlet implements this interface, you are guaranteed that no two threads will execute concurrently in the servlet's service method. The servlet container can make this guarantee by synchronizing access to a single instance of the servlet, or by maintaining a pool of servlet instances and dispatching each new request to a free servlet.
Better to implement a ServletRequestListener and put the logic there.
Related
If multiple requests are handled by a server to run a single servlet then where we need to take care of synchronization?
I have got the answer from How does a single servlet handle multiple requests from client side how multiple requests are handled. But then again there is a question that why we need synchronization if all requests are handled separately?
Can you give some real life example how a shared state works and how a servlet can be dependent? I am not much interested in code but looking for explanation with example of any portal application? Like if there is any login page how it is accessed by n number of users concurrently.
If more than one request is handled by the server.. like what I read is server make a thread pool of n threads to serve the requests and I guess each thread will have their own set of parameters to maintain the session... so is there any chance that two or more threads (means two or more requests) can collide with each other?
Synchronization is required when multiple threads are modifying a shared resources.
So, when all your servlets are independent of each other, you don't worry about the fact that they run in parallel.
But, if they work on "shared state" somehow (for example by reading/writing values into some sort of centralized data store); then you have to make sure that things don't go wrong. Of course: the layer/form how to provide the necessary synchronization to your application depends on your exact setup.
Yes, my answer is pretty generic; but so is your question.
Synchronization in Java will only be needed if shared object is mutable. if your shared object is either read-only or immutable object, then you don't need synchronization, despite running multiple threads. Same is true with what threads are doing with an object if all the threads are only reading value then you don't require synchronization in Java.
Read more
Basically if your servlet application is multi-threaded, then data associated with servlet will not be thread safe. The common example given in many text books are things like a hit counter, stored as a private variable:
e.g
public class YourServlet implements Servlet {
private int counter;
public void service(ServletRequest req, ServletResponse, res) {
//this is not thread safe
counter ++;
}
}
This is because the service method and Servlet is operated on by multiple thread incoming as HTTP requests. The unary increment operator has to firstly read the current value, add one and the write the value back. Another thread doing the same operation concurrently, may increment the value after the first thread has read the value, but before it is written back, thus resulting in a lost write.
So in this case you should use synchronisation, or even better, the AtomicInteger class included as part of Java Concurrency from 1.5 onwards.
Can i use a singleton within a servlet to share information between diffrent session.
I know that only 1 instance Servlet is running at any time. Calling service method for each incoming request. But how about creating another Singleton class (for eg: ShareSingleton) which calls its getInstance() in the servlets Init() method. This ShareSingleton can carry data that needs to be shared between sessions/reqests.
Is it risky to use such an approach in servlets ?
First..see this for the best approach of singletons: http://javarevisited.blogspot.com/2012/07/why-enum-singleton-are-better-in-java.html
Second: Remember singletons are only single to the JVM. So..if you have more than one JVM running do not expect each singleton to have the same state.
Third: To be safe, I would instantiate the singleton from a listener of the servlet context.
see http://docs.oracle.com/javaee/6/api/javax/servlet/ServletContextListener.html
define a class in your web.xml and instantiate it there. Your singleton will be created when your webapp starts up rather than when n people hit the service method of your servlet at once.
Yes, you can. Note that the servlet container may use multiple instance of the Servlet object, so you'll have to make sure one object is shared amongst all these instances.
For example, you might do:
private static final Cache<String,String> = //cache
And then use the value in the cache if it's available, or otherwise update the cache with a newly calculated value. Note that the object that is shared must be thread safe.
Referring to: Head First Servlets & JSP, page 204, third question:
Q. "The
effect of implementing SingleThreadModel is virtually
the same as synchronizing the service method. Both
can bring a web app to its knees without protecting
the session and context state."
What does this mean: "bring a web app to its knees without protecting the session and context state"? Are they saying that it's not enough thread-safe to implement the SingleThreadModel? Because even though only one thread at a time can be running at one servlet, this doesn't stop other servlets from accessing and mutating the context/session scoped variables? If a Servlet implements the SingleThreadingModel, then why would you need to protect session state? It only allows one thread at a time. Even if you open up a new browser window, the servlet wouldn't allow you to make two requests, I think. Maybe they mean that different Servlets with one thread at a time could still corrupt the context/session state if they don't synchronize on that state?
And why are class (static) variables not thread-safe? Because all threads can access and modify (corrupt) that value?
It's still a little vague to me.
Referring to: Head First Servlets & JSP, page 204, third question:
Q. "The
effect of implementing SingleThreadModel is virtually
the same as synchronizing the service method. Both
can bring a web app to its knees without protecting
the session and context state."
What does this mean: "bring a web app to its knees without protecting the session and context state"? Are they saying that it's not enough thread-safe to implement the SingleThreadModel? Because even though only one thread at a time can be running at one servlet, this doesn't stop other servlets from accessing and mutating the context/session scoped variables?`
This is correct.
If a Servlet implements the SingleThreadingModel, then why would you need to protect session state? It only allows one thread at a time. Even if you open up a new browser window, the servlet wouldn't allow you to make two requests, I think.
That is incorrect. You could have another tab, another window or whatever. You might not be able to access the same Servlet at the same time, because you might be blocked, but you could access another Servlet that also accesses the same Context or Session. And, according to the API, it is allowable to have multiple instances of the same Servlet serve multiple responses in different threads (the only restriction is that one instance can't server multiple threads).
Maybe they mean that different Servlets with one thread at a time could still corrupt the context/session state if they don't synchronize on that state?
And why are class (static) variables not thread-safe? Because all threads can access and modify (corrupt) that value?
There is nothing inherently more or less thread-safe about static variables than instance variables. But you have to understand how the values are protected and how the SingleThreadModel is implemented. If the SingleThreadModel is implemented by allowing multiple instances of the Servlet, each stuck on a single Thread, then the static variables would be shared among all instances and therefore accessible to their threads as well.
Regardless, I would think you should never use (non-final) static variables in the Servlet class because you don't control the Servlet's life cycle. It can be created, destroyed, and recreated as the container demands. So a value you put in the static variables may not be there when you next try to access it. And you should never use the SingleThreadModel because it is inefficient and doesn't really do its job, and it has been deprecated for a long time. So you definitely should not use them both together.
bring a web app to its knees
Because the access to the service() method of the Servlet will be synchronized . This can be implemented in two ways , (1) block other request threads till the current thread completes execution of the service() , (2) Create new instance of the Servlet (or maintain a pool of Servlet instance) in the Container and each request invokes the service() of a separate instance. Both are resource intensive and non performant.
without protecting the session and context state
Because even though you synchronize access to the service() method of your particular Servlet which implements the SingleThreadModel . The access to the session and context are not synchronized . Code other than your Servlet are free to access HttpSession or ServletContext attributes.
Are they saying that it's not enough thread-safe to implement the SingleThreadModel?
Yes , even the class variables may not be thread safe , if the Container implements the model such that each thread uses a free Servlet instance from the pool.
Because even though only one thread at a time can be running at one servlet, this doesn't stop other servlets from accessing and mutating the context/session scoped variables?
Absolutely.
If a Servlet implements the SingleThreadingModel, then why would you need to protect session state?
To protect the data stored in the HttpSession . Because even though only one thread at a time can be running at one servlet, this doesn't stop other servlets from accessing and mutating the context/session scoped variables.
class (static) variables not thread-safe
Because it is shared by all instances of a class.
And why are class (static) variables not thread-safe? Because all
threads can access and modify (corrupt) that value?
Correct. If a member is static, one thread can set a value and another thread can set differently. As static is shared variable, the value set by first thread will be the same for another thread also.
Q. "The effect of implementing SingleThreadModel is virtually the same
as synchronizing the service method. Both can bring a web app to its
knees without protecting the session and context state."
Even if you make some servlet implement SingleThreadModel, it will stop only those thread to executly simultaneoulsy which are trying to access that servlet. It can't stop all other servlets which do not implement SingleThreadModel from accessing context and session attributes. This is because context attributes are available all over the web application and anyone resource can access them and modify them.
I'd like to multithread my GAE servlets so that the same servlet on the same instance can handle up to 10 (on frontend instance I believe the max # threads is 10) concurrent requests from different users at the same time, timeslicing between each of them.
public class MyServlet implements HttpServlet {
private Executor executor;
#Override
public void doGet(HttpServletRequest request, HttpServletResponse response) {
if(executor == null) {
ThreadFactory threadFactory = ThreadManager.currentRequestFactory();
executor = Executors.newCachedThreadPoolthreadFactory);
}
MyResult result = executor.submit(new MyTask(request));
writeResponseAndReturn(response, result);
}
}
So basically when GAE starts up, the first time it gets a request to this servlet, an Executor is created and then saved. Then each new servlet request uses that executor to spawn a new thread. Obviously everything inside MyTask must be thread-safe.
What I'm concerned about is whether or not this truly does what I'm hoping it does. That is, does this code create a non-blocking servlet that can handle multiple requests from multiple users at the same time? If not, why and what do I need to do to fix it? And, in general, is there anything else that a GAE maestro can spot that is dead wrong? Thanks in advance.
I don't think your code would work.
The doGet method is running in threads managed by the servlet container. When a request comes in, a servlet thread is occupied, and it will not be released until doGet method return. In your code, the executor.submit would return a Future object. To get the actual result you need to invoke get method on the Future object, and it would block until the MyTask finishes its task. Only after that, doGet method returns and new requests can kick in.
I am not familiar with GAE, but according to their docs, you can declare your servlet as thread-safe and then the container will dispatch multiple requests to each web server in parallel:
<!-- in appengine-web.xml -->
<threadsafe>true</threadsafe>
You implicitly asked two questions, so let me answer both:
1. How can I get my AppEngine Instance to handle multiple concurrent requests?
You really only need to do two things:
Add the statement <threadsafe>true</threadsafe> to your appengine-web.xml file, which you can find in the war\WEB-INF folder.
Make sure that the code inside all your request handlers is actually thread-safe, i.e. use only local variables in your doGet(...), doPost(...), etc. methods or make sure you synchronize all access to class or global variables.
This will tell the AppEngine instance server framework that your code is thread-safe and that you are allowing it to call all of your request handlers multiple times in different threads to handle several requests at the same time. Note: AFAIK, It is not possible to set this one a per-servlet basis. So, ALL your servlets need to be thread-safe!
So, in essence, the executor-code you posted is already included in the server code of each AppEngine instance, and actually calls your doGet(...) method from inside the run method of a separate thread that AppEngine creates (or reuses) for each request. Basically doGet() already is your MyTask().
The relevant part of the Docs is here (although it doesn't really say much): https://developers.google.com/appengine/docs/java/config/appconfig#Using_Concurrent_Requests
2. Is the posted code useful for this (or any other) purpose?
AppEngine in its current form does not allow you to create and use your own threads to accept requests. It only allows you to create threads inside your doGet(...) handler, using the currentRequestThreadFactory() method you mentioned, but only to do parallel processing for this one request and not to accept a second one in parallel (this happens outside doGet()).
The name currentRequestThreadFactory() might be a little misleading here. It does not mean that it will return the current Factory of RequestThreads, i.e. threads that handle requests. It means that it returns a Factory that can create Threads inside the currentRequest. So, unfortunately it is actually not even allowed to use the returned ThreadFactory beyond the scope of the current doGet() execution, like you are suggesting by creating an Executor based on it and keeping it around in a class variable.
For frontend instances, any threads you create inside a doGet() call will get terminated immediately when your doGet() method returns. For backend instances, you are allowed to create threads that keep running, but since you are not allowed to open server sockets for accepting requests inside these threads, these will still not allow you to manage the request handling yourself.
You can find more details on what you can and cannot do inside an appengine servlet here:
The Java Servlet Environment - The Sandbox (specifically the Threads section)
For completeness, let's see how your code can be made "legal":
The following should work, but it won't make a difference in terms of your code being able to handle multiple requests in parallel. That will be determined solely by the <threadsafe>true</threadsafe> setting in you appengine-web.xml. So, technically, this code is just really inefficient and splits an essentially linear program flow across two threads. But here it is anyways:
public class MyServlet implements HttpServlet {
#Override
public void doGet(HttpServletRequest request, HttpServletResponse response) {
ThreadFactory threadFactory = ThreadManager.currentRequestThreadFactory();
Executor executor = Executors.newCachedThreadPool(threadFactory);
Future<MyResult> result = executor.submit(new MyTask(request)); // Fires off request handling in a separate thread
writeResponse(response, result.get()); // Waits for thread to complete and builds response. After that, doGet() returns
}
}
Since you are already inside a separate thread that is specific to the request you are currently handling, you should definitely save yourself the "thread inside a thread" and simply do this instead:
public class MyServlet implements HttpServlet {
#Override
public void doGet(HttpServletRequest request, HttpServletResponse response) {
writeResponse(response, new MyTask(request).call()); // Delegate request handling to MyTask object in current thread and write out returned response
}
}
Or, even better, just move the code from MyTask.call() into the doGet() method. ;)
Aside - Regarding the limit of 10 simultaneous servlet threads you mentioned:
This is a (temporary) design-decision that allows Google to control the load on their servers more easily (specifically the memory use of servlets).
You can find more discussion on those issues here:
Issue 7927: Allow configurable limit of concurrent requests per instance
Dynamic Backend Instance Scaling
If your bill shoots up due to increased latency, you may not be refunded the charges incurred
This topic has been bugging the heck out of me, too, since I am a strong believer in ultra-lean servlet code, so my usual servlets could easily handle hundreds, if not thousands, of concurrent requests. Having to pay for more instances due to this arbitrary limit of 10 threads per instance is a little annoying to me to say the least. But reading over the links I posted above, it sounds like they are aware of this and are working on a better solution. So, let's see what announcements Google I/O 2013 will bring in May... :)
I second the assessments of ericson and Markus A.
If however, for some reason (or for some other scenario) you want to follow the path that uses your code snippet as a starting point, I'd suggest that you change your executor definition to:
private static Executor executor;
so that it becomes static across instances.
I have few questions. As far as I know, every request to a container becomes a HttpServletRequest. More request-> more instances of HttpServletRequest. Then, when a request object calls a servlet called 'abc', an instance of 'abc' servlet is created. Let's say same time 3 requests come to 'abc' servlet ,then
(1) I want to know ,does it mean, 3 instances of 'abc' servlet per each request are created? or requests are queued till one request to the servlet is done.
Then let's say,3 request to 'abc' servlet do some database processes which could be insertions and retrieves at the same time. Then
(2) does one request should be in the queue until other request's servelt completes the task (synchronize)or all servelets do their DB task as multi threads as seperate tasks(not sinchronized) ?
(3). If they work as not synchronized, how can we make those tasks synchronized (lets say, only one particular task-save some thing to DB) and queued ? to do so, is it better to implement the servlet SingleThreadModel or use a method which is in a class created according to singleton pattern ? Then how it affect to the performance of the container?
In short,how can we run a particular task synchronized for all requests ?
I read this as well. That article says about servlets. Lets say the task of a servlet is handed over to another class, then I would like to know how about using singleton pattern on this?
A container may create a pool of servlet instances (an excerpt from a servlet spec below explains the details). It may use three different instances for three concurrent requests or may use one for all three. Your servlets thus need to be thread safe and shouldn't have state in their member variables. The SingleThreadModel marker interface will signal to container not to use same instance of the servlet for more than one concurrent request (thus making your servlet thread-safe) but it won't prevent the container from creating multiple instances and using them simultaneously. makes sense? if your operation requires synchronization then you handle it in your Model classes, not your Controller. So basically synchronize (or queue things up) elsewhere is the answer. Let the servlets take the command and just run with it without putting too much thoughts into the process.
UPDATE. A very basic example of explicit operation synchronization for your case (not that I like it, just to illustrate the point) would be to have a singleton service handling your operation with its main do() method declared as synchronized. Ideally, though, you would delegate database concurrency to your database and persistence layer (transactions, optimistic concurrency).
CORRECTION as per the servlets spec:
In the default case of a servlet not implementing SingleThreadModel and not hosted in a
distributed environment, the servlet container must use only one instance of a servlet class
per servlet definition.
In the case of a servlet that implements the SingleThreadModel interface, the servlet
container may instantiate multiple instances of that servlet so that it can handle a heavy
request load while still serializing requests to a single instance.
With that said, you would have only one instance of your servlet unless you use that single thread model marker.
1) No, only instance of servlet exists per server
2) No, each request is separate thread
Your server could shouldn't contain any instance variables (or) static variables, then synchronization won't be any issue because each thread will have it's own copy of local variables and execution sequence.
3) You can make servlet synchronized by prefixing synchronized the doGet(), doPost() methods are with the help of synch block. But it is bad practice.
Refer this SO Wiki link for complete discussion.
to synchronize a particular task, Let me suggest 2 ways.
use java synchronized block. You should consider what object is suitable for the lock object.
use database lock. Such as select * from xxx for update