I'm writing a JEE7/Glassfish 4 application that reads data from an external queue (RabbitMQ) and processes it. It needs a method (I suppose an EJB method) that contains a loop that never exits that reads the queue. I suppose since this loop never exits, it needs to be on a separate thread. My question is, what is the correct way to do this in a JEE7 application?
This may be obvious, but the ReadQueue() method needs to start automatically when the app starts and must keep running permanently.
Is the ManagedExecutorService appropriate for this?
ManagedExecutorService is exactly what you want to use for this.
The availability of this service in JEE is a great benefit. In the past, we basically just ignored the guidelines and managed all of this stuff ourselves.
The MES allows you to capture the context information of the invoking component, and tie your task in to the life cycle of the container. These are both very important in the JEE environment.
As to where to start the task, you basically have two options.
One, you can use a ServletContextListener, and have that kick off the task during container startup.
Two, you can use an #Singleton EJB, and tie in to its lifecycle methods to start your task.
If you start the task up from the ServletContextListener, then the task will run as if it's in the WAR environment. If you start it up from the #Singleton, it will run within the Session Beans environment (this mostly relates to how the JNDI appears).
Either way, you only need to worry about starting the task via these mechanisms. You should rely on the ManagedTaskListener.taskAborted interface method to shut your task down.
In theory you can work with the Thread.interrupt that is sent to your task during shut down. I've never had good luck with that myself, I rely on an external mechanism to tell the long running tasks to shut off.
I wish I could give first hand experience with this new facility, but I haven't had an opportunity to try it out yet. But from the spec, this is what you want to do.
To start a thread with an infinite loop that polls the queue periodically is usually not a good idea. The nature of queues suggests an async, event-driven processing. For such problems in the JEE world you have MDBs. The only issue here is that MDB requires a JMS queue provider but RabbitMQ is using a different protocol (AMQP). You need a JMS-AMQP bridge to make this work. Could be Qpid JMS but no guarantee that it will work.
Here is one way to create a thread that never exits:
public class HelloRunnable implements Runnable {
public void run() {
while (true) {
// do ReadQueue() here
}
}
public static void main(String args[]) {
(new Thread(new HelloRunnable())).start();
}
}
Related
I'm thinking how to write a signal handler that would inform the main thread about the need to exit.
What I'm thinking is:
1) use the following code to intercept the signal
SignalHandler handler = new SignalHandler () {
public void handle(Signal sig) {
System.out.println("Signal " + sig);
System.out.println("Shutting down...");
ServiceLocator.ProgramState().setMustExit();
System.exit(0);
}
};
Signal.handle(new Signal("INT"), handler);
Signal.handle(new Signal("TERM"), handler);
2) Set a ProgramState object to indicate the need to exit: ServiceLocator.ProgramState().setMustExit();
3) put the following code in some parts of the program to check if ProgramState tells me to exit:
if (ServiceLocator.ProgramState().mustExit()) {
throw new MustExitException();
}
the exception would be intecepted by the main thread which would exit cleanly.
I don't like very much throwing an exception like I'm going to do, but this seems a quick way to achieve my goal.
Are there any other ways to exit gracefully?
The main thread usually waits for some event/notification (either directly or indirectly) that prevents it from terminating the program immediately
A clean shutdown would be letting the main thread know it's time to "move-on" either by interrupting it or by notifying it. As part of path to end the program execution beyond that point, it should take care of "terminating" other crucial parts of the program (in most of the cases, there aren't any).
If the application is single threaded... well it probably shouldn't be. The core execution logic should be separated from the main thread.
Spring IOC / Guice (Netflix governator) exist especially to achieve better life cycle-control over your object-graph.
Both can aid you in building an implementation where the bootstrap/shutdown/component wiring is decoupled from the actual logic of the application and provide convenient way of managing the life-cycle of your various objects/classes.
I wholeheartedly recommend that you'll use them instead of rolling your own shutdown mechanism. (Keeping the signal handling functionality, of course, but that should also be decoupled from the main thread). You'll eventually wind up with a poison-pill like mechanism.
For example - if you choose to work with Spring, you'll define the signal handler as a bean, inject/autowire it with the ConfigurableApplicationContext instance, and call its close() method upon receiving the desired signal. That'll cause all spring wired beans to perform their defined (if defined) shutdown/destruction behavior
P.S. signal handling will work, but there are more concrete ways to convey shutdown messages (see ZeroMq/JeroMQ, for a brokerless message example) from external sources.
What's the recommended way of starting a thread from a servlet?
Example: One user posts a new chat message to a game room. I want to send a push notification to all other players connected to the room, but it doesn't have to happen synchronously. Something like:
public MyChatServlet extends HttpServlet {
protected void doPost(HttpServletRequest request,
HttpServletResponse response)
{
// Update the database with the new chat message.
final String msg = ...;
putMsgInDatabaseForGameroom(msg);
// Now spawn a thread which will deal with communicating
// with apple's apns service, this can be done async.
new Thread() {
public void run() {
talkToApple(msg);
someOtherUnimportantStuff(msg);
}
}.start();
// We can send a reply back to the caller now.
// ...
}
}
I'm using Jetty, but I don't know if the web container really matters in this case.
Thanks
What's the recommended way of starting a thread from a servlet?
You should be very careful when writing the threading program in servlet.
Because it may causes errors (like memory leaks or missing synchronization) can cause bugs that are very hard to reproduce,
or bring down the whole server.
You can start the thread by using start() method.
As per my knowledge , I would recommend startAsync (servlet 3.0).
I got some helpful link for you Click.
but I don't know if the web container really matters in this case.
Yes it matters.Most webservers (Java and otherwise, including JBoss) follow a "one thread per request" model, i.e. each HTTP request is fully processed by exactly one thread.
This thread will often spend most of the time waiting for things like DB requests. The web container will create new threads as necessary.
Hope it will help you.
I would use a ThreadPoolExecutor and submit the tasks to it. The executor can be configured with a fixed/varying number of threads, and with a work queue that can be bounded or not.
The advantages:
The total number of threads (as well as the queue size) can be bounded, so you have good control on resource consumption.
Threads are pooled, eliminating the overhead of thread starting per request
You can choose a task rejection policy (Occurs when the pool is at full capacity)
You can easily monitor the load on the pool
The executor mechanism supports convenient ways of tracking the asynchronous operation (using Future)
In general that is the way. You can start any thread anywhere in a servlet web application.
But in particulary, you should protect your JVM from starting too much threads on any HTTP request. Someone may request a lot ( or very very much ) and propably at some point your JVM will stop with out of memory or something similiar.
So better choice is to use one of the queues found in the java.util.concurrent package.
One option would be to use ExecutorService and it's implementations like ThreadPoolExecutor
, to re-use the pooled threads thus reducing the creation overhead.
You can use also JMS for queuing you tasks to be executed later.
Is a typical J2ee web application or any web app built on top java is multi threaded application , so every time i write some code i have to keep race condition or concurrent modification in mind ?
Is a typical J2ee web application or any web app built on top java is multi threaded application?
Yes, it is. But the application server (Tomcat, JBoss, WebSphere, etc.) handles the threads and resources for you, so you may not worry about race condition or concurrent modification.
When you should worry about concurrent modification? For example, if you happen to create a field in a Servlet and you update this field on every request (doPost or doGet method of the servlet), then two users in their pcs could perform the request on the same URL at the same time, and this field will have an unexpected value. This is covered here: How do servlets work? Instantiation, sessions, shared variables and multithreading, Threadsafety section of the accepted answer. Note that having a design like this is a bad practice.
Another case may be you firing new threads and resources shared among this threads by your own. It is not a good practice nor a bad practice, it is kind of you must understand the risk you're taking and assume the consequences. This means, you can have a Servlet and fire threads on your own, but it's up to you to handle this in the right way. Note that you should evaluate if you really need to fire and handle threads in your Java EE application or if you could use another approach like firing JMS messages that will handle multiple requests in parallel and asynchronously.
#AndreiI noted in his/her answer that EJB prohibits using threads, but this means that you cannot manage threads inside an EJB, nor by creating a new instance of Thread nor by using ExecutorService or any other. In code:
#Stateless
public class FooEJB {
public void bar() {
//this is not allowed!
Thread t = new Thread(new Runnable() {
//implementation of runnable
});
t.start();
}
public void baz() {
//this is not allowed either!
final int numberOfThreads = ...;
ExecutorService es = Executors.newFixedThreadPool(numberOfThreads);
es.execute(new Runnable() { ... });
es.shutdown();
}
}
Like almost any framework in Java (server applications, inclusive Web frameworks or GUI applications based on AWT or Swing), Java EE is multi-threaded. But the answer to your question is no: you do not have to care about race condition or concurrent modification. Of course you are not allowed to make some errors (like sharing Servlet variables), but in a typical application you do not care about such things. For example the EJB specification prohibits using threads, but it has a mechanism for asynchronous jobs. Excerpt from the EJB specification:
The enterprise bean must not attempt to manage threads. The enterprise
bean must not attempt to start, stop, suspend, or resume a thread, or
to change a thread’s priority or name. The enterprise bean must not
attempt to manage thread groups.
Also the most used interface in the JPA specification (EntityManager) is not thread safe, although others are.
In a Java EE application container the Server takes care of the threading for you. Typically it creates one thread per request. However using Spring or EJB you can declare different scopes to your threads. So, you should not have to directly manage threads in a JavaEE application.
I have a spring bean with 4 blocking queues. Each queue is assigned a method (named processQueueX() ) which calls take() on that queue and processes taken object from queue.
I want to call each of those method in a separate thread on app startup.
I tried with task scheduler and fixed-delay setting but that in some way blocks tomcat and it stops responding to requests. Each method needs to be called once, so scheduling was a bad idea I guess.
Init method does not work also since it works in a single thread, each method has endless loop to process queue forever.
Is there a way to call these methods declaratively from spring config file in manner similar to task namespace? Or programmatically?
Tnx
I think using scheduler not a bad idea use quart scheduler with simple trigger thus quarz will do threading for you and tomcat not effected .And configure quartz with just enough number of thread.
Would 23.4. The Spring TaskExecutor abstraction help?
Where the example has a MessagePrinterTask class, you would have similar, but your run() method would access one of the queues. You would set up your Spring config to inject one of the queues into the task, so depending on how similar your queues are, you might be able to use the same Runnable task.
in a Spring MVC Controller I would like to start a thread that continues work while my controller sends the response. Will this work with spring-mvc ?
Best Reagrds,
Heinrich
Yes, You can start new Thread in Controller. But better way of doing asynchronous job is to use spring-scheduling support. You can leverage Quartz framework. That will manage your job.
This link will give you how to integrate this in your application.
Yes, it'll work. On one web app I worked on, I needed to send a notification email depending on the user's action. I added a post-commit interceptor on the service, and had that fire off the email in a separate thread. (In my case that happened to be cleaner than putting the code in the controller, because I only wanted it to happen if the transaction committed.)
You do need to make sure the thread actually stops running at some point, either by setting daemon to true (if it's ok that stopping the server kills the thread without notice) or making sure the code in its run method will always terminate at some point.
You are better off using a threadpool than creating new threads, so you don't risk resource exhaustion (threads stalling out are usually not independent events, if a thread hangs the next one probably will too, so you need a way to cut your losses). Methods annotated with #Async will be executed using an executor that you can configure as shown in the Spring documentation.
As the others mentioned, it's will work. ExecutorService can do the job. Here you can see I used it for starting a video stream that sits on a separate endpoint.
#PostMapping("/capture")
public ResponseEntity capture() {
// some code omitted
ExecutorService service = Executors.newCachedThreadPool();
service.submit(() -> startStreaming(deviceConfig));
return return ResponseEntity.ok()
.body(stream);
}