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

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

Tomcat subir formularios de mas de 2MB

Recientemente necesitaba enviar a través del formulario una factura firmada. Las facturas no suelen ocupar mas de 100KB, pero cuando agregas adjuntos a la factura, este tamaño se puede incrementar hasta el infinito.

Estamos en el caso de un formulario normal, no un multipart. Para los multipart no hace falta nada de esta configuración. Los formularios multipart, son formularios de subida de ficheros, donde dentro del formulario existe un input del tipo «file». Yo necesitaba hacerlo transparente al usuario, que firme a través de la web y el proceso de grabado se realice sin mas interacción que la contraseña de su certificado.

El problema lo he tenido en dos sitios:

  • en el Applet de @firma. No puede firmar ficheros de mas de 2MB.
  • en el Tomcat, era incapaz de subir a traves del formulario ficheros de mas de 2MB.

Para estos dos problemas finalmente después de muchas horas de trabajo, he encontrado dos soluciones:

  • sustituir el Applet por el MiniApplet de @firma. Esta es una version mas reciente, mas rápida y eficiente, del cual no se cual es el limite máximo de ficheros a firmar, pero es bastante mas elevado. Creo que leí que estaba entorno a los 64MB. Pero seguro que depende de la capacidad de memoria y de procesamiento del ordenador cliente. El cambio no es nada doloroso.
  • en Tomcat y en la mayoría de servidores existe un máximo tanto para el GET como para el POST. Si bien el estándar no pone limites. En los navegadores, excluyendo Internet Explorer, para el POST no han puesto limite, pero si para el GET. En ambos casos se pretender prevenir un ataque de denegación de servicio.

Limite para el POST: en tomcat por defecto es de 2 MB. Para incrementarlo o dejarlo indefinido se utiliza el parametro: maxPostSize. En el manual de Tomcat, aparece como configurar este parámetro, debe ser configurado en bytes. Dentro de los Connectors.

    <Connector port="8080" protocol="org.apache.coyote.http11.Http11Protocol"
               connectionTimeout="20000"
               maxPostSize="2000000"
               redirectPort="8443" />

Opciones:

  • maxPostSize=»2000000″. 2MB por defecto, no hace falta indicarlo.
  • maxPostSize=»-1″. Ilimitado, también indican que se puede poner maxPostSize=»0″.
  • maxPostSize=»6000000″. 6MB aproximadamente.

¿En que conectores ponerlo?, en todos, en los HTTP y en los AJP que redirijen el trafico.

En el caso de que tengas un cluster de Tomcat’s con un Apache delante, quizás es necesario que indiques también esta capacidad al Apache, en el httpd.conf.

Tomcat subir formularios de mas de 2MB

Tomcat error APR version 1.1.22

¿Como solucionar este error?

26-mar-2014 9:21:21 org.apache.catalina.core.AprLifecycleListener init
GRAVE: Se encuentra instalada una versión incompatible 1.1.22 de la biblioteca nativa APR de Apache Tomcat, mientras que Tomcat necesita la versión 1.1.24

Para Windows:
te descargas de aqui, la «tomcat-native-1.1.29-win32-bin.zip». Descomprimes y copias en la carpeta tomcat/bin el tcnative-1.dll

En esta pagina dicen como compilar e instalar las fuentes.

Para linux (no lo he probado)

#!/bin/bash
# By Guido Medina
# http://stackoverflow.com/questions/18109722/an-incompatible-version-1-1-22-of-the-apr-based-apache-tomcat-native-library-is

export APR_PATH=/usr/bin/apr-1-config
export JAVA_HOME=/opt/java
export TOMCAT_HOME=/opt/tomcat
export INSTALL_PREFIX=/usr

wajig install libaprutil1-dev make

cd /tmp
rm -Rf tomcat-native-*
tar -zxf $TOMCAT_HOME/bin/tomcat-native.tar.gz
cd /tmp/tomcat-native-*/jni/native

./configure --with-apr=$APR_PATH --with-java-home=$JAVA_HOME --prefix=$INSTALL_PREFIX
make && make install

sacado de sourceforge

Tomcat error APR version 1.1.22

Problemas con el log en tomcat


Depuracion de log4j en el propio log


Para depurar log4j en Tomcat puedes usar -Dlog4j.debug al ejecutar tomcat.
En mi caso lo he añadido dentro de la variable JAVA_OPTS que esta en el fichero catalina.sh. Que es quien me arranca Tomcat.
Tambien se puede incluir como parte de la variable CATALINA_OPTS


ERROR Attempted to append to closed appender named


Cuando te da el error:

log4j:ERROR Attempted to append to closed appender named [pepito]

Pueden ocurrir dos cosas:

  1. has repetido el nombre de ese appender dentro de la configuracion del log.
  2. log4j se inicia dos veces. Al arrancar la primera vez, lanza el appender y le agrega los distintos loggers. Pero cuando se arranca por segunda vez… Se borra y carga de nuevo. Si tienes dos ficheros, por el motivo que sea, solo se va a cargar el que lea en 2º lugar. Evita este comportamiento.
    En mi caso, yo tenia mi fichero log4j.xml y luego mi aplicacion estaba configurada para que spring levantase el log. Aqui esta mi dualidad.
Problemas con el log en tomcat

Debuguear Tomcat en Eclipse

Necesidad:
Quiero poder debuguear los portlets que tengo en Tomcat-Liferay en mi Eclipse IDE.

Pasos:
1.- Arrancar tomcat con jpda activo:

# Arrancar tomcat con jpda activo:
/cygdrive/c/Software/liferay/liferay-portal-6.1.1-ce-ga2_depo/tomcat-7.0.27/bin/catalina.sh jpda start

2.- Configurar en eclipse en «Run Debug» un «Remote Java Aplication»:
Ir al boton Run Debug/Debug Configurations

En Remote Java Aplication boton derecho «New». En la pestaña conecction

En la pestaña source

En la pestaña common

Opciones:

# ver los logs de tomcat
tail -f /cygdrive/c/Software/liferay/liferay-portal-6.1.1-ce-ga2_depo/tomcat-7.0.27/logs/catalina.out
Debuguear Tomcat en Eclipse