All Downloads are FREE. Search and download functionalities are using the official Maven repository.

clime.messadmin.providers.lifecycle.KnownThreadLocalsCleaner Maven / Gradle / Ivy

Go to download

Notification system and Session administration for J2EE Web Applications

The newest version!
/**
 * 
 */
package clime.messadmin.providers.lifecycle;

import java.lang.reflect.Method;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import clime.messadmin.providers.spi.RequestExceptionProvider;
import clime.messadmin.providers.spi.RequestLifeCycleProvider;

/**
 * Takes care of clean (some of) the ThreadLocals
 * thereby avoiding (well, trying to avoid)
 * OOM (java.lang.OutOfMemoryError) on hot restart...
 * 
 * @see Memory leaks where the classloader cannot be garbage collected
 * @author Cédrik LIME
 * @since 4.1
 */
public class KnownThreadLocalsCleaner implements RequestLifeCycleProvider, RequestExceptionProvider {
	/* From ProviderUtils:
	 * "Providers are cached, keyed by its Interface, and by a ClassLoader.
	 * This enables different WebApps (different ClassLoaders) to have their own set of plugins (same Interface)."
	 * 
	 * Thus we have a copy of plugins per webapp. Which means the ClassLoader is an invariant for each
	 * instance of this class.
	 */

	private Method log4jNDCRemoveMethod;
	private Method log4jMDCContextMethod;
	private Method logBackMDCClearMethod;

	/**
	 * 
	 */
	public KnownThreadLocalsCleaner() {
		super();
		final ClassLoader thisClassLoader = Thread.currentThread().getContextClassLoader();//this.getClass().getClassLoader();
		// Apache Logging Log4J 1.x
		// org.apache.log4j.NDC.remove();
		try {
			Class log4jNdcClass = thisClassLoader.loadClass("org.apache.log4j.NDC");//$NON-NLS-1$
			log4jNDCRemoveMethod = log4jNdcClass.getMethod("remove", null);//$NON-NLS-1$
		} catch (Throwable e) {
			// ignore
		}
		// org.apache.log4j.MDC.getContext().clear();
		try {
			Class log4jMdcClass = thisClassLoader.loadClass("org.apache.log4j.MDC");//$NON-NLS-1$
			log4jMDCContextMethod = log4jMdcClass.getMethod("getContext", null);//$NON-NLS-1$
		} catch (Throwable e) {
			// ignore
		}
		// LOGBack
		// ch.qos.logback.classic.MDC.clear();
		try {
			Class logBackMdcClass = thisClassLoader.loadClass("ch.qos.logback.classic.MDC");//$NON-NLS-1$
			logBackMDCClearMethod = logBackMdcClass.getMethod("clear", null);//$NON-NLS-1$
		} catch (Throwable e) {
			// ignore
		}
	}

	/* (non-Javadoc)
	 * @see clime.messadmin.providers.spi.BaseProvider#getPriority()
	 */
	public int getPriority() {
		return Integer.MAX_VALUE;
	}

	/* (non-Javadoc)
	 * @see clime.messadmin.providers.spi.RequestLifeCycleProvider#requestInitialized(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, javax.servlet.ServletContext)
	 */
	public void requestInitialized(HttpServletRequest request,
			HttpServletResponse response, ServletContext servletContext) {
		// do nothing
	}

	/* (non-Javadoc)
	 * @see clime.messadmin.providers.spi.RequestLifeCycleProvider#requestDestroyed(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, javax.servlet.ServletContext)
	 */
	public void requestDestroyed(HttpServletRequest request,
			HttpServletResponse response, ServletContext servletContext) {
		cleanThreadLocals();
	}

	/* (non-Javadoc)
	 * @see clime.messadmin.providers.spi.RequestExceptionProvider#requestException(java.lang.Exception, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, javax.servlet.ServletContext)
	 */
	public void requestException(Exception e, HttpServletRequest request,
			HttpServletResponse response, ServletContext servletContext) {
		cleanThreadLocals();
	}

	protected void cleanThreadLocals() {
		// ThreadLocals - With Great Power, comes Great Responsibility
		// Can't do anything here. You need to manually set all your ThreadLocals to null yourself (myThreadLocal.remove() or myThreadLocal.set(null))...

		// Apache Logging Log4J 1.x
		// org.apache.log4j.NDC.remove();
		if (log4jNDCRemoveMethod != null) {
			try {
				log4jNDCRemoveMethod.invoke(null, null);
			} catch (Exception e) {
				// do nothing
			}
		}
		// org.apache.log4j.MDC.getContext().clear();
		if (log4jMDCContextMethod != null) {
			try {
				Map context = (Map) log4jMDCContextMethod.invoke(null, null);
				if (context != null) {
					context.clear();
				}
			} catch (Exception e) {
				// do nothing
			}
		}

		// LOGBack
		// ch.qos.logback.classic.MDC.clear();
		if (logBackMDCClearMethod != null) {
			try {
				logBackMDCClearMethod.invoke(null, null);
			} catch (Exception e) {
				// do nothing
			}
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy