Prevent Tomcat C3p0 memory leaks

Create a class:

public class RemoveTomcatC3P0Connections implements ServletContextListener {

	private static final Logger LOGGER = LoggerFactory.getLogger(RemoveTomcatC3P0Connections.class);

	@Override
	public void contextInitialized(ServletContextEvent sce) {
		// TODO Auto-generated method stub

	}

	@Override
	public void contextDestroyed(ServletContextEvent sce) {
		// This manually deregisters JDBC driver, which prevents Tomcat 7 from complaining about memory leaks wrto this class
		Enumeration<Driver> drivers = DriverManager.getDrivers();
		while (drivers.hasMoreElements()) {
			Driver driver = drivers.nextElement();
			try {
				DriverManager.deregisterDriver(driver);
				LOGGER.info(String.format("deregistering jdbc driver: %s", driver));
			} catch (SQLException e) {
				LOGGER.info(String.format("Error deregistering driver %s", driver), e);
			}

		}

		XmlWebApplicationContext xmlWebApplicationContext = (XmlWebApplicationContext) WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext());
		if(xmlWebApplicationContext == null) {
			LOGGER.info("No se ha podido recuperar el contexto de Spring por segunda vez");
		}else if(xmlWebApplicationContext != null) {
			try {
				com.mchange.v2.c3p0.ComboPooledDataSource pool = (com.mchange.v2.c3p0.ComboPooledDataSource) xmlWebApplicationContext.getBean("dataSource");
				LOGGER.info("Se procede a cerrar las conexiones de la url: " + pool.getJdbcUrl());
				pool.close(true);
				LOGGER.info("Se cierra la conexion con el Pool de C3P0");
			} catch (Exception e) {
				LOGGER.info("Error al cerrar la conexion con el Pool de C3P0", e);
			}
		}

	}

}

Add to web.xml:

	<listener> 
		<listener-class> 
			mi.paquete.RemoveTomcatC3P0Connections
		</listener-class>
	</listener>

log:

15:36:28.051 [ContainerBackgroundProcessor[StandardEngine[Catalina]]] INFO  e.t.a.p.r.c.RemoveTomcatC3P0Connections - deregistering jdbc driver: sun.jdbc.odbc.JdbcOdbcDriver@4fda99
15:36:28.051 [ContainerBackgroundProcessor[StandardEngine[Catalina]]] INFO  e.t.a.p.r.c.RemoveTomcatC3P0Connections - deregistering jdbc driver: oracle.jdbc.OracleDriver@2d405a
15:36:28.051 [ContainerBackgroundProcessor[StandardEngine[Catalina]]] INFO  e.t.a.p.r.c.RemoveTomcatC3P0Connections - deregistering jdbc driver: net.sf.log4jdbc.DriverSpy@f72dd7
16:21:26.880 [ContainerBackgroundProcessor[StandardEngine[Catalina]]] INFO  e.t.a.p.r.c.RemoveTomcatC3P0Connections - Se procede a cerrar las conexiones de la url: jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=10.3.2.44) (PORT=1521))(CONNECT_DATA=(SERVICE_NAME=orcl)))

Be carefull with net.sf.log4jdbc.Log4jdbcProxyDataSource, it´s a wrapper for log not a Data Source.

Prevent Tomcat C3p0 memory leaks

addProxy

gist

	public static void addProxy(String user, String pass, String host, String port) {

		if(user!= null && pass != null) {
			final String authUser = user;
			final String authPassword = pass;

			Authenticator.setDefault(
					new Authenticator() {
						public PasswordAuthentication getPasswordAuthentication() {
							return new PasswordAuthentication(
									authUser, authPassword.toCharArray());
						}
					}
			);

			System.setProperty("http.proxyUser", authUser);
			System.setProperty("http.proxyPassword", authPassword);
		}

		System.setProperty("http.proxyHost", host);
		System.setProperty("http.proxyPort", port);
	}
addProxy

JPopulator

