I am working on a web application which is deployed in Tomcat. We are using Spring, H开发者_运维知识库ibernate, 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
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.
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.
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
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).
精彩评论