Running a Java daemon with a GWT front-end served by embedded Jetty
- by BinaryMuse
Greetings, coders,
Background Info and Code
I am trying to create a daemon-type program (e.g., it runs constantly, polling for things to do) that is managed by a GWT application (servlets in a WAR) which is in turn served by an embedded Jetty server (using a WebAppContext). I'm having problems making the GWT application aware of the daemon object.
For testing things, I currently have two projects: The daemon and embedded Jetty server in one (EmbJetTest), and the GWT application in another (DefaultApp). This is the current state of the code:
First, EmbJetTest creates an embedded Jetty server like so, using a ServletContextListener to inject the daemon object into the web application context:
EmbJetTest.server = new Server(8080);
// Create and start the daemon
Daemon daemon = new Daemon();
Thread thread = new Thread(daemon);
thread.start();
// war handler
WebAppContext waContext = new WebAppContext();
waContext.setContextPath("/webapp");
waContext.setWar("./apps/DefaultApp.war");
waContext.addEventListener(new DaemonLoader(daemon));
// Add it to the server
EmbJetTest.server.setHandler(waContext);
EmbJetTest.server.setThreadPool(new QueuedThreadPool(10));
// Start the server; join() blocks until we shut down
EmbJetTest.server.start();
EmbJetTest.server.join();
// Stop the daemon thread
daemon.stopLoop();
Daemon is a very simple object with a couple properties, at the moment. DaemonLoader is the following ServletContextListener implementation:
private Daemon daemon;
public DaemonLoader(Daemon daemon)
{
this.daemon = daemon;
}
@Override
public void contextDestroyed(ServletContextEvent arg0) {
}
@Override
public void contextInitialized(ServletContextEvent arg0) {
arg0.getServletContext().setAttribute("daemon", this.daemon);
}
Then, in one of my servlets in the GWT application, I have the following code:
Daemon daemon = (Daemon) this.getServletContext().getAttribute("daemon");
However, when I visit localhost:8080/webapp/* and invoke the servlet, this code throws a ClassCastException, even though the classes are of the same type. This StackOverflow answer indicates that this is because the two classes are loaded with different classloaders.
Question
My question is twofold.
Am I even on the right track here? Am I going about this completely the wrong way? Something tells me I am, but I can't think of another way to make the daemon available to both applications. Is there a better way to communicate with the daemon from the GWT application? Should the GWT app own the daemon and somehow start the daemon itself? The daemon needs to run even if no one visits the one of the GWT app's servlets--how could I do this?
If I am on the right track, how can I get around the classloader issue?
Thanks in advance.