I'm implementing a serlvet that, using AsyncContext, can send messages back to the client asynchronously. Other servlets need to be able to queue up messages for the client, that are then served to the client when the browser asks for messages via AJAX.
My current implementation uses a static timer:
private static Timer messageSender = new Timer("MessageSerlvetSender", true);
It is created as a daemon thread so that it will not keep the servlet container's threads alive longer than they should. Other servlets queue up messages via:
public static void write(HttpServletRequest req, MessageType type, String message) {
try {
synchronized (messageSender) {
messageSender.schedule(new MessageTask(hashSession(req), type, message), MSG_DELAY_MS, MSG_TIMEOUT_MS);
}
} catch (IllegalStateException ex) {
// Timer daemon thread has been canceled
messageSender = new Timer("MessageSerlvetSender", true);
write(req, type, message);
}
}
MessageTask
is a runnable that grabs the AsyncContext
that has been added to a hash map (using the session ID), writes the message, completes the context, and cancels the task on success.
This is thread-safe, and allows the timer to be restarted if the daemon thread has died. This implementation tries not to assume any state to comply with the API of servlets, but it feels... dirty. What is the best practice in this situation? How can I leverage HTTP session attributes?