To use the data source in my log4j application, I wrote a custom appender. The application is trying to get the data source as a spring bean. However, the application cannot get a bean. I use a technology stack: mybatis, tomcat and spring.
My log4j files look like this:
log4j.category.com.db.wscis.core.web.interceptor=INFO, sql
log4j.appender.sql=com.db.wscis.core.util.appender.CustomJDBCAppender
log4j.appender.sql.sql=INSERT INTO LOGS VALUES ('%x', current_timestamp ,'%C','%p','%m')
log4j.appender.sql.layout=org.apache.log4j.PatternLayout
The code for the user application is as follows:
public class CustomJDBCAppender extends org.apache.log4j.jdbc.JDBCAppender {
protected java.sql.Connection getConnection() throws java.sql.SQLException {
if(connection == null) {
org.springframework.jdbc.datasource.DataSourceTransactionManager dstm = (org.springframework.jdbc.datasource.DataSourceTransactionManager) ExternalBeanFactory.getBean("txManager");
if(dstm==null) throw new java.sql.SQLException("dstm is null");
System.out.println("here");
connection = DataSourceUtils.getConnection(dstm.getDataSource());
return connection;
} else{
return connection;
}
}
protected void closeConnection() throws java.sql.SQLException {
if (connection != null && !connection.isClosed())
connection.close();
}
}
The external Bean factory class is as follows:
package com.db.wscis.core.util;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
public class ExternalBeanFactory implements BeanFactoryAware {
private static BeanFactory beanFactory;
public final void setBeanFactory(final BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
@Deprecated
public static final Object getBean(final String beanName) {
return beanFactory.getBean(beanName);
}
public final Object getBeanInstance(final String beanName) {
return beanFactory.getBean(beanName);
}
}
Now that the tomcat server is starting up, I assume that it is trying to initialize log4j. Thus, it calls the getConnection method in the user application. This inturn calls ExernalFactory.getBean (), however the beanfactory property in the External BeanFactory is not yet initialized. The error stack trace is as follows:
SEVERE: Error configuring application listener of class com.db.wscis.core.web.context.FWContextLoaderLis
java.lang.NullPointerException
at com.db.wscis.core.util.ExternalBeanFactory.getBean(ExternalBeanFactory.java:64)
at com.db.wscis.core.util.appender.CustomJDBCAppender.getConnection(CustomJDBCAppender.java:27)
at org.apache.log4j.jdbc.JDBCAppender.execute(JDBCAppender.java:215)
at org.apache.log4j.jdbc.JDBCAppender.flushBuffer(JDBCAppender.java:289)
at org.apache.log4j.jdbc.JDBCAppender.append(JDBCAppender.java:186)
at org.apache.log4j.AppenderSkeleton.doAppend(AppenderSkeleton.java:251)
at org.apache.log4j.helpers.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.
at org.apache.log4j.Category.callAppenders(Category.java:206)
at org.apache.log4j.Category.forcedLog(Category.java:391)
at org.apache.log4j.Category.log(Category.java:856)
at org.apache.commons.logging.impl.Log4JLogger.info(Log4JLogger.java:176)
at com.db.wscis.core.web.context.FWContextLoaderListener.<init>(FWContextLoaderListener.java:34)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.j
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at java.lang.Class.newInstance(Class.java:374)
at org.apache.catalina.core.DefaultInstanceManager.newInstance(DefaultInstanceManager.java:140)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4888)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5467)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:632)
at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:1073)
at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1857)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)
, , , datasource Bean appender.