Apache Tomcat Servlet threads not finishing - java

I've written a servlet deployed in tomcat.
public class myServlet extends HttpServlet {
public int NumberOfThreads = 0;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println(NumberOfThreads);
NumberOfThreads++;
....
..a lot of code..
....
NumberOfThreads--;
}
}
Now when I get too many requests the NumberOfThreads keeps rising and never goes down again. My problem is that there is a few tasks that have to be performed by each request before leaving.
I just don't understand why this happens. Is it that some of the threads get lost on the way? I really need each request to say properly goodbye.
Thanks

You are doing it wrong.
System.out.println(ManagementFactory.getThreadMXBean().getThreadCount());
Alternatively, just use JMX/JConsole.

As you're speaking about this taking a long time and requests are being cancelled (in your comment): Yes, the whole doGet will be executed, even when the user cancelled the request: Request cancelling is only on HTTP level. However, when the request is cancelled, the HTTP connection might be closed, resulting in exceptions when you actually want to write to the response's output stream.
Combining the other answers already given:
You'll need to synchronize your modifications of the counter (see didxga's answer)
there's probably a better way to solve your problem (as Ravi Thapliyal states)
use try{ ... } finally { ... } to ensure you actually decrease the counter
make your code more maintainable by moving it out of the servlet into a proper, non-UI, class
Pseudo code:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
synchronized(this){NumberOfThreads++;}
doSomething();
} finally {
synchronized(this){NumberOfThreads--;}
}
}
Also, be aware that long-running execution in the actual http connector thread blocks all subsequent http requests - it might be a good idea to trigger background processing and just query that background process in later HTTP requests. That way you can also queue multiple invocations and not start a huge number of background threads at the same time. Keep in mind, there's a limited number of HTTP request handlers.
I'm assuming the try/finally will be your main problem (or an endless loop in your code) - synchronizing will solve rare race conditions, especially as you're speaking of a lot of code executed in this servlet.

The different servlet threads are caching NumberOfThreads. You have to mark it as volatile.
public volatile int NumberOfThreads = 0;
But, I have a feeling that there are better ways of doing what you probably want to achieve with this code.

You need to synchronize modification to NumberOfThreads
public class myServlet extends HttpServlet {
public int NumberOfThreads = 0;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println(NumberOfThreads);
synchronized(this){NumberOfThreads++;}
....
..a lot of code..
....
synchronized(this){NumberOfThreads--;}
}
}

Related

Execute method before Business Logic

I know about Servlet Filters and Event Listeners but I'm not sure if that's what I need to use.
Let's say I have a method:
Integer count = 0;
public void increment() {
count++;
}
and then a doGet:
public void doGet(HttpServletRequest request, HttpServletResponse response) {
System.out.println(count);
}
When performing a Get request for the first time, I'd expect count=1 and not count=0 because I want the method increment() to be executed first, before any other business logic in the web application.
Also, the count should be different for each user. It should be based on the number of requests a particular user has made.
What can I use to solve this problem?
I would prefer to not use Spring or any other 3rd party library
This all depends on where the count should be available, but you can create an abstract HttpServlet sub class that calls some abstract method to perform logic before handling the request
public abstract class BaseServlet extends HttpServlet {
#Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// wrap it in try-catch if you need to
prePerformLogic(req, resp);
// call super implementation for delegation to appropriate handler
super.service(req, resp);
}
protected abstract void prePerformLogic(HttpServletRequest req,
HttpServletResponse resp) throws ServletException, IOException;
}
Now your own Servlet implementation will extend from this class. You'll implement it as you see fit. But, as Luiggi has stated in the comments, the example you've posted brings up many possible concurrency issues. A Servlet shouldn't normally have any mutable state.
If you just want to add an counter attribute to the HttpSession, synchronize on the HttpSession, check if an attribute exists. If it doesn't, add one starting at 0. If it does, increment it and add it back as an attribute. You might get better performance with a AtomicInteger, but you need to synchronized the check for the existence of the attribute.
A Filter would probably be more appropriate in that sense, since the Servlet wouldn't have any state anyway.

How to make a servlet respond to multiple requests?

I have a task that I want to wrap in a servlet to provide the ability to run the task remotely, by http request.
I know I can achieve this with REST API, but currently I assume (and please correct me if I'm wrong) that a simple servlet will do.
One of the things I want to achieve is that if a request to the servlet is made while another request is still processed, I'll get an appropriate response - "Task is already running".
I've built a simple servlet, using servlet-3.0, that calls the jar I want to run, but when I make 2 requests, the second one is not processed until the first one is finished.
EDIT:
My servlet is a simple http serlvet. service method overriden.
I have a system.out.println("a") in the start.
when I call the servlet in debug mode and then (while stopped at breakpoint) call it again, the message is printed only one time and printed the second time when I release the breakpoint and the first run finishes.
First of all, this does not seems like REST at all. If you really just want to spawn a (single) background task, make sure you do it in a separate worker thread, not the request thread.
Maybe you need a lock:
public class Task extends HttpServlet {
// for singleton
//private volatile boolean running = false;
// or try this:
public static boolean running = false;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
if(running){
PrintWriter out = response.getWriter();
out.println("running");
return;
}
synchronized(Task.class){
if(!running){
running = true;
// run the task
running = false;
}
}
}
}

