views:

1547

answers:

4

I have a servlet S which handles callbacks from a 3rd party site.

The callback invocations happen in a specific order. Thus, I need to queue them.

I propose to use an in-memory queue like

java.util.ConcurrentLinkedQueue

So the logic looks like this:

  • Servlet S receives a callback & queues the received item into queue Q.
  • By this time, the thread that hosted an instance of servlet S would have terminated.
  • A consumer thread reads from Q and processes each one serially.

As I understand it, each instance of Servlet S is executed in its own Thread.

How do I create a single Consumer Thread for the whole webapp (war) that will service a Queue ? Basically I need singleton instances of:

  1. Threadpool
  2. ConcurrentLinkedQueue
+1  A: 

Remember that while your servlets are in seperate threads, they're in the same VM instance, so they're living in a shared memory space. If you create a Singleton instance, it will automagically be shared by all the servlets. You can also create a separate servlet to act as your shared data, which has the advantage that you can use container services to persist it if you want.

There's a thorough examination of ways of doing this --- technically called "servlet collaboration" --- in the OReilly book on servlet programming, available online here.

Charlie Martin
I don't like Singletons.
ashitaka
Sorry to hear it.
Charlie Martin
+1  A: 

Oh, one other thought: the one thing you DO NOT WANT TO DO is to try managing your own thread pools inside a servlet container; it can do thread pooling a lot better than you can, UNLESS you mess with it.

Charlie Martin
Yes Tomcat/jetty will have threadpools for executing servlets. I'm not sure if it has threadpools for custom user Runnables.
ashitaka
It doesn't, but the point is that you shouldn't even try using your own threads or threadpools inside a servlet; use another servlet and let the container manage it. Otherwise you're liable to bugger things for yourself and anyone sharing the container.
Charlie Martin
+3  A: 

This isn't the sort of thing a servlet container is for. You really need a more full-blown J2EE application server if you're going to use a standards-based approach. What you're going to have are hacks otherwise but they might be sufficient for your task.

What I would probably try is creating a DaemonServlet. This is just a normal servlet that is not mapped to a URL (except, perhaps, a blind URL for monitoring purposes, although prefer JMX for this kind of thing). The init() method is called when the servlet is loaded. You could start a thread in that. Arguably you may need to create two: one that does the work. The other makes sure the first one is running and gracefully terminates it once destroy() is called.

Alternatively, if you're using Spring (and, let's face of it, what kind of whacko doesn't use Spring?), you could simply create a bean in the application context that does much the same thing, except with Spring lifecycle events (eg afterPropertiesSet() on InitializingBean).

Actually, I have an even better suggestion. Use asynchronous message consumers, which will be a lot cleaner and more scalable but this is predicated on a JMS-based solution, rather than just a LinkedBlockingQueue (and JMS is probably a better idea anyway). Depending on your constraints, you may not have JMS available as an option however.

cletus
I don't use Spring, but Guice (So I'm a whacko unfortunately). Yes I've been mulling about integrating ActiveMQ. That is one of the upcoming priorities. I prefer *NOT* to use a J2EE appserver.
ashitaka
But you're not alone, Whacko. That's why JEE appeared: hardly anyone really needs a full J2EE infrastructure.
Charlie Martin
A: 

I second the comment that says managing your own thread pool is a bad idea.

Servlets are for handling HTTP requests. HTTP is a synchronous request/response protocol. The logic for how they're handled belongs somewhere else. That handler may be synchronous or asynchronous, but that should be up to the handler implementation. The servlet should decide which handler to defer to for a given response and that's it.

Even if you use Tomcat or a servlet/JSP engine, you can still use Spring, JMS, and MDPs by adding ActiveMQ to your Tomcat implementation.

duffymo