3

The scenario I am trying to complete is the following:

  1. The client submits a HTTP POST request to the servlet.
  2. The servlet sends a response to the client confirming the request has been received.
  3. The servlet then sends an email notification to the system administrator.

So far I am able to complete the following steps in the order described above, however I run into an issue at the end. If the client makes another HTTP request to the same or another servlet while the email notification method EmailUtility.sendNotificationEmail() is still running, the servlet will not run any further code until this email method is completed (I am using javax.mail to send emails if that matters).

I have tried to use AsyncContext to get around this (which I may be using incorrectly), but unfortunately the issue still remains.

How can I make the EmailUtility.sendNotificationEmail() run in a different thread/asynchronously so that the servlets do not have to wait for this method to complete?

This is my code so far:

//Step 1: Client submits POST request to servlet.
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
    request.setAttribute("org.apache.catalina.ASYNC_SUPPORTED", true);

    //Step 2: Servlet sends response to client.
    response.getWriter().write("Your request has been received");
    response.getOutputStream().flush();
    response.getOutputStream().close();

    //Step 3: Servlet send email notification.
    final AsyncContext acontext = request.startAsync();
    acontext.start(new Runnable() {
        public void run() {
            EmailUtility.sendNotificationEmail();
            acontext.complete();
        }
    });
}
dat3450
  • 954
  • 3
  • 13
  • 27
  • 1
    Send the email before replying to the request. it is generally asynchronous, so the reply would be received beforehand... – Usagi Miyamoto Oct 10 '17 at 03:19
  • 1
    I have tried sending the email beforehand but unfortunately the response is not sent until the email method is completed, so the issue still remains. – dat3450 Oct 10 '17 at 03:20
  • 1
    I don't think `AsyncContext` can be used after sending the response; it's meant for asynchronous preparation of a response. – Davis Herring Oct 10 '17 at 03:37
  • Yeah I think I have been using this incorrectly, as the following post explains "There is no thread created by startAsync! It just tells the servlet container: hey, although the doGet/doPost method finished, I am not done with this request, please do not close." https://stackoverflow.com/a/10066273/7155133 – dat3450 Oct 10 '17 at 03:41

2 Answers2

0

Try something simple, like a thread:

new Thread(new Runnable()
{
   @Override
   public void run()
   {
       EmailUtility.sendNotificationEmail();
   }
}, "Send E-mail").start();
Usagi Miyamoto
  • 6,196
  • 1
  • 19
  • 33
  • From my understanding, using threads in a servlet environment is not recommended. Thanks for the help though. – dat3450 Oct 10 '17 at 03:46
0

So I resolved the issue by using ExecutorService as follows:

ExecutorService executorService = Executors.newFixedThreadPool(10);

executorService.execute(new Runnable() {
    public void run() {
        EmailUtility.sendNotificationEmail();
    }
});

executorService.shutdown();
dat3450
  • 954
  • 3
  • 13
  • 27