tags:

views:

629

answers:

8

Hi,

we have a web application that does various things and sometimes emails users depending on a given action. I want to decouple the http request threads from actually sending the email in case there is some trouble with the SMTP server or a backlog. In the past I've used JMS for this and had no problem with it. However at the moment for the web app we're doing JMS just feels a bit of an over kill right now (in terms of setup etc) and I was wondering what other alternative there are out there. Ideally I just like something that I can run in-process (JVM/Tomcat), but when the servlet context is unloaded any pending items in the queue would be swapped to disk/db. I could of course just code something together involving an in memory Q, but I'm looking to gain the benfit of opensource projects, so wondering whats out there if anything.

If JMS really is the answer anyone know of somethign that could fit our simple requirements. thanks

A: 

I agree that JMS is overkill for this.

You can just send the e-mail in a separate thread (i.e. separate from the request handling thread). The only thing to be careful about is that if your app gets any kind of traffic at all, you may want to use a thread pool to avoid resource depletion issues. The java.util.concurrent package has some nice stuff for thread pools.

Willie Wheeler
last time I looked, the use application-created threads was considered non-portable, since different servlet containers might limit the creation of Thread instances.
toolkit
I believe that thread creation happens through the SecurityManager, which the admin can configure as desired.
Willie Wheeler
+1  A: 

You could use a scheduler. Have a look at Quartz.

The idea is that you schedule a job to start at regular intervals. All requests need to be persisted somewhere. The scheduled job will read them and process them. You need to define the interval between two subsequent jobs to fit your needs.

This is the recommended way of doing things. Full-fledged application servers offer JEE Timers for this, but these aren't available in Tomcat. Quartz is fine though and you could avoid starting your own threads, which will cause mess in some situations (e.g. in application updates).

kgiannakakis
A: 

We have the exact same problem. This may sound a little simplistic but it does work:

  1. Write the request to disk to an "outgoing" mail folder.
  2. Email process reads in the request.
  3. When the message has been sent, the outgoing mail message is deleted.
  4. Plan is to use Amazon S3 as needed to help distribute the message transmission across servers if needed.
Pat
+1  A: 

I'm using JMS for something similar. Our reasons for using JMS:

  • We already had a JMS server for something else (so it was just adding a new queue)
  • We wanted our application be decoupled from the processing process, so errors on either side would stay on their side
  • The app could drop the message in a queue, commit, and go on. No need to worry about how to persist the messages, how to start over after a crash, etc. JMS does all that for you.
Aaron Digulla
+2  A: 

Wow, this issue comes up a lot. CommonJ WorkManagager is what you are looking for. A Tomcat implementation can be found here. It allows you to safely create threads in a JEE environment but is much lighter weight than using JMS (which will obviously work as well).

Robin
A: 

Since you say the app "sometimes" emails users it doesn't sound like you're talking about a high volume of mail. A quick and dirty solution would be to just Runtime.getRuntime().exec():

sendmail [email protected]

and dump the message into the resulting Process's getOutputStream(). After that it's sendmail's problem.

Figure a minute to see if you have sendmail available on the server, about fifteen minutes to throw together a test if you do, and nothing to install assuming you found sendmail. A few more minutes to construct the email headers properly (easy - here are some examples) and you're done.

Hope this helps...

Marty Lamb
A: 

I would think spring integration would work in this case as well.

http://www.springsource.org/spring-integration

J. Scarbrough
A: 

Beyond JMS, for short messages you could also use Amazon Simple Queue Service (SQS). While you might think it an overkill too, consider the fact there's minimal maintenance required, scales nicely, has ultra-high availability, and doesn't cost all that much. No cost for creating new queues etc; or having account. As far as I recall, it's purely based on number of operations you do (sending messages, polling/retrieving).

Main limitation really is the message size (there are others, like not guaranteeing ordering due to distributed nature etc); but that might work as is. Or for larger messages, using related AWS service, s3, for storing actual body, and just passing headers through SQS.

StaxMan