Redirect servlet async and heart beat

1.2k Views Asked by At

We have tasks in java web-app that take a long time in completing and before the time the task completes the request times out and page cannot be displayed happens. We are think of setting a async redirection servlet that acts as a front-controller redirecting the request to the appropriate action classes and while the request is being served the servlet keeps sending a heartbeat every minute or so, until the request is completed by the corresponding action classes. Has anybody implemented something similar using asynchronous servlet 3.0? Also is this possible? I understand that this is similar to server push. Thanks for guidance.

1

There are 1 best solutions below

0
Nirav Prajapati On

yes this kind of functionality you can achive by use of asynchronous servlet 3.0.it basically works like push notification and also give you respose continously with out making request here i have one code that i share with this code may help for you to make async request.

this example check live users



@WebServlet(urlPatterns = { "/checkliveuser" }, asyncSupported = true)
public class CheckLiveUser extends HttpServlet {
    private static final long serialVersionUID = 1L;

    private static final Queue<AsyncContext> queue = new ConcurrentLinkedQueue();

    private static final BlockingQueue<String> messageQueue = new LinkedBlockingQueue();

    private static final String BEGIN_SCRIPT_TAG = "<script type='text/javascript'>\n";

    private static final String END_SCRIPT_TAG = "</script>\n";

    private Thread notifierThread = null;
    @Override
    public void init(ServletConfig config) throws ServletException {

        ServletContext context = config.getServletContext();
        Set<String> users = new HashSet<String>();
        Map<String, String> page = new HashMap<String, String>();
        context.setAttribute("page", page);
        context.setAttribute("messageQueue", messageQueue);


        Runnable notifierRunnable = new Runnable() {
            public void run() {
                boolean done = false;
                while (!done) {
                    System.out.println("in thread");
                    String cMessage = null;
                    try {
                        cMessage = BEGIN_SCRIPT_TAG + toJsonp("<b>Live User:", messageQueue.take())
                        + END_SCRIPT_TAG;
                        for (AsyncContext ac : queue) {
                            try {
                                PrintWriter acWriter = ac.getResponse()
                                        .getWriter();
                                acWriter.println(cMessage);
                                acWriter.flush();
                            } catch (IOException ex) {
                                System.out.println(ex);
                                queue.remove(ac);

                            }
                        }
                    } catch (InterruptedException iex) {
                        done = true;
                        System.out.println(iex);
                    }
                }
            }
        };
        notifierThread = new Thread(notifierRunnable);
        notifierThread.start();
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
     *      response)
     */
    protected void doGet(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {


        response.setContentType("text/html");

        PrintWriter writer = response.getWriter();

request.setAttribute("org.apache.catalina.ASYNC_SUPPORTED", true);
        final AsyncContext ac = request.startAsync();
        ac.setTimeout(10 * 60 * 1000 * 1000);
        ac.addListener(new AsyncListener() {
            public void onComplete(AsyncEvent event) throws IOException {
                queue.remove(ac);
                System.out.println("on complete");
            }

            public void onTimeout(AsyncEvent event) throws IOException {
                queue.remove(ac);
                System.out.println("on timeout");
            }

            public void onError(AsyncEvent event) throws IOException {
                queue.remove(ac);
                System.out.println("on error");

            }

            public void onStartAsync(AsyncEvent event) throws IOException {
                System.out.println("on startup");
            }
        });
        queue.add(ac);
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
     *      response)
     */
    protected void doPost(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {

        response.setContentType("text/plain");
        response.setCharacterEncoding("UTF-8");
        ServletContext context = request.getServletContext();
        HttpSession session = request.getSession();
        Map<String, String> logins = (Map<String, String>) context
                .getAttribute("page");
        if (request.getParameter("action") != null
                && !request.getParameter("action").isEmpty()) {

            if (request.getParameter("action").equalsIgnoreCase("logout")) {

                logins.remove(request.getSession().getId());
                request.getSession().invalidate();

            }
        }
        String name = request.getParameter("loginID");
        if (name != null) {

            session.setAttribute("user", name);
            session.setAttribute("jsessionId", session.getId());
            logins.put(session.getId(), name);

        }
        String html = "";

        for (Map.Entry<String, String> entry : logins.entrySet()) {
            System.out.println("Key : " + entry.getKey() + " Value : "
                    + entry.getValue());
            html += entry.getValue() + "<br>";
        }

        String cMessage = BEGIN_SCRIPT_TAG + toJsonp("<b>Live User:", html)
                + END_SCRIPT_TAG;
        notify(cMessage);

        response.getWriter().println("success");
        if (request.getParameter("action") != null
                && !request.getParameter("action").isEmpty()) {

            if (request.getParameter("action").equalsIgnoreCase("logout"))
                response.sendRedirect("login.jsp");

        } else {
            response.sendRedirect("welcome.jsp");
        }

    }

    @Override
    public void destroy() {
        queue.clear();
        notifierThread.interrupt();
    }

    private void notify(String cMessage) throws IOException {
        try {
            messageQueue.put(cMessage);
        } catch (Exception ex) {
            IOException t = new IOException();
            t.initCause(ex);
            throw t;
        }
    }

    private String escape(String orig) {
        StringBuffer buffer = new StringBuffer(orig.length());

        for (int i = 0; i < orig.length(); i++) {
            char c = orig.charAt(i);
            switch (c) {
            case '\b':
                buffer.append("\\b");
                break;
            case '\f':
                buffer.append("\\f");
                break;
            case '\n':
                buffer.append("<br />");
                break;
            case '\r':
                // ignore
                break;
            case '\t':
                buffer.append("\\t");
                break;
            case '\'':
                buffer.append("\\'");
                break;
            case '\"':
                buffer.append("\\\"");
                break;
            case '\\':
                buffer.append("\\\\");
                break;
            case '<':
                buffer.append("<");
                break;
            case '>':
                buffer.append(">");
                break;
            case '&':
                buffer.append("&");
                break;
            default:
                buffer.append(c);
            }
        }

        return buffer.toString();
    }

    private String toJsonp(String name, String message) {
        return "window.parent.app.update({ name: \"" + escape(name)
                + "\", message: \"" + escape(message) + "\" });\n";
    }