13

for my webapp I use Quartz. When I deploy the app all is ok. When I undeploy the app, the Quartz thread is not destroyed.

Log is:

INFO: Stopping service Catalina

SEVERE: The web application [/example] appears to have started a thread named [DefaultQuartzScheduler_Worker-1] but has failed to stop it. This is very likely to create a memory leak. Jul 12, 2010 6:30:40 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads

Anyone can tell me how I can force the destroy action for those threads?

Thanks,

Tommaso

Community
  • 1
  • 1
Tommaso Taruffi
  • 8,932
  • 9
  • 44
  • 56

3 Answers3

7

I found that the issue for me was that quartz was being shutdown but the webapp didn't wait for quartz to finish before it shutdown so Tomcat decided that it had left threads running and complained.

So I managed my scheduler like this:

Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
...do some stuff with the scheduler...
scheduler.shutdown(true);

Note the boolean argument to shutdown is the vital part. If you remove that true to call the no-arg version or set it to false, your webapp won't wait for quartz to shudown before it shuts down.

TL;DR: call scheduler.shutdown(true) to make your webapp wait for quartz to finish.

Tom Saleeba
  • 4,031
  • 4
  • 41
  • 36
4

How are you starting Quartz?

Assuming you are not using a convenient wrapper like Spring, you probably want to be using a <listener> in your application's web.xml so that Quartz can be notified of the application start and shutdown.

See QuartzInitializerListener or QuartzInitializerServlet for instance.

Community
  • 1
  • 1
matt b
  • 138,234
  • 66
  • 282
  • 345
  • Yes, my app use quartz for execute thread in a given moment of the day. – Tommaso Taruffi Jul 12 '10 at 17:01
  • @tommaso I was asking how you start/invoke the Quartz scheduler to be able to execute jobs at specific times. Given that you are in a servlet environment, rather than simply starting it in your code you likely want to hook into the listener/servlet startup sequence, so you can also receive notification when the application is being shut down - so you can shut down quartz at the same time. – matt b Jul 12 '10 at 17:52
  • 1
    I give to spring the control of quartz via org.springframework.scheduling.quartz.SchedulerFactoryBean org.quartz.simpl.SimpleThreadPool ... – Tommaso Taruffi Jul 13 '10 at 08:06
  • And how are you initializing/starting Spring? Is it through a ContextLoaderListener? Is Spring notified when the app shuts down? – matt b Jul 13 '10 at 11:08
  • Yes spring start via ContextLoaderListener and Spring received a notify when the app shut down. – Tommaso Taruffi Jul 13 '10 at 12:51
  • 1
    The `destroy()` method of `SchedulerFactoryBean` will invoke `org.quartz.Scheduler.shutdown()` with a boolean argument for `waitForJobsToCompleteOnShutdown`. Are you by any chance setting this flag in `SchedulerFactoryBean` to true? Perhaps Tomcat does not wait long enough for jobs to complete in Quartz before shutting down anyway. – matt b Jul 13 '10 at 13:07
  • This parameter is set to true, but after still waiting more than 2 minutes tomcat not stop. – Tommaso Taruffi Jul 13 '10 at 13:23
  • Well are your jobs completing within that time frame or are they longer-running? Do you need the server shutdown to wait for the jobs to complete? Sounds like you need to choose between one or the other. – matt b Jul 13 '10 at 16:22
0

I recommend you to use the 2.x version and, add a listener to web.xml.

Add the method below to the listener:

public void contextDestroyed(ServletContextEvent event) {

    if (this.contextLoader != null && event!=null && event
        .getServletContext()!=null) {
        ServletContext context = event.getServletContext();
        StdSchedulerFactory sch = (StdSchedulerFactory) context.getAttribute("org.quartz.impl.StdSchedulerFactory.KEY");

        if(sch!=null){
            try {
                logger.debug("call quartz Scheduler.shutdown()");
                Collection<Scheduler> col = sch.getAllSchedulers();
                for(Scheduler s:col){ 
                    s.shutdown();
                }
            } catch (SchedulerException e) {
                e.printStackTrace();
            }
        }
    }
}
Littm
  • 4,923
  • 4
  • 30
  • 38
Yu Jiaao
  • 4,444
  • 5
  • 44
  • 57