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);
}
}