开发者

Running a Java daemon with a GWT front-end served by embedded Jetty

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 co开发者_开发知识库ntext:

    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.

  1. 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?
  2. If I am on the right track, how can I get around the classloader issue?

Thanks in advance.


Why not just run the functionality of the daemon in a separate thread within the GWT web application ? That way you'll avoid all the classloading grief (as you've found out, apps in different .war files run within their own classloaders).

Just create a servlet for your daemon alongside your existing servlets (in the same .war), and start/stop the thread on servlet initialisation and destruction.


Well, in case anyone is interested, I actually managed to solve the classloader issue--originally, I placed the compiled Daemon.class in the GWT app's WEB-INF/classes folder. I deleted this file and now it appears that the GWT app uses the Daemon class from the EmbJetTest project.

That being said, I think Brian's answer is much more noteworthy. :)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