Multithreading a jsp? - java

I'm new to jersey, jsp's and web application development in general so hopefully this isn't a silly question. I've got a jsp and currently when the user hits a button on it, it starts a HTTP request which takes about 5-10 minutes to return. Once it finishes they're redirected to another page.
I'm wondering, is it possible or even advisable that I multithread the application so that the heavy processing will start but the user get's redirected to the next .jsp right away. If multithreading is not possible is there another method that you would recommend for dealing with heavy processing in a web application?

A JSP is basically a Servlet (it's translated in a Java Servlet Class and compiled). Teoretically you can start a new thread in a servlet (and hence in a JSP, via scriptlet), but that's really not advised for multiple reasons.
It'd be better recommended to make an asynchronous HTTP call via ajax, then, once the call is done immediately show something else to the user, and when the call back returns display the results.

Rather than create a new thread each time it might be more efficient to have a worker thread which continually polls a shared queue. Using, for example, ArrayBlockingQueue you web request can simple add an object to the queue and return to the user, and your worker thread (or repeating scheduled job) can take care of the heavy weight processing.

Instead of waiting for process to complete in a JSP, you can create a TimerTask (or Quartz Job) and set it for immediate execution and redirect user to some other page. Have that Job store the result in some central place that can be accessed by another JSP (in case you want to pull result of Job later, may be through ajax) Doing so, you save yourself from managing threads manually (which is error prone), you get async functionality, user does not need to see the blank browser screen for around 5-10 minutes.

It is possible.
Create a thread, store its reference somewhere that is available everywhere (a static Map) and store its key (in the session, in the code of the JSP's answer).
Following calls can retrieve the thread and check its state/results.
Anyway, use with care:
a) You will need to control that old results are deleted. It is inevitable that sometimes the browser will close, so you need a Watchdog to clear data obviously no longer needed.
b) The user are not used to this kind of behavior. There is a serious risk that they will just "go back" and try to launch the thread again, and again, and again. Try to control it (ideally the id of the thread will be linked to the user, so as long as an older thread is active an user cannot launch another one).

Related

How to get the Thread response before page get rendered

I have an application which require File Operation , that need to be done as concurrently
If a user try to READ a file , other users cant perform WRITE operation
If a user try to WRITE to file , other user cant perform READ Operation
business logic applied :
Created Thread using Runnable Interface and added Synchronized READ Methods to read property file from remote location and put it into session /request object
issue : while starting a new thread the response get finished (since thread is independent path of execution) .so the property values are not available
How to get the thread response before the page get displayed ? I heared that we can use Callable Interface , please share the best approach suited in this situation.
Making a thread in servlet in this way(initiate a Runnable and run it by JVM directly) is completely non-sense and not recommended for sake of memory leak, and unmanaged context.
It's completely nature you get undefined/nonstable states of request/session context by the new thread.
Since the thread gets started asynchronously, the servlet/server context continue its working and response to the client, and the request context is no more valid.
You may do it by a mutex, since the servlet context is multi-threaded by default, and you may not never and never run threads that way please, and if you do, you may do it by session context listeners to handle events and prevent any possible memory leak.
You may either wait(block) the response while the related context(file) is locked, which is not so logical. Or inform the user the requested file is being locked becasue of another read/write operation.
And of course you need a push like method(like websockets) or alternatives(check status by ajax or reloading) to check the latest related context status.
And the most logical way is, you need to do it in queue mode, and just make sure the part of the file need to be changed is valid with latest state.

Handling asynchronous saving with the possibility of time-critical errors?

