views:

2434

answers:

4

I have a GWT application that displays some charts rendered by JFreeChart. Every few minutes, the page refreshes, which causes the app to generate new charts. (In other words, the entire chart generation process is bootstrapped by a client request.) The problem with this is that multiple clients hitting the same server would result in multiple requests to generate charts, but since the charts are the same for all users, there's really no reason to do this. I would like to prerender the charts in a background thread, which would be kicked off when the application starts, and then just serve the already-rendered charts to the client on request.

I don't see any "sanctioned" way in GWT to execute your own code at server startup. The only way I can think of to accomplish this is to create a servlet that gets loaded at startup by the application container, and kick off the chart generation thread in the init() method.

Is there a more preferred way to do this?

Note: Assuming that it's true, "no" is a perfectly acceptable answer.

+3  A: 

To answer your question: No. GWT is a front end technology, and the only bit of GWT that crosses this line is the RPC mechanism. The only 'GWT' type way that you could do it would be to check if the chart files exist the first time a user requests them, and generate them if they don't. This would mean using the file system as your check of if it's been created yet or not.

The better way would be to do what you said, eg: configure your your web project to kick off a class on startup. You do this in your web.xml as described here:

http://wiki.metawerx.net/wiki/Web.xml.LoadOnStartup

Here's an example of how Stripes does it:

<servlet>
        <servlet-name>StripesDispatcher</servlet-name>
        <servlet-class>net.sourceforge.stripes.controller.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>StripesDispatcher</servlet-name>
        <url-pattern>*.action</url-pattern>
    </servlet-mapping>
rustyshelf
+1  A: 

First of all, I disagree with the prior poster that GWT is a a front-end technology only, since the framework includes everything for building and invoking services asynchronously. See, for example, RemoteServiceServlet, and usages. GWT provides client-side and server-side components.

Having said this, GWT doesn't seem to specifically have a startup type servlet. But, since the back end is servlet-based, I'd be inclined, for consistency's sake, to use a startup servlet (search on Loading Servlets on Startup in google), and have it generate the charts on startup, then periodically as needed.

An alternative would be to have a cron job that periodically re-builds the charts, either directly or by invoking a private service.

Either way, the client requests would then just retrieve the pre-generated chart. When a new chart is generated, just swap it in in place of the old one, so that there's no noticeable lag to the user.

Don Branson
A: 

GWT is a front-end framework. I does have some specific server component, but these are only used to serialize/deserialize the client's requests. Remember that the front end is in JavaScript, and the back end is in java. So the server components convert a JavaScript object to it's java representation. If you look at your code, you can notice that GWT RemoteServiceServlet just inherits the standards "javax.servlet.http.HttpServlet", like any servlet would do. It just implements its own doPost and doGet method to do the serialization.

That being said, your question could apply to a multitude of other framework. It is not dependent on GWT. You just need to configure your servlet container to start GWT RemoteServiceServlet at startup. The servlet could have static cache the are used by all clients and deliver the same chart. You could then just start a second thread at startup that updates the thread periodically.

Thierry-Dimitri Roy
Don Branson
+1  A: 

I disagree that you should put code in the servlet initialization to create these threads. When the web app is stopped you won't get control over when to destroy these threads. Also when you start the web app up again will it create these threads again or not?

What would be better is to use the J2EE ServletContextListener event named contextInitialized to create the threads and the contextDestroyed event to destroy your threads. This also allows you to control thread destruction and wait for code in the threads to finish executing before destroying them.

Looks like this explains how that works: http://www.java-tips.org/java-ee-tips/java-servlet/how-to-work-with-servletcontextlistener.html

sjbotha