2017-01-11 122 views
0

我已经在Spring配置中定义了一个数据源。log4j2 JDBCAppender with spring

<bean id="dataSource" 
    class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 

    <property name="driverClassName" value="com.mysql.jdbc.Driver" /> 
    <property name="url" value="jdbc:mysql://localhost:3306/db" /> 
    <property name="username" value="root" /> 
    <property name="password" value="password" /> 
</bean> 

对于LOG4J2 JDBCAppender,我知道我们需要获得数据源:

<JDBC name="databaseAppender" tableName="error_log"> 
     <ConnectionFactory class="net.example.db" 
      method="getDatabaseConnection" /> 
     <Column name="EVENT_DATE" isEventTimestamp="true" /> 
     <Column name="LEVEL" pattern="%level" /> 
     <Column name="LOGGER" pattern="%logger" /> 
     <Column name="MESSAGE" pattern="%message" /> 
     <Column name="THROWABLE" pattern="%ex{full}" /> 
    </JDBC> 

我已经添加了封装成组件扫描:

<context:component-scan base-package="com.test,net.example.db" /> 

而在添加注释作为组件的类ConnectionFactory

import java.sql.Connection; 
import javax.sql.DataSource; 

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.stereotype.Component; 

@Component 
public class ConnectionFactory { 

    @Autowired 
    private DataSource dataSource; 

    public void setDataSource(DataSource dataSource) { 
     this.dataSource = dataSource; 
    } 

    public Connection getDatabaseConnection() throws Exception { 
     return dataSource.getConnection(); 
    } 

} 

不过,我得到空当调用getDatabaseConnection()

2017-01-14 14:17:24,579 localhost-startStop-1 ERROR JdbcDatabaseManager jdbcManager{ description=databaseAppender, bufferSize=0, connectionSource=factory{ public static java.sql.Connection net.example.db.ConnectionFactory.getDatabaseConnection() }, tableName=error_log, columns=[ { name=EVENT_DATE, layout=null, literal=null, timestamp=true }, { name=LEVEL, layout=%level, literal=null, timestamp=false }, { name=LOGGER, layout=%logger, literal=null, timestamp=false }, { name=MESSAGE, layout=%message, literal=null, timestamp=false }, { name=THROWABLE, layout=%ex{full}, literal=null, timestamp=false } ] } Could not perform database startup operations: java.sql.SQLException: Failed to obtain connection from factory method. java.sql.SQLException: Failed to obtain connection from factory method. 
    at org.apache.logging.log4j.core.appender.db.jdbc.FactoryMethodConnectionSource$1.getConnection(FactoryMethodConnectionSource.java:107) 
    at org.apache.logging.log4j.core.appender.db.jdbc.FactoryMethodConnectionSource.getConnection(FactoryMethodConnectionSource.java:53) 
    at org.apache.logging.log4j.core.appender.db.jdbc.JdbcDatabaseManager.startupInternal(JdbcDatabaseManager.java:60) 
    at org.apache.logging.log4j.core.appender.db.AbstractDatabaseManager.startup(AbstractDatabaseManager.java:65) 
    at org.apache.logging.log4j.core.appender.db.AbstractDatabaseAppender.start(AbstractDatabaseAppender.java:89) 
    at org.apache.logging.log4j.core.config.AbstractConfiguration.start(AbstractConfiguration.java:255) 
    at org.apache.logging.log4j.core.LoggerContext.setConfiguration(LoggerContext.java:530) 
    at org.apache.logging.log4j.core.LoggerContext.start(LoggerContext.java:258) 
    at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:239) 
    at org.apache.logging.log4j.core.config.Configurator.initialize(Configurator.java:158) 
    at org.apache.logging.log4j.web.Log4jWebInitializerImpl.initializeNonJndi(Log4jWebInitializerImpl.java:168) 
    at org.apache.logging.log4j.web.Log4jWebInitializerImpl.start(Log4jWebInitializerImpl.java:110) 
    at org.apache.logging.log4j.web.Log4jServletContainerInitializer.onStartup(Log4jServletContainerInitializer.java:57) 
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5604) 
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:147) 
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1571) 
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1561) 
    at java.util.concurrent.FutureTask.run(FutureTask.java:266) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
    at java.lang.Thread.run(Thread.java:745) 
Caused by: java.lang.NullPointerException 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:497) 
    at org.apache.logging.log4j.core.appender.db.jdbc.FactoryMethodConnectionSource$1.getConnection(FactoryMethodConnectionSource.java:105) 
    ... 20 more 

我怀疑是否bean的数据源尚未建立时LOGJ2调用getDatabaseConnection()。请让我知道是什么原因和解决方案。

+0

为什么不?是的,你可以提供连接工厂类是组件扫描的一部分,并创建它的一个bean。 – Barath

+0

嗨,Barath,请在帖子中看到我的更新。我已经实现了你提到的要点,但是我得到了dataSource的空值。 – user2051823

+0

ConnectionFactory的软件包名称是什么。确保它是组件扫描基础软件包的一部分 – Barath

回答

2

请通过本教程[Log4j2 JDBC(http://self-learning-java-tutorial.blogspot.in/2015/10/log4j2-jdbcappender-write-log-messages.html

如前所述:请参见本部分

以下是连接工厂参数。

Class : Name of the class, that contains a static factory method for obtaining JDBC connections. 
method : The name of a static factory method for obtaining JDBC connections. Method return type must be either java.sql.Connection or DataSource. 

请注意,它需要一个静态工厂方法。这就是为什么调用反射失败。

+0

谢谢,但ConnectionFactory可以从spring bean中获取数据源吗? – user2051823

+0

我不确定。你可以添加构造函数并将其打印出来吗?或者使用@PostContruct public void init {sop(“data source”+ dataSource)}来标识bean是否被创建 – Barath

+1

谢谢Barath,我遵循了另一篇文章的回答,现在问题得到解决 – user2051823