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.
Related
I need to run some time-consuming task from a controller. To do it I have implemented an #Async method in my service so that the controller can return immediately (for example with 202 Created status).
The problem is that the task need access to some session-scoped beans. With this approach I am getting org.springframework.beans.factory.BeanCreationException: Error creating bean with name (...): Scope 'session' is not active for the current thread (...).
The same result is when I manually create an ExecutionService instead of #Async.
Is it possible to somehow make a worker thread attached to the current session?
EDIT
The purpose is to implement a bulk operation, providing a way to monitor the status of processing. Something like described in this answer: https://stackoverflow.com/a/28787774/718590
If I run it synchronously, there will be no indication of the status (how many items processed), and a request timeout may occur.
If I correctly understand, you want to be able to start a long time asynchronous processing from a spring web application, and be able to follow advancement of processing from the session that started it. And the processing could use beans contained in the session.
For a good separation of concerns, I would never have an asynchronous thread know a session. The session is related to HTTP and can be destroyed at any time before the thread can finish (or even begin in race conditions) its processing.
IMHO, a correct design would be to create a class containing all the informations shared between the web part and the asynchronous processing : the status (whatever it can be), the user that started processing if is is relevant and every other relevant piece of information. In your controller (of preferently in the service method called by the controller) you prepare an object of that class, and pass it to the #Async method. Then before returning, the controller stores the object in session. That way :
the asynchronous processing has all its required information, even is the session is destroyed later. It does not need to know the session and only cares for its processing and updates its status
the session of the web application knows that the asynchronous processing is running, know how it was started and what is the current status
It can be adapted to your real problem, but this should meet your requirements.
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.
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).
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);
}
}
Are the threadlocals variables global to all the requests made to the servlet that owns the variables?
I am using resin for the server.
Thanks for awnser.
I think I can make my self more clear.
The specific Case:
I want to:
initialize a static variable when the request starts the execution.
be able to query the value of the variable in the further executions of methods called from the servlet in a thread safety way until the request ends the execution
Short answer: Yes.
A bit longer one: This is how Spring does its magic. See RequestContextHolder (via DocJar).
Caution is needed though - you have to know when to invalidate the ThreadLocal, how to defer to other threads and how (not) to get tangled with a non-threadlocal context.
Or you could just use Spring...
I think they are global to all requests made with that specific thread only. Other threads get other copies of the thread-local data. This is the key point of thread-local storage:
http://en.wikipedia.org/wiki/Thread-local_storage#Java.
Unless you check the appropriate option in the servlets config, the servlet container will use your servlet with multiple threads to handle requests in parallel. So effectively you would have separate data for each thread that's up serving clients.
If your WebApplication isn't distributed (runs on multiple Java Virtual Machines), you can use the ServletContext object to store shared data across requests and threads (be sure to do proper locking then).
Like Adiel says, the proper way to do this is probably to use the request context (i.e. HttpServletRequest), not to create a ThreadLocal. While it's certainly possible to use a ThreadLocal here, you have to be careful to clean up your thread if you do that, since otherwise the next request that gets the thread will see the value associated with the previous request. (When the first request is done with the thread, the thread will go back into the pool and so the next request will see it.) No reason to have to manage that kind of thing when the request context exists for precisely this purpose.
Using ThreadLocal to store request scoped information has the potential to break if you use Servlet 3.0 Suspendable requests (or Jetty Continuations)
Using those API's multiple threads process a single request.
Threadlocal variables are always defined to be accessed globally, since the point is to transparently pass information around a system that can be accessed anywhere. The value of the variable is bound to the thread on which it is set, so even though the variable is global, it can have different values depending on the thread from which it is accessed.
A simple example would be to assign a user identity string to a thread in a thread local variable when the request is received in the servlet. Anywhere along the processing chain of that request (assuming it is on the same thread in the same VM), the identity can be retrieved by accessing this global variable. It would also be important to remove this value when the request is processed, since the thread will be put back in a thread pool.