6

I am working on a web application which is deployed in Tomcat. We are using Spring, Hibernate, GWT at the client side).

One of the functionality of this application is to send alerts ( emails ) to Users when any entity is created, updated or deleted. ( Alerts can be added by Users on the fly, so there is some processing involved - to decide which users should be notified by email ).

Alert mechanism ideally should be asynchronous and it should be affect the performance of CRUD operation.

First thing which came in my mind is to create a thread and have a blocking queue. Thread keeps polling blocking queue to see if it has got any events. But creating thread in web application is something which is discouraged by many Containers.

Can someone advice/ suggest - is this the correct way of doing it ? or There are better ways of doing the same thing .

Any pointers would be highly appreciated.

Thanks in advance, Sachin

Sachin
  • 103
  • 2
  • 8
  • Just don't forget to mark your Threads as Daemon threads, so they don't stop the Tomcat from shutting down cleanly. – Daniel Mar 23 '11 at 14:39

4 Answers4

7

The restriction on creating threads in a container was really just a suggestion to keep inexperienced developers from shooting themselves in the foot. No container actually prohibits you from doing this. With java.util.concurrent classes, creating threads should be less error prone and I wouldn't worry about this restriction too much.

If your requirements are simple, it's easy enough to just create a single thread / runnable in a ServletContextListener. Create and start the thread in contextInitialized() and shut it down in contextDestroyed(). . Use a ScheduledExecutorService created by Executors.newSingleThreadScheduledExecutor(). The Runnable you pass to the Executor would read from a BlockingQueue.

If your requirements change and you need something more complicated, you probably want to looks at JMS / MDBs or a scheduler like Quartz.

AngerClown
  • 6,149
  • 1
  • 25
  • 28
  • 1
    It is not just a suggestion for inexperienced developers. The point is to discourage the usage of unmanaged resources inside of an environment which is designed to manage resources. It is allowed in the web container, but there are ways of providing managed threads which will work better in this environment. As a side note, the EJB container doesn't even allow it. – Robin Mar 23 '11 at 15:09
  • Please see this example: http://java-by-ash.blogspot.com/2012/07/threads-in-java-web-application.html –  Jul 23 '12 at 11:58
  • I disagree with this answer, as mentioned EJB containers don't allow this. If you use Google App Engine, they place restrictions on async processing as well. When you are creating your own threads there is no management of them. If you keep your async service separate you won't have to worry about it taking the container down with it. – Joel Mar 18 '14 at 03:44
1

You could use a scheduler to run jobs regularly or use the Spring equivalent of Message Driven Beans (some documentation on JMS and Spring) which are executed by the container which does the queue polling for you.

Thomas
  • 87,414
  • 12
  • 119
  • 157
  • Thanks Thomas for your quick reply. We are thinking of using AOP and intercept all the service level CRUD calls and update in the ArrayBlockingQueue upon successful completion. If I use a scheduler, how will the Aspect which intercepts all service level CRUD calls notify the scheduler ? And Can you please provide some more details ( links , etc ) on Spring equivalent of MDB. Thanks once again – Sachin Mar 23 '11 at 14:21
  • Well, I added a link already, did you check that out? As for the scheduler, it should run regularly (say in 1 minute intervals or so), check for pending alerts and send those. One such scheduler would be [Quartz](http://www.quartz-scheduler.org/). – Thomas Mar 23 '11 at 14:50
  • Yes I did have a look at the link. – Sachin Mar 23 '11 at 15:01
1

You can try using Spring 3.x asynchronous method invocation. Caller method will return immediately and the actual execution happens asynchronously

applicationContext:

<task:annotation-driven executor="asyncExecutor" mode="aspectj"/>
<task:executor id="asyncExecutor" pool-size="${executor.poolSize}"/>

On your bean:

@Async
public void sendEmail(...) {
 // ...
}

please refer to Spring documentation for further details: Spring 3.x Task Execution and Scheduling

gouki
  • 4,382
  • 3
  • 20
  • 20
0

There are ways of doing it, the simplest (besides simply creating an unmanaged thread) is to use the commonj WorkManager. Certainly you can go the simple thread route, but it does have shortcomings in the environment you are operating in (as described in the link).

Community
  • 1
  • 1
Robin
  • 24,062
  • 5
  • 49
  • 58