This week's book giveaway is in the OCAJP 8 forum. We're giving away four copies of OCA Java SE 8 Programmer I Study Guide and have Edward Finegan & Robert Liguori on-line! See this thread for details.
Suppose I wanted to trigger some process from a website. This process might take 10 minutes. I want to avoid having the screen hang for five or ten minutes. Also, I want the user to be able to keep navigating the rest of the site. I would, however, like the user to be able to check the progress at a certain screen. My first thought would be to just have an actionListener or action start a separate thread which does the processing. However, I was told this would be an unmanaged thread.
I guess my main two questions are, "What are the dangers of an unmanaged thread?" and "What is the right way to do this?"
Running background processes is not exactly a JSF related problem, I think. JSF is "just" for creating user interfaces. That said, JSF is part of Java EE, which is a full blown enterprise framework. I have not much experience with background processing on Java EE. However, I can give you some hints that may help you get started:
You should never create Threads in Java EE code. The enterprise container manages the server processes; by manually creating Threads, you interfere with this. What are the risks? Your Thread might "eat up" all CPU time, resulting in a not responding server. Or the opposite can occur: your Thread doesn't get any CPU time.
Things that happen in the background, are usually performed by Enterprise JavaBeans (EJBs). You should take a look at EJB 3. Perhaps your problem can be solved by using Message Driven Beans (MDBs).
If the EJB standard doesn't provide what you need, you can have a look at Quartz, an "Enterprise Job Scheduler". I recently came across this project, I have no experience with it, so I can't tell if it works.
A lot of projects use a "lightweight" server that only has a Web Container. (This is the case if you're using Tomcat.) A web container is not a full blown Java EE server and therefore doesn't have EJB services. The best solution is to upgrade to a full blown Java EE server. (There are good open source Java EE servers, GlassFish is a good example.) But if that isn't an option, you could choose a less elegant solution by implementing a special Servlet for executing your tasks.
There's nothing special about JSF in this regard. But Bart is correct. If you spawn a thread in an HTTP action processor (and that includes JSF code), it will do one of 2 things:
1. It will lock up resources and make the HTTP service thread non-recyclable for the duration of the process. Which would eventually exhaust the service thread pool if you start stacking these things up.
2. the HTTP service may terminate its child threads when the service completes and the thread gets returned to the pool. Which would kill whatever you're trying to do
My traditional solution for this is to create what I call a "null servlet", which is simply a servlet that starts up automatically when the webapp starts, executes an init method, and has no HTTP request handlers in it. The init method constructs an engine processor which generally has a work queue. Web requests that need long-duration work done post requests to this queue. The engine normally includes status and control methods so that later requests can monitor and control the long-running process.
IMPORTANT If you use this approach, make sure you allow for server shutdown. Otherwise the appserver will hang indefinitely, since only when all child threads are terminated will the server itself be allowed to terminate. That generally means you should have a master cancel method for the engine, and typically you'd invoke it from the null servlet's destroy() method.
Also note that the init method MUST not itself attempt to be the engine, since the webapp won't finish starting until after you're returned from init(). It's OK, however for the init method to set up an environment containing child threads, as long as you remember the warning I just gave.
I have this nagging feeling that newer versions of J2EE have a slightly cleaner way of doing this, but I can't remember what it is, and this is a reliable and protable process that I've used for years.
EJBs are forbidden per the spec from spawning threads. Session and Entity EJBs should not contain long-running processes, since their methods are typically serialized and beans cannot be returned to their pools while they're processing. Message-driven EJBs have some applicability, since they can queue up work, but read the instructions carefully.
An IDE is no substitute for an Intelligent Developer.