What is the correct way to disable threads when tomcat is closed?

I am trying to disconnect threads when Tomcat shuts down.
Specifically, I am trying to disable the log4j watchdog (for file sharing) and also trying to terminate the executor who is using the class in my web application.
On shutdown, I see exceptions in Catalina.out.
For Log4J, I see:

INFO: Illegal Access: This web application instance
has been stopped already. Failed to load org.apache.log4j.helpers.NullEnumeration.
The possible next stack trace is caused by an error caused by debugging and an attempt to terminate the thread that caused the illegal access and has no functional impact. Throwable
happened: java.lang.IllegalStateException
        on org.apache.catalina.loader.WebappClassLoader.loadClass (WebappClassLoader.java:1587)
        on org.apache.catalina.loader.WebappClassLoader.loadClass (WebappClassLoader.java:1546)
        on org.apache .log4j.Category.getAllAppenders (Category.java:413)
        to org.apache.log4j.Category.closeNestedAppenders (Category.java:226)
        at org.apache.log4j.Hierarchy.shutdown (Hierarchy.java:467)
        at org.apache.log4j.LogManager.shutdown (LogManager.java:267)
        at com.listeners.myListener $ 1.run (myListener.java:232)
Exception on thread "Thread-14" java.lang.NoClassDefFoundError:
org.apache.log4j.helpers.NullEnumeration
        at org.apache.log4j.Category.getAllAppenders (Category.java:413)
        at org.apache.log4j.Category.closeNestedAppenders (Category.java:226)
        at org.apache.log4j.Hierarchy.shutdown (Hierarchy.java:467)
        at org.apache.log4j.LogManager.shutdown (LogManager.java:267)

And for the performer part:

INFO: Illegal Access: This web application instance
has been stopped already. Failed to load com.my.class.SomeClass. Ultimately the following stack trace is caused by an error generated to debug and also try to terminate the thread that caused the illegal access and has no functional impact. Thrown: java.lang.IllegalStateException
        on org.apache.catalina.loader.WebappClassLoader.loadClass (WebappClassLoader.java:1587)
        on org.apache.catalina.loader.WebappClassLoader.loadClass (WebappClassLoader)
        on thread Exception: 1546 Thread-13 "java.lang.NoClassDefFoundError:
com.my.class.SomeClass

What I am doing is in ServletContextListener

on contextDestroyed

. I added disconnect hooks like this:

public void contextDestroyed(ServletContextEvent arg0) {  

         Runtime.getRuntime().addShutdownHook(new Thread(){  
            @Override  
            public void run(){  
                LogManager.shutdown();                  
            }  
         });  

    } 





 public void contextDestroyed(ServletContextEvent arg0) {  

        Runtime.getRuntime().addShutdownHook(new Thread(){  
            @Override  
            public void run(){  
                SomeClass.updater.shutdown();  
            }  
        });  

    }  

      

What am I doing wrong here? Why am I getting exceptions?

UPDATE:
SomeClass.updater

is public static ScheduledExecutorService

.
LogManager

org.apache.log4j.LogManager

UPDATE2:
After following the answer from BGR, I do directly

public void contextDestroyed(ServletContextEvent arg0) {  

            SomeClass.updater.shutdown();  

        }  

      

and

public void contextDestroyed(ServletContextEvent arg0) {  

                LogManager.shutdown();                  

        } 

      

I am not getting an exception from Log4j, but I am getting the following exception for SomeClass.updater

which is public static ScheduledExecutorService

:

INFO: Illegal Access: This web application instance
has been stopped already. Failed to load java.util.concurrent.ExecutorService.
a possible subsequent stack trace is caused by an error caused by debugging, as well as attempts to terminate the thread that caused the illegal access and has no functional impact. Throwable
happened: java.lang.IllegalStateException
        on org.apache.catalina.loader.WebappClassLoader.loadClass (WebappClassLoader.java:1587)
        on org.apache.catalina.loader.WebappClassLoader.loadClass (WebappClass15Loader ).java:1587

Why? Are the classes already garbage collected?

+3


source to share


2 answers


I would register the stop hooks in the init () method of the servlet, not contextDetroyed (), but anyway, why would you need to have hooks off in the first place?

Can't you just call SomeClass.updater.shutdown();

directly in the contextDestroyed () method?

EDIT



contextDestroyed()

the listener must be late for the executor service. As stated in the javadoc All servlets and filters will be destroyed before any ServletContextListeners will be notified to destroy the context.

whereas overriding servlet destroy()

should be ok as per the javadoc. This method gives the servlet the ability to clean up any resources that are stored (e.g. memory, manuscript files, streams ...

@Override
public void destroy(  ) {


        myThreadExecutor.shutdown();

        super.destroy(  );
}

      

+2


source


Call

LogManager.shutdown();

      

in context, the destroyed () method is the first step, but the ExecutorService does not close immediately. You get exceptions because the ExecutorService threads are still running after the contextDestroyed () method returns. You need to do:



public void contextDestroyed(ServletContextEvent arg0) {  
    LogManager.shutdown();
    if(LogManager.awaitTermination(10, TimeUnit.SECONDS) == false) {
        LogManager.shutdownNow();
    }
} 

      

This way the thread pool closed and stopped all threads when contextDestroyed () is called.

+2


source







All Articles