He usado la libreria jPopulator para rellenar unos beans y mockear el comportamiento de unos algoritmos.

Estoy intentando mockear un Web Service. Y estaba rellanado los bean generados con la herramienta cxf codegen. Estas herramientas son geniales super útiles, pero los bean no cumplen los estandars. Por ejemplo:

public class ArrayOfPCGError {
    protected List<PCGError> pcgError;

    public List<PCGError> getPCGError() {
        if (pcgError == null) {
            pcgError = new ArrayList<PCGError>();
        }
        return this.pcgError;
    }
}

En esta clase no hay metodo set y el metodo getPCGError no cumple con el atributo «pcgError». Debiera ser: getPcgError()

Si le dices a jPopulator que te lo rellene, salta una excepcion.

nov 11, 2014 XX:XX:20 PM io.github.benas.jpopulator.impl.PopulatorImpl populateBeanWithExcludeFields
GRAVE: Unable to populate an instance of type class xxx.yyy.zzz.ArrayOfPCGError
java.lang.NoSuchMethodException: Unknown property 'pcgError' on class 'class xxx.yyy.zzz.ArrayOfPCGError'

¿Como solucionarlo?. Añadiendo a la libreria una nueva funcionalidad. La de excluir algunos metodos. HE añadido a la interfaz Populator el siguiente metodo:

public interface Populator {
    //...
    <T> T populateBeanWithExcludeFields(Class<T> type, String... excludeFieldsName);
}

He implementao el metodo resultante sin repetir codigo y he realizado los test.

Espero lo agreguen como funcionalidad, mientras lo tengo compilado en mi maven, en local.

JPopulator

Reflection: Prohibited package name

Estaba invocando una clase para hacer reflexión sobre ella y llamar a un método especifico. Esta clase tenia un paquete que se denomina tal que asi:
java.xxx.yyy.clase.java

Y me salta en las pruebas un error tal que:

java.lang.SecurityException: Prohibited package name: java.xxx.yyy

Motivo: aquellos paquetes que empiezan por ‘java.‘ están «reservados», es decir no se puede hacer reflexión sobre ellos pues en su código fuente así lo especifica. En la clase ClassLoader. Aquí el fragmento:

//...
private ProtectionDomain More preDefineClass(String name, ProtectionDomain protectionDomain) {
        if (!checkName(name))
            throw new NoClassDefFoundError("IllegalName: " + name);

        if ((name != null) && name.startsWith("java.")) {
            throw new SecurityException("Prohibited package name: " +
                                        name.substring(0, name.lastIndexOf('.')));
        }
        if (protectionDomain == null) {
            protectionDomain = getDefaultDomain();
        }

        if (name != null)
            checkCerts(name, protectionDomain.getCodeSource());

        return protectionDomain;
    }
//...
Reflection: Prohibited package name

@Transactional y @Rollback en Spring JDBC

Estoy en un proyecto en el que he abandonado Hibernate. Prefiero tener el control de las queries. Realmente no van a ser unas queries poderosas, pero tambien es cierto que realmente no entiendo la ventaja de Hibernate. Y para colmo no tengo acceso a ningun curso, con el cual pueda abrir los ojos.

He decidido probar Spring JDBC. Uso NamedParameterJdbcTemplate para todas las operaciones. Esto implica no tener que estar inyectando el DataSource por todos los lados. Simplificación y legibilidad.

Con el paso de los días, y en progresión a la experiencia. Decidí hacer test, pero sin grabar en bbdd. Haciendo rollback. Así me queda un proyecto tan completo como los que he realizado con Hibernate. Añadí a mi fichero de configuración de Spring:


    <tx:annotation-driven proxy-target-class="true" transaction-manager="transactionManager" />

    <bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>

y en los métodos en los que se hace insert, update ó delete, indico la anotación @Transactional

	@Transactional
	protected void update(String query, T bean) {
	      // ...
	}

