java - application - log4j2 jdbc appender
Log4j jdbc appender para DB2 en Tomcat 8 (2)
Intento usar Log4j 2 para guardar los registros generados desde una aplicación web en una tabla en una base de datos DB2 10.5 . Como contenedor de servlets estoy usando Tomcat 8.
La declaración de mi fuente de datos, dentro de context.xml de Tomcat:
<Resource
type="javax.sql.DataSource"
name="jdbc/NCRDS"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
driverClassName="com.ibm.db2.jcc.DB2Driver"
url="jdbc:db2://192.168.1.58:50000/NCR"
username="admin"
password="admin"
initialSize="0"
maxActive="80"
maxIdle = "30"
minIdle="20"
timeBetweenEvictionRunsMillis="30000"
minEvictableIdleTimeMillis="60000"
testOnBorrow="true"
validationQuery="VALUES 1"
validationInterval="30000"
removeAbandoned="true"
removeAbandonedTimeout="60"
logAbandoned="true"
abandonWhenPercentageFull="60"
jdbcInterceptors="org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer"/>
El appender declaró insinde log4j2.xml :
<JDBC name="databaseAppender" tableName="admin.logs">
<DataSource jndiName="java:/comp/env/jdbc/NCRDS" />
<Column name="evendDate" isEventTimestamp="true" />
<Column name="Level" pattern="%level" />
<Column name="Logger" pattern="%logger" />
<Column name="Message" pattern="%msg" />
</JDBC>
El recurso jdbc también se declara en el archivo web.xml de mi aplicación. Si bien he logrado insertar los registros en una base de datos MySQL (cambiando por supuesto la información requerida en mis archivos de configuración), no puedo lograr lo mismo en DB2. La siguiente parte de rastreo de pila es lo que parece estar causando el problema:
Caused by: java.lang.AbstractMethodError: com.ibm.db2.jcc.am.po.setNString(ILjava/lang/String;)V
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.apache.tomcat.jdbc.pool.interceptor.AbstractQueryReport$StatementProxy.invoke(AbstractQueryReport.java:233)
at com.sun.proxy.$Proxy40.setNString(Unknown Source)
at org.apache.logging.log4j.core.appender.db.jdbc.JdbcDatabaseManager.writeInternal(JdbcDatabaseManager.java:110)
at org.apache.logging.log4j.core.appender.db.AbstractDatabaseManager.write(AbstractDatabaseManager.java:167)
at org.apache.logging.log4j.core.appender.db.AbstractDatabaseAppender.append(AbstractDatabaseAppender.java:105)
at org.apache.logging.log4j.core.config.AppenderControl.callAppender(AppenderControl.java:99)
at org.apache.logging.log4j.core.config.LoggerConfig.callAppenders(LoggerConfig.java:430)
at org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:409)
at org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:367)
at org.apache.logging.log4j.core.Logger.logMessage(Logger.java:112)
at org.apache.logging.log4j.spi.AbstractLogger.logMessage(AbstractLogger.java:738)
at org.apache.logging.log4j.spi.AbstractLogger.logIfEnabled(AbstractLogger.java:708)
at org.apache.logging.log4j.spi.AbstractLogger.debug(AbstractLogger.java:237)
at com.ikubinfo.fileservice.FileSystemFileManager.<init>(FileSystemFileManager.java:53)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:147)
... 24 more
Parece que no puedo encontrar ninguna información sobre este error y realmente puedo explicarme qué está pasando mal. Estaría muy agradecido por tu ayuda.
Qué estoy usando: Eclipse Luna, Tomcat 8, DB2 10.5, db2jcc.jar, jdk1.7, log4j requieren tarros .
Esto: Caused by: java.lang.AbstractMethodError: com.ibm.db2.jcc.am.po.setNString
básicamente dice que el controlador de DB2 no implementa el método setNString()
, que Log4j intenta usar at org.apache.logging.log4j.core.appender.db.jdbc.JdbcDatabaseManager.writeInternal(JdbcDatabaseManager.java:110)
.
Ahora, qué hacer al respecto, no puedo decirlo. Puede haber un parámetro que pueda indicar a Log4j que use setString()
lugar, o puede ser que Log4j sea de código abierto, podría editar la clase JdbcDatabaseManager
.
El problema aquí, como mustaccio indicó correctamente, fue que se llamó al método setNString()
que intentaba establecer var args, pero en su lugar, la implementación de log4j2 solo podía ofrecer un método setString()
para una configuración de DB2. Esta llamada fue causada por los nombres de columna definidos. Mi primer caso:
<Column name="Date" isEventTimestamp="true" />
<Column name="Level" pattern="%level" isUnicode="false"/>
<Column name="Logger" pattern="%logger" isUnicode="false"/>
<Column name="Message" pattern="%msg" isUnicode="false"/>
Puede ver que los nombres tienen letras mayúsculas y minúsculas. Ahora tengo dos soluciones:
1. Pude haber agregado la entidad HTML para la comilla, porque DB2 necesita comillas para leer caracteres en minúsculas. Así que la forma final habría sido: <Column name=""Date""
2. El que estoy siguiendo, cambie el nombre de los nombres de tabla a mayúsculas y simplemente haga lo mismo en las referencias de columna en log4j2.xml: <Column name="DATE"