How do you to detect the end of a thread via ThreadId?

Talking Java Servlets here... I'm working on creating my own "Per Request Context" and I was looking to tie the "Per Request Context" object to the Thread.currentThread().getId() value.
Instead of passing around this context object everywhere I was planning on checking the current threadid when a user calls a function that is Per Request based and automatically getting the Context object out of a hashtable for that threadId.
I would use the code this like..
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
MyFramework.EnterContext();
try {
// do stuff here that leads to other classes on the same thread
// Access current context via static MyFramework.getCurrentContext()
}
finally { MyFramework.ExitContext(); }
}
However I would like to protect my application automatically from any potential user that does not call ExitContext(). In C# there is an event handler on the thread object for onexit...(think I wrong on this) is there some way to detect or poll when a thread exits? I'm currently storing only the threadId (long).
Any ideas?
unfortunatelly, there is no such feature built in for threads in Java. Besides, thread id is only guaranteed to be unique at any one time, but may be reused eventually when the thread dies (from the docs). however, the servlet framework that you are using may be implementing such feature (just a speculation).
i would recommend you implement a servlet filter, and tell your users to include it in their web.xml. with this you can be sure the client code always gets correctly wraped in your thread context.
A ThreadLocal seems to fit your use perfectly. A ThreadLocal object can provide a way to store a variable per thread. The internal workings of this class are very much of what you describe, it uses a map to give thread-local variables.
Something like this should do the trick:
private static final ThreadLocal<UserContext> userContext = new ThreadLocal<UserContext>();
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
MyFramework.EnterContext();
try {
UserContext context = userContext.get();
//if you used the set method in this thread earlier
//a thread local context would be returned using get
}
finally { MyFramework.ExitContext(); }
}
As for your other problem, you can use an observer pattern and notify when the thread completes its task.

in servlet I want to have a response.print() while another thread is running

I have a cumbersome object which has to work in background , I create a servlet which will call this object and for running the object I've implemented the Runnable interface inside my servlet like following :
public class myObject extends HttpServlet implements Runnable
{
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
res.print("<br/> running...");
res.flush(); //doens't help
Thread t = new Thread(this);
t.run();
}
public void run()
{
res.print("<br/> running...");
res.flush();//doesn't helper either
cumbersomeObject.workHard();
}
}
How can I print this simple line and then send 200 status to user and my servlet work in background happily ever after?
Change t.run() to t.start(), your thread is not running in background, but blocking in foreground. BTW how does this compile? How can run() access res variable?
However it looks like you are trying to send some data to a user via res response object from a thread. This won't work, see HttpServletResponse seems to periodically send prematurely for a detailed discussion.
You're making a fundamental mistake. The HTTP servlet request and response objects are tied to the current HTTP request thread. Once this thread finishes (i.e. when the HTTP request/response finished), then the associated HTTP servlet request and response objects are trashed and completely useless. So if you use those objects in a different thread after the initial HTTP request/response finishes, then you'll get exceptions in all colors because they point nowhere to.
Manually spawning new thread on a per-request basis is also a terribly bad idea. Threads are not cheap and definitely not unlimited available. Rather use a pool of 5~10 threads or something. If you have such a thread pool, then you could just submit a task to it, associate it with some unique key in the HTTP session or maybe even in a database along the logged-in user ID. You can then just poll in every subsequent request if the task is finished or not (i.e. it has stored the result there where you'd expect to see it).

Servlet seems to handle multiple concurrent browser requests synchronously

As far as I know Java Servlets are handling multiple requests concurrently and I've searched through StackOverflow as well as Google, and confirmed what I thought. However I am quite confused right now, I wrote a simple servlets that seem to show blocking behaviour.
so I have a simple Servlet:
public class MyServlet extends HttpServlet
{
private static final long serialVersionUID = 2628320200587071622L;
private static final Logger logger = Logger.getLogger(MyServlet.class);
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
logger.info("[doGet] Test before");
try {
Thread.sleep(60000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
logger.info("[doGet] Test after");
resp.setContentType("text/plain");
resp.getWriter().write("OK");
}
}
Then I have 2 browser windows, I opened at the same time that hit my Servlet.
And the result is the first request blocking the 2nd one. The log also shows:
10:49:05,088 [http-8383-Processor14] INFO MyServlet - [doGet] Test before
10:50:05,096 [http-8383-Processor14] INFO MyServlet - [doGet] Test after
10:50:05,106 [http-8383-Processor22] INFO MyServlet - [doGet] Test before
10:51:05,112 [http-8383-Processor22] INFO MyServlet - [doGet] Test after
I feel like I am missing something ... Servlets supposed to be able to handle concurrent request, but it doesnt seem to be doing it. I also did the same as above on the service method instead of doGet and it does the same thing.
Any pointers?
Thanks
Your browser is apparently using the same HTTP connection in different windows. The servlet container uses a single thread per HTTP connection, not per HTTP request. You should run two physically different webbrowsers to test this properly. E.g. one Firefox and one Chrome.

Categories