Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

No log output on contextDestroyed using ServletContextListener & SLF4J

I am trying to write a message to the logger that a (Vaadin) servlet has stopped, this using SLF4J and Log4j2.

For this I am using a ServletContextListener which logs a message when the application has started. However I have been unable to get any output when logging inside the contextDestroyed method... Here is my implementation:

@WebListener
public class VaadinLogger implements ServletContextListener {

    private static final Logger logger = LoggerFactory.getLogger(VaadinLogger.class);

    @Override
    public void contextInitialized(ServletContextEvent contextEvent) {
        // Remove appenders from JUL loggers
        SLF4JBridgeHandler.removeHandlersForRootLogger();

        // Install bridge
        SLF4JBridgeHandler.install();

        // Get servlet context
        ServletContext context = contextEvent.getServletContext();

        // Retrieve name
        String name = context.getServletContextName();

        // Log servlet init information
        logger.info("Start \"{}\"", name);
    }

    @Override
    public void contextDestroyed(ServletContextEvent contextEvent) {
        // Get servlet context
        ServletContext context = contextEvent.getServletContext();

        // Retrieve name
        String name = context.getServletContextName();

        // Log servlet destroy information
        logger.info("End \"{}\"{}", name, System.lineSeparator()));

        // Uninstall bridge
        SLF4JBridgeHandler.uninstall();
    }
}

At this point, I'm guessing this is probably because at the point contextDestroyed is called, logging is no longer possible because they have already been destroyed by the garbage collector.

So now my question is, is it possible to either log that the servlet has stopped before the context is destroyed, or make the contextlistener execute before log4j2 loggers are destroyed?

Thanks in advance!

like image 500
Kryptoxx Avatar asked Nov 21 '15 14:11

Kryptoxx


People also ask

What is the difference between ServletContextEvent and ServletContextListener?

ServletContextEvent class provides alerts/notifications for changes to a web application's servlet context. ServletContextListener is a class that receives alerts/notifications about changes to the servlet context and acts on them.

Which listener's should be used to log the request?

HttpSessionListener is a simple implementation to log the event when the session is created or destroyed. ServletRequestListener is to log the servletRequest IP address when the request is initialized and destroyed.

What are the methods available in ServletContextListener?

Methods of ServletContextListener interfacepublic void contextInitialized(ServletContextEvent e): is invoked when application is deployed on the server. public void contextDestroyed(ServletContextEvent e): is invoked when application is undeployed from the server.

What is ServletContextListener in Java?

void contextInitialized(ServletContextEvent sce) Receives notification that the web application initialization process is starting. All ServletContextListeners are notified of context initialization before any filters or servlets in the web application are initialized.


1 Answers

Since log4j 2.14.1, you can disable the auto-shutdown and add a listener to stop the logger.

<context-param>
    <!-- auto-shutdown stops log4j when the web fragment unloads, but that
         is too early because it is before the listeners shut down. To 
         compensate, use a Log4jShutdownOnContextDestroyedListener and
         register it before any other listeners which means it will shut
         down *after* all other listeners. -->
    <param-name>isLog4jAutoShutdownDisabled</param-name>
    <param-value>true</param-value>
</context-param>    

<listener>
   <!-- ensure logging stops after other listeners by registering
        the shutdown listener first -->
    <listener-class>
       org.apache.logging.log4j.web.Log4jShutdownOnContextDestroyedListener
    </listener-class>
</listener>
<listener>
    <listener-class>
        org.springframework.web.context.ContextLoaderListener
    </listener-class>
</listener>
like image 111
Tim Perry Avatar answered Sep 21 '22 14:09

Tim Perry