Ahora bien, en los test. He estado probando y realizando pruebas para saber concretamente el uso que tiene Transactional y Rollback.

  • Si pones solo Transacctional , hara rollback, cuando se lance alguna excepción no cacheadas (derivadas de RuntimeException). Dentro de la anotación puedes indicarle otras opciones.
  • Si acompañas la anotacion @Transacctional con @Rollback (por defecto es true), estas indicando que siempre se va a hacer Rollback. Mediante la anotacion Rollback, estas sobreescribiendo el comportamiento de Transacctional, referente a los rollback.
  • 	@Test
    	@Transactional
    	@Rollback
    	public void testSave() {
    	      // ...
    	}
    

    Indicar @Transacctional en el metodo de test, es sobreescribir el comportamiento de @Transacctional en el metodo a testear.

El Javadoc de Rollback dice:

Test annotation to indicate whether or not the transaction for the annotated
test method should be rolled back after the test method has
completed. If {@code true}, the transaction will be rolled back;
otherwise, the transaction will be committed.

@Transactional y @Rollback en Spring JDBC

Vagrant

Me acabo de terminar de leer: «Creating Development Environments with Vagrant«.

Un libro que se lee muy rapido, apenas llega a las 100 paginas. Pero ha satisfecho todas mis dudas sobre que y para que usar Vagrant.

Tengo que decir que no lo he probado, todas estas conclusiones derivan de la lectura de este libro.

Vagrant es un sistema de virtualizacion, que tiene como base VirtualBox. La diferencia con respecto a otros sistemas de virtualizacion, es que este sistema se basa en un fichero de configuracion en el cual se indica, el Sistema Operativo y todas las librerias o productos que se quieren instalar dentro. De manera que si exportas ese fichero de configuracion a otra persona, tiene exactamente el mismo sistema. Solo compartiendo un fichero, que no pesa.

Para configurar el sistema internamente puedes usar tres herramientas, ssh, puppet y chef. Estas ultimas son automatizadores de instalación y configuración de programas. El libro dedica una capitulo a cada configurador de programas. Y en un solo capitulo te explica como usarlos. De hecho podrias usar los tres a la vez.

Es insteresante como puedes montar un entorno de mas de un servidor. Por ejemplo Liferay en un server y MySQL en otro. Todo esta configuracion dentro del mismo fichero Vagrant.

Ahora bien, he estado mirando que es Docker, y creo que ya no es necesario usar Vagrant. Pero esto va en otro post.

Vagrant

Probar JavaScript desde el navegador

El site ws3schools.com tiene unos tutoriales bastante sencillos para probar el codigo javascript.

La web me ha resultado muy «user-friendly» y entre un compañero y yo lo hemos sacado de esa web y hemos creado un fichero html. Cuando queramos probar pequeños codigos javascript ya tenemos una plataforma.

He creado mi repositorio personal: javascript_web_test

Evidentemente tambien hay herramientas on-line como: jsfiddle.net

Probar JavaScript desde el navegador

tomcat java.io.IOException: Cannot recover key

Esto sucede cuando copias la carpeta tomcat y le insertas en otro ordenador.

Nos ubicamos en la carpeta:
tomcat/conf

eliminamos el alias tomcat del almacen de claves:

keytool -delete -alias tomcat

Generamos un nueco alias tomcat y guardamos el keystore:

keytool -genkey -alias tomcat -keyalg RSA -keystore keystore_tomcat.jks
pass(changeit)

otra opcion:

keytool -genkey -v -alias tomcat -keyalg RSA -validity 3650 -keysize 2048 -keystore keystore_tomcat.jks -storepass changeit -keypass changeit

Configuramos Tomcat para acceso-https:
tomcat/conf/server.xml:

		<Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol" SSLEnabled="true"
				maxThreads="150" scheme="https" secure="true"
				keystoreFile="conf/keystore_tomcat.jks"
				keystorePass="changeit"
				clientAuth="false" sslProtocol="TLS" />
tomcat java.io.IOException: Cannot recover key