So, to explain this, I'll start out by going through the application stack.
The system is running JSP with jQuery on top, talking through a controller layer with a service layer, which in turn utilizes a persistence layer implemented in Hibernate.
Now, traditionally, errors like having overlapping contracts has been handled through throwing exceptions up through the layers until they're translated into an error message for the user.
Now I have an object that at any given time can only be tied to one contract. At the moment, when I save a contract, I look at all of these objects and check if they're already covered by an existing contract. However, since multiple clients can be saving at any given time, this introduces the risk of getting past the check on two separate contracts, leading to one object being tied to two contracts at the same time.
To combat this, the idea was to use a queue, put objects into the queue from the main thread, and then have a separate thread take them out one by one, saving them.
However, here's the problem. For one, I would like the user to know that the saving is currently happening, for another, if by accident the scenario before happens, and two contracts with the same object covering the same time is in the queue, the second one will fail, and this needs to be sent back to the user.
My initial attempt was to keep data fields on the object put into the queue, and then check against those in a blocking wait, and then throw an exception or report success based on what happens. That deadlocked the system completely.
Anyone able to point me in the right direction with regards to techniques and patterns I should be using for this?
I can't really tell why you have a deadlock without seeing your code. I can think of some other options though:
Poll the thread to see its state (not as good).
Use some kind of eventing system. You would have an event listener (OverlappingContractEventListener perhaps) and then you would trigger the event from the thread when the scenario happens. The event handler would need to persist this information somehow.
If you are going for this approach, then on the client side you will need to poll.
You can poll a specific controller (using setInterval and AJAX) that looks up the corresponding information for the object to see what state its in. This information should have been persisted by your event listener.
You can use web workers (this is supported in Chrome, Firefox, Safari, and Opera. IE will support it in 10) and perform the polling in the background.
There is one other way that doesn't involve eventing. It depends on you figuring out the source of your deadlock though. Once you fix the source of your deadlock you can do one of two things:
Perform an AJAX call to the controller. The controller will wait for the service to return information. The code to issue feedback to the user will be inside the success handler of your controller.
Use a web worker to perform the call in the background. The web worker would also perform an AJAX call and wait for the response.
Shouldn't you be doing the check for duplicate contracts in the database? Depending on the case, you can do this with a constraint, trigger, o stored procedure. If it fails, send an exception up the stack. That's normally the way to handle things like this. You can then catch the exception in jQuery and display an error:
jQuery Ajax error handling, show custom exception messages
Hope this helps.

Exchange data in real time over AJAX with multiple threads

I am developing an application in JSF 2.0 and I would like to have a multiline textbox which displays output data which is being read (line by line) from a file in real time.
So the goal is to have a page with a button on it that triggers the backend to start reading from the file and then displaying the results as it's reading in the textbox.
I had thought about doing this in the following way:
Have the local page keep track of what lines it has retrieved/displayed in the textbox so far.
Periodically the local page will poll the backend using AJAX and request any new data that has been read (tell it what lines the page has so far and only retrieve the new lines since then).
This will continue until the entire file has been completely retrieved.
The issue is that the bean method that reads from the file is running a while loop that blocks. So to read from the data structure it is writing to at the same time will require using additional Threads, correct? I hear that spawning new Threads in a web application is a potentially dangerous move and that Thread pools should be used, etc.
Can anyone shed some insight on this?
Update: I tried a couple of different things with no luck. But I did manage to get it working by spawning a separate Thread to run my blocking loop while the main thread could be used to read from it whenever an AJAX request is processed. Is there a good library I could use to do something similar to this that still gives JSF some lifecycle control over this Thread?
Have you considered implementing the Future interface (included in Java5+ Concurrency API)? Basically, as you read in the file, you could split it into sections and simply create a new Future object (for each section). Then you can have the object return once the computation has completed.
This way you prevent having to access the structure while it is still being manipulated by the loop and you also split the operations into smaller computations reducing the amount of time locking occurs (total lock time might be greater but you get faster response to other areas). If you maintain the order in which your Future objects were created then you don't need to track line #'s. Note that calling Future.get() does block until the object is 'ready'.
The rest of you're approach would be similar - make the Ajax call to get content of all 'ready' Future objects from a FIFO queue.
I think I understand what you're trying to accomplish.. maybe a bit more info would help.

Threading in Servlets

I am working on a servlet that can take a few hours to complete the request. However, the client calling the servlet is only interested in knowing whether the request has been received by the servlet or not. The client doesn't want to wait hours before it gets any kind of response from the servlet. Also since calling the servlet is a blocking call, the client cannot proceed until it receives the response from the servlet.
To avoid this, I am thinking of actually launching a new thread in the servlet code. The thread launched by the servlet will do the time consuming processing allowing the servlet to return a response to the client very quickly. But I am not sure if this an acceptable way of working around the blocking nature of servlet calls. I have looked into NIO but it seems like it is not something that is guaranteed to work in any servlet container as the servlet container has be NIO based also.
What you need is a job scheduler because they give assurance that a job will be finished, even in case a server is restarted.
Take a look at java OSS job schedulers, most notably Quartz.
Your solution is correct, but creating threads in enterprise applications is considered a bad practice. Better use a thread pool or JMS queue.
You have to take into account what should happen server goes down during processing, how to react when multiple requests (think: hundreds or even thousands) occur at the same time, etc. So you have chosen the right direction, but it is a bit more complicated.
A thread isn't bad but I recommend throwing this off to an executor pool as a task. Better yet a long running work manager. It's not a bad practice to return quickly like you plan. I would recommend providing some sort of user feedback indicating where the user can find information about the long running job. So:
Create a job representing the work task with a unique ID
Send the job to your background handler object (that contains an executor)
Build a url for the unique job id.
Return a page describing where they can get the result
The page with the result will have to coordinate with this background job manager. While it's computing you can have this page describe the progress. When its done the page can display the results of the long running job.

