Tuesday, January 24, 2006
Design Self Refreshing HTML Page
I faced a problem in one of my WebApplication where the response from the server for the client request was taking too long, without any feedback to the client about the progress. The servlet (ClientServlet) which handled the request (for url, clientreq), spent most of its time on lookups before sending the response.
I found html meta to be useful in such case. The <meta http-equiv='refresh' content='1; url="clientreq"'> when included in HTML page will timeout the page every 1 second (specified value in content) and the request is sent to the specified url (clientreq). Taking advantage of this feature I designed a model where the client can get the feedback on the progress of the response.
The design was, ClientServlet will redirect to progress.jsp with status message if it is not ready to send response (busy in doing the lookup). Once ClientServlet has finished its lookup it sends the actual response to the client instead of redirect.
Task of progress.jsp is just to send the HTML page with the status message along with <meta http-equiv='refresh' content='1; url="clientreq"'>. Which makes frequent request to the ClientServlet to get the status or response.
The lookup work was moved to the class AsyncHandler, which spans a new thread when it is started and gives the status of its work.
First ClientServlet creates AsyncHandler and puts into the session after starting it. A redirect is sent to progress.jsp with status message. For subsequent request, ClientServlet checks the status of AsyncHandler and decides whether to redirect to progress.jsp or send actual response.
Snippet of my Servlet code:
Snippet of progress.jsp:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv='refresh' content='1; url="clientreq"'>
<title>Please Wait</title>
</head>
<body>
<%= req.getParameter("msg") %>
</body>
</html>
I found html meta to be useful in such case. The <meta http-equiv='refresh' content='1; url="clientreq"'> when included in HTML page will timeout the page every 1 second (specified value in content) and the request is sent to the specified url (clientreq). Taking advantage of this feature I designed a model where the client can get the feedback on the progress of the response.
The design was, ClientServlet will redirect to progress.jsp with status message if it is not ready to send response (busy in doing the lookup). Once ClientServlet has finished its lookup it sends the actual response to the client instead of redirect.
Task of progress.jsp is just to send the HTML page with the status message along with <meta http-equiv='refresh' content='1; url="clientreq"'>. Which makes frequent request to the ClientServlet to get the status or response.
The lookup work was moved to the class AsyncHandler, which spans a new thread when it is started and gives the status of its work.
First ClientServlet creates AsyncHandler and puts into the session after starting it. A redirect is sent to progress.jsp with status message. For subsequent request, ClientServlet checks the status of AsyncHandler and decides whether to redirect to progress.jsp or send actual response.
Snippet of my Servlet code:
private void processRequest(HttpServletRequest req,
HttpServletResponse res) throws Exception {
final String HANDLER_KEY = "Client_Async_Handler";
HttpSession session = req.getSession();
AsyncHandler ah =
(AsyncHandler) session.getAttribute(HANDLER_KEY);
if(ah == null) {
ah = new AsyncHandler();
ah.start();
session.setAttribute(HANDLER_KEY, ah);
res.sendRedirect("progress.jsp?msg=" +
URLEncoder.encode(ah.getStatus(), "utf-8"));
return;
} else {
if(ah.done()) {
sendResponse(res, ah);
session.setAttribute(HANDLER_KEY, null);
ah = null;
return;
} else {
res.sendRedirect("progress.jsp?msg=" +
URLEncoder.encode(ah.getStatus(), "utf-8"));
return;
}
}
}
Snippet of progress.jsp:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv='refresh' content='1; url="clientreq"'>
<title>Please Wait</title>
</head>
<body>
<%= req.getParameter("msg") %>
</body>
</html>