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

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

Go to download

Notification system and Session administration for J2EE Web Applications

There is a newer version: 4.1.1
Show newest version
/**
 * 
 */
package clime.messadmin.providers.lifecycle;

import java.beans.Introspector;
import java.lang.reflect.Method;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Enumeration;

import javax.servlet.ServletContext;

import clime.messadmin.providers.spi.ApplicationLifeCycleProvider;

/**
 * Takes care of deregistering (some of) the evil Singletons
 * when the app shuts down, thereby avoiding (well, trying to avoid)
 * OOM (java.lang.OutOfMemoryError) on hot restart...
 * 
 * see http://opensource2.atlassian.com/confluence/spring/pages/viewpage.action?pageId=2669
 * 
 * @author Cédrik LIME
 */
public class EvilSingletonsUnregisterer implements ApplicationLifeCycleProvider {

	/**
	 * 
	 */
	public EvilSingletonsUnregisterer() {
		super();
	}

	/**
	 * {@inheritDoc}
	 */
	public int getPriority() {
		return Integer.MAX_VALUE;
	}

	/**
	 * {@inheritDoc}
	 */
	public void contextDestroyed(ServletContext servletContext) {
		// 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))...


		// java.beans.Introspector - Slightly less Evil singleton
		// Flushes the cache of classes
		// Note this is going to clear ALL the classes, regardless of what ClassLoader or application they came from, but its all that available.
		Introspector.flushCaches();

		// Jakarta Commons Logging <= 1.0.4
		// org.apache.commons.logging.LogFactory.release(Thread.currentThread().getContextClassLoader());
		try {
			Class logFactoryClass = Thread.currentThread().getContextClassLoader().loadClass("org.apache.commons.logging.LogFactory");//$NON-NLS-1$
			Method releaseMethod = logFactoryClass.getMethod("release", new Class[] {ClassLoader.class});//$NON-NLS-1$
			releaseMethod.invoke(null, new Object[] {Thread.currentThread().getContextClassLoader()});
		} catch (Throwable t) {
			// ignore
		}

		// Apache Logging Log4J 1.x
		// org.apache.log4j.NDC.remove();
		try {
			Class ndcClass = Thread.currentThread().getContextClassLoader().loadClass("org.apache.log4j.NDC");//$NON-NLS-1$
			Method removeMethod = ndcClass.getMethod("remove", null);//$NON-NLS-1$
			removeMethod.invoke(null, null);
		} catch (Throwable t) {
			// ignore
		}
		// org.apache.log4j.LogManager.shutdown();
		try {
			Class lmClass = Thread.currentThread().getContextClassLoader().loadClass("org.apache.log4j.LogManager");//$NON-NLS-1$
			Method shutdownMethod = lmClass.getMethod("shutdown", null);//$NON-NLS-1$
			shutdownMethod.invoke(null, null);
		} catch (Throwable t) {
			// ignore
		}

		// java.sql.DriverManager - Evil Singleton
		// Although registering the JDBC driver in your web app is a horrible, horrible thing to do (the container should always manage your connections), some apps do just that.
		// Unregister JDBC drivers during shutdown: remove any drivers that were loaded by the same classloader that loaded the web app.
		Enumeration drivers = DriverManager.getDrivers();
		ClassLoader thisClassLoader = Thread.currentThread().getContextClassLoader();//this.getClass().getClassLoader();
		while (drivers.hasMoreElements()) {
			Driver o = (Driver) drivers.nextElement();
			if (o.getClass().getClassLoader() == thisClassLoader){
				// Current driver 'o' is being deregistered
				try {
					DriverManager.deregisterDriver(o);
				} catch (SQLException sqle) {
					//throw new RuntimeException(sqle.getMessage());//new RuntimeException(sqle);
					System.err.println("Failed to cleanup DriverManager for webapp:");
					sqle.printStackTrace();
				}
			} else {
				// Driver 'o' wasn't loaded by this webapp, so no touching it
			}
		}
	}

	/**
	 * {@inheritDoc}
	 */
	public void contextInitialized(ServletContext servletContext) {
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy