【问题标题】:log4j2 JDBCAppender with Spring带有 Spring 的 log4j2 JDBCAppender
【发布时间】:2017-05-26 14:36:39
【问题描述】:

我已经在 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() 时我得到了 null

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

我怀疑 LOGJ2 调用 getDatabaseConnection() 时是否还没有创建 bean 数据源。请告诉我是什么原因和解决方案。

【问题讨论】:

  • 为什么不呢?是的,您可以提供连接工厂类是组件扫描的一部分,并创建它的 bean。
  • 嗨 Barath,请在帖子中查看我的更新。我已经实现了您提到的要点,但是我的 dataSource 为空。
  • ConnectionFactory 的包名是什么。确保它是组件扫描基础包的一部分
  • 我已经在组件扫描中添加了包名:包名是net.example.db,如问题中所述。
  • Log4J 没有从 Spring 上下文中获取 ConnectionFactory。所以 Spring 不知道这个对象,也不会在其中注入任何东西。顺便说一句,即使 log4j 使用了 spring 上下文,您的连接工厂也在包 hk.gov.lcsd.mois.logging 中,而您只是在扫描包 com.test,net.example.db。最后,您错过了文档的一个重要部分:无论您采用哪种方法,都必须有连接池支持。否则,日志记录性能将受到很大影响

标签: spring log4j2


【解决方案1】:

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

如前所述:请看这部分

以下是 ConnectionFactory 参数。

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.

请注意,它需要静态工厂方法。这就是反射调用失败的原因。

【讨论】:

  • 谢谢,ConnectionFactory可以从spring bean获取数据源吗?
  • 我不确定。你可以添加构造函数并打印出来吗?否则使用@PostContruct public void init { sop(" data source "+dataSource) } 来识别bean是否被创建
  • 谢谢Barath,我按照另一个帖子的答案,现在问题已经解决了
【解决方案2】:

最后我找到了一个解决方案。 LOG4J 在 Spring 之前初始化,因此 bean Datasource 将返回 null。

我按照以下 URL 中的说明进行操作: How to use Spring BoneCPDataSource bean as data source for Log4j 2 JDBC appender?

现在一切都很好。

【讨论】:

    猜你喜欢
    • 2014-02-14
    • 2021-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-07
    • 2017-05-18
    • 2017-06-14
    • 2017-01-23
    相关资源
    最近更新 更多