5

I'm working on a web application which needs to clear expired cache elements now and then. I'd like to do this using the Quartz framework, and have a separate job to take part of this.

Now, I've used Quartz in other projects and usually schedule all jobs from a ServletContextListener using contextInitialised(ServletContextEvent sce) and contextDestroyed(ServletContextEvent sce). However, I've done it this way because a tutorial i once read did it that way.

I'm uncertain if I can just schedule the tasks from the servlet's init() and destroy() methods instead? I guess one could argue that I'm now mixing background tasks and servlets, and thus responsibilities, but I'd like to hear if there is a "best practice" on this?

sbrattla
  • 4,960
  • 3
  • 33
  • 57
  • @BalusC : out of pure curiosity; how can my question - posted in 2011 - be a duplicate of a question posted in 2014? Even though my question has less views and "likes", my question asks for "best practices" for starting background threads whereas the other question seems to be a scream for help with understanding the difference between servlets and background threads. – sbrattla Oct 08 '15 at 08:05
  • It wasn't posted in 2014. It was edited in 2014. With duplicates, focus on answer, not on question. – BalusC Oct 08 '15 at 08:08

3 Answers3

3

A servlet is not necessarily initialized when the webapp is deployed. It may be initialized lazily.

And you may have many servlets in a single webapp, so you might then wonder which servlet would be responsible of the scheduling.

A ServletContextListener is the right tool to use when something must be done at deployment and undeployment time.

JB Nizet
  • 633,450
  • 80
  • 1,108
  • 1,174
3

First of all, usual disclaimer: you're not supposed to mess with threads in a Servlet container. So all the ways are by definition wrong (I suspect the right way would be calling curl from crontab).

ServletContextListener is the preferred method these days; Servlet's init() was an OK method back when ServletContextListener wasn't here. There are different problems with servlets, though: first of all, it may not be inited on startup (addressed by load-on-startup parameter); it can be unloaded just because servlet contained decided to do so (never saw in practice—but the spec says it can be).

Most important, though, is that it's a trick—and as any other trick, it makes little sense to the reader unless you document it carefully, or he knows well ahead that it's a trick. So if in doubt, avoid.

Community
  • 1
  • 1
alf
  • 8,147
  • 21
  • 45
  • Thanks! I'd like the application to be "self contained", meaning that I'd like to not have to rely on external configuration such as crontab and the like. However, is there any "critical" implications with regards to using threads through something like the Quartz framework? – sbrattla Dec 04 '11 at 13:57
  • Nothing critical as far as I know. We all do it all the time—I just wanted to mention that the spec says, "don't do that!" Theoretically, if you deploy to a managed environment, your code may be restricted, and thread management can be disabled. The only example I can come up with is Google AppEngine—but it's so restricted that threads will be your least significant concern. – alf Dec 04 '11 at 14:05
  • Alright, thanks. I've seen Tomcat issue log warnings when I undeploy servlets that says a thread or two was not stopped. However, I believe that's causes by threads not always being able to finish whatever they do before Tomcat impatiently quits. – sbrattla Dec 04 '11 at 14:09
  • This one is a different concern, raised several times (e.g. re: Quartz: http://stackoverflow.com/questions/3815587/tomcat-not-shutting-down-cleanly-due-to-daemon-threads). Usually, it's not your threads that are still around, but threads started by some of the libraries you use. In most cases, the only practical solution for production is to kill the server on redeploy. (I'd be happy to find the magic wand—but had no luck so far.) – alf Dec 04 '11 at 14:14
  • Ok. I haven't really paid that much attention to it, other than making sure that the ServletContextListener stops all threads. Anyway, thanks for your input. Marking this one as the accepted answer. – sbrattla Dec 04 '11 at 14:24
1

Using contextInitialised and contextDestroyed methods of ServletContextListener looks perfectly correct for your case.

For example Spring Framework does exactly in the same way when initializing spring beans and scheduling tasks (org.springframework.web.context.ContextLoaderListener).

Also I would consider using some kind of abstraction for scheduling quartz tasks (for example mentioned Spring Framework).

Andrey
  • 6,117
  • 3
  • 30
  • 54
  • Thanks! Which gains to I get from abstracting task scheduling? I've used Quartz without any extra abstractions before, and that worked well. However, if it can make implementation and maintenance easier then I'd sure be willing to give it a try. – sbrattla Dec 04 '11 at 14:06
  • @sbrattla That abstraction will allow you to do not care about implementation details (writing own servlet context listeners, manipulating quartz api, etc.). But just configure once, and then register tasks in convenient way (for example using annotations). Refer here, for example: http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/scheduling.html – Andrey Dec 04 '11 at 17:46