Scheduled task in a web application?

Bart van Heukelom picture Bart van Heukelom · Nov 8, 2010 · Viewed 35.7k times · Source

I'm building a statistics apps for an online game, built using the servlet API in Java (to be deployed on Tomcat). It's easy enough to let the game send a message to the stats server every time a user logs in, because handling requests is what Servlets/Tomcat are for.

I also need to periodically initiate requests on the stats server though, for example to retrieve the number of online users from the game server or the number of fans from our Facebook page.

It would be easy to just start a thread in the app's main servlet and let that do the data retrieval once in a while, but it feels a bit strange because all other threads are created by Tomcat.

  1. Is doing it like that ok?
  2. If not, what is the recommended way of doing this?
  3. Is it even correct to use servlets for something like this? What's the alternative?

Note after first answers: I'm not looking for a solution to the problem of timing or concurrency, because I can easily handle both. I just need to know how to properly start a pro-active process in a servlet container.

Answer

vaskin picture vaskin · Nov 8, 2010

Quartz is your best bet, and most highly configurable. It has CRON based interface or a more dynamic way to generate jobs that are relative from a specific event, if your use case calls for it Quartz can do it. It has the ability to persist jobs to the database so they can survive restarts.

http://www.quartz-scheduler.org/

Make configurations in web.xml like this to auto-start it:

  <servlet> 
    <servlet-name>QuartzInitializer</servlet-name>
    <display-name>Quartz Initializer Servlet</display-name>
    <servlet-class>org.quartz.ee.servlet.QuartzInitializerServlet</servlet-class>
    <load-on-startup>1</load-on-startup>

    <init-param>
      <param-name>shutdown-on-unload</param-name>
      <param-value>true</param-value>
    </init-param>

    <init-param>
      <param-name>start-scheduler-on-load</param-name>
      <param-value>true</param-value>
    </init-param>

  </servlet>