20 - Asynchronous Method Invocation Example in EJB

Asynchronous Method Invocation Example

In the following example, we will create a web application with 2 singleton services, one called AsyncAction that has an asynchronous action and the other one is called MainService that will handle all the communication with the AsyncAction bean. The project will contain one servlet that is mapped to the URL pattern ClientServlet and will be used to invoke the startAction/checkActionDone/getFinalResult on the MainService bean. The project structure will look like the following:

                 

The code for the 3 classes should be like the following:

package com.ejb3tutorial.async;

import java.util.concurrent.Future;

import javax.ejb.AsyncResult;
import javax.ejb.Asynchronous;
import javax.ejb.Singleton;

@Singleton
public class AsyncAction {

     @Asynchronous
    public Future<String> getResult() {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return new AsyncResult<String>("Final Action Result");
    }
}

package com.ejb3tutorial.async;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

import javax.ejb.EJB;
import javax.ejb.Singleton;

@Singleton
public class MainService {

    private Future<String> task = null;

    @EJB
    private AsyncAction asyncBean;

    public void startAction() {
        task = asyncBean.getResult();
    }

    public boolean checkActionDone() {
        return task.isDone();
    }

    public String getFinalResult() throws InterruptedException,
            ExecutionException {
        return task.get();
    }
}

package com.ejb3tutorial.async;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.concurrent.ExecutionException;

import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/ClientServlet")
public class ClientServlet extends HttpServlet {

      private static final long serialVersionUID = 1L;
      @EJB
      private MainService mainService;
      public ClientServlet() {
        super();
      }

      protected void doGet(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {
        PrintWriter pw = response.getWriter();
        if (request.getSession().getAttribute("ActionStart") == null) {
            mainService.startAction();
            request.getSession().setAttribute("ActionStart", "1");
            pw.print("Action In Progress");
            response.setIntHeader("Refresh", 1);
        } else {
            if (mainService.checkActionDone()) {
                try {
                    pw.print("Action finished, final result : "
                            + mainService.getFinalResult());
                    request.getSession().removeAttribute("ActionStart");
                } catch (InterruptedException | ExecutionException e) {
                    e.printStackTrace();
                }
            } else {
                pw.print("Action In Progress");
                response.setIntHeader("Refresh", 1);
            }
        }
        pw.close();
    }

    protected void doPost(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}

When deploying the web application on JBOSS web server and directing to the URL : http://localhost:8080/AsynchronousMethod/ClientServlet the following actions will take place:

  1. The servlet will check if the session has the attribute “ActionStart” that is used to check if the action already started or not.
  2. If the action has not started, the servlet will call the method “startAction” from MainService bean. The startAction method will call the asynchronous method getResult from the AsyncAction bean and will cache the returned Future object.
  3. The servlet will direct the browser to refresh again after 1 second.
  4. If the ActionStart attribute already exists in the client session map, then the servlet will first check if the asynchronous action is finished or not  using the method checkActionIsDone from the MainService bean. The MainService can check if the task has  finished or not yet using the method “isDone” from the Future object that is retrieved from the getResult method invocation.
  5. In case the checkActionIsDone returns false, the servlet will direct the browser to check again after 1 second.
  6. In case the checkActionIsDone returns true, then the servlet will call the MainService bean method “getFinalResult” which calls the Future object “get” method to get the actual returned value from the asynchronous method and the servlet will print the final result on the browser screen.

Only one note about the code, our long running time method just waits for 5 seconds simulating a long running code.

Like us on Facebook