Home > database >  How to send email from a servlet using threads or executor service?
How to send email from a servlet using threads or executor service?

Time:01-28

Where executor service should be declared so it is available to other servlets and not new thread gets created for every new request

Can I do something like this and whenever need to send email, forward request to this servlet Can you please suggest better design to use ExecutorService in servlet or any other way to send email from servlet?

public class EmailTestServlet extends HttpServlet
{

    ExecutorService emailThreadPool = null;

    public void init()
    {
          super.init();
      emailThreadPool = Executors.newFixedThreadPool(3);

    }
    protected void doGet(HttpServletRequest request,HttpServletResponse response)
    {
        sendEmail(); //it will call emailThreadPool.execute();
    }
    public void destroy()
    {
         super.destroy();
    }
}

CodePudding user response:

Depends on whether CDI is available at your environment. It is available out the box in normal Jakarta EE servers, but in case of barebones servletcontainers such as Tomcat or Jetty you'd need to manually install and configure it. It's relatively trivial though and gives a lot of benefit: How to install and use CDI on Tomcat?

Then you can simply create an application scoped bean for the job like below:

@ApplicationScoped
public class EmailService {

    private ExecutorService executor;

    @PostConstruct
    public void init() {
        executor = Executors.newFixedThreadPool(3);
    }

    public void send(Email email) {
        executor.submit(new EmailTask(email));
    }

    @PreDestroy
    public void destroy() {
        executor.shutdown();
    }
}

In order to utilize it, simply inject it in whatever servlet or bean where you need it:

@WebServlet("/any")
public class AnyServlet extends HttpServlet {

    @Inject
    private EmailService emailService;

    @Override
    protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
        Email email = new Email();
        // ...
        emailService.send(email);
    }

}

In case you find yourself in the unfortunate situation that you cannot use CDI, then you'll have to remove the @ApplicationScoped annotation from the EmailService class and reinvent the wheel by simulating whatever CDI is doing under the covers by manually fiddling with ServletContext#get/setAttribute() to simulate an application scoped bean. It might look like this:

@WebListener
public class ApplicationScopedBeanManager implements ServletContextListener {

    @Override
    public void contextCreated(ServletContextEvent event) {
        EmailService emailService = new EmailService();
        emailService.init();
        event.getServletContext().setAttribute(EMAIL_SERVICE, emailService);
    }

    @Override
    public void contextDestroyed(ServletContextEvent event) {
        EmailService emailService = (EmailService) event.getServletContext().getAttribute(EMAIL_SERVICE);
        emailService.destroy();
    }

}

In order to utilize it, rewrite the servlet as follows:

@WebServlet("/any")
public class AnyServlet extends HttpServlet {

    private EmailService emailService;

    @Override
    public void init() {
        emailService = (EmailService) getServletContext().getAttribute(EMAIL_SERVICE);
    }

    @Override
    protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
        Email email = new Email();
        // ...
        emailService.send(email);
    }

}

See also:

  • Related