Is it ok to store a Thread object in a session or application attribute?

I'm not sure if I'm on the right track, but I have previously created a Thread and stored it in the current session to be able to use it in other Servlets.
When a user logs in, I need a Thread that will periodically poll a webservices server and retrieve updates. When the user logs out I want to stop/pause the Thread.
If I create the Thread when the user logs in, I need a reference to this Thread if I want to pause it when the user is logged out, and then start it again when they login.
What is the best and correct way to go about this? Should I monitor the session from inside the Thread and if the user has logged out, have the thread return in order to end the Thread?
Then next time the user logs in, I can create a new background Thread?
***I need the thread to run in the background and poll a web services server for updates which I use to update my database. It may poll once every 5 minutes.
I don't want it to be polling all the time, hence why I was trying to control it based on the user being logged in or not... I was setting the boolean running to false when they log out in order to stop the thread. Because the thread was stored in the application context, I could then set running to true when they logged back in.
What about a Thread to run in the background and check something, for example that your internet is up?
I know how to create the Thread, but I'm confused about how to terminate it, since it needs to be continually running in the background.
Am I using threads for the wrong thing? should I be using something else?
Thanks again, hopefully this is a better explanation...
Since servlets themselves will be instantiated multiple times at the same time, creating even more threads is not a wise idea. You will run into problems if you decide to cluster your application one day across multiple machines because of serialization issues, so you're locking yourself at the beginning.
Besides, it seems your problem can be done using AJAX pooling from client side. Why pool a webservices server and retrieve updates if you can't show them to your client without them refreshing the entire page?
Think of this scenario: if a user sessions lasts for 30 minutes, and a user doesn't log out, but just closes the browser window: you won't know that this happened, and you would pool for next 30 minutes that webservice, which is a waste of resources.
A Thread is not serializable, so storing it in a session is likely to be problematic.
Also, stopping or pausing a thread can be problematic unless you code the thread's Runnable to periodically check to see if it has been paused / stopped and act accordingly. (The Thread.stop() and Thread.pause() methods are deprecated and you should avoid using them. They can potentially destabilize your JVM.)
Even if you address the above issues, there are a host of resource management issues to be addressed.
I'm not sure if I'm on the right track
In short, you are not, IMO.
You have not explained why you need to associate a thread with each session, or what these threads are intended for. If you did, you would get some good suggestions for alternative approaches that (largely) avoid the problems above.
FOLLOWUP
I wasn't using .stop and .pause.
Good.
i was using a boolean "runnable" to control the thread.
That's one alternative. I prefer to use the Thread.interrupt() mechanism, because it allows you to interrupt a thread that is blocked on an I/O operation or in a wait(...) call to stop.
What if you are polling a device, and need to access returned data? What is the best approach?
Probably, the best approach is to create a thread or thread pool in servlet initialization that is responsible for polling the device(s). If you need to save the returned data so that it can be accessed in a subsequent HTTP request, put it into (say) a queue that the request controller can access. You may need some infrastructure to remove uncollected data objects from the queue after a certain period, etc.
You really shouldn't be creating Threads inside containers at all. What's it for?
And if it's for use by other servlets it's more likely to belong in the application attributes, not the session attributes, isn't it? or are you really creating a thread per user? which you really don't want to do.
I can see, that there may be valid reasons to do the polling server side in a background thread: For example it may take longer than a user wants to wait for the answer of a request. And there is the issue that some anti-discrimination laws (to be more precise the guidelines on how to interpret those laws) deny the use of JavaScript, so no Ajax.
So if there is really no other way, I suggest to create one thread (or a very small thread pool) in Servlet.init(). This single (or small number of threads) should do the polling for all active users. In web.xml you can define a session listener so you can keep track of opened and closed/expired sessions.
Make sure to signal in Servlet.destroy() that the thread(s) should exist.
To define a session live cycle listener add this in web.xml:
<listener>
<listener-class>
com.example.SessionListener
</listener-class>
</listener>
And then remember the open sessions, so that you can iterate over them in the background thread.
public class SessionListener implements HttpSessionListener {
private Set<HttpSession> sessions = Collections.synchronizedCollections(
new HashSet<HttpSession>());
public void sessionCreated(HttpSessionEvent sessionEvent) {
HttpSession session = sessionEvent.getSession();
sessions.add(session;
}
public synchronized void sessionDestroyed(HttpSessionEvent sessionEvent) {
HttpSession session = sessionEvent.getSession();
sessions.remove(session);
}
}

Categories

Resources