即使配置了log4j.xml,仍无法启用Spring ORM/事务日志记录。

3

我在使用EclipseLink、JPA 2.0和Spring 4.0时,遇到了关于启用与Spring相关的日志记录的配置问题。我需要验证在执行事务时实体管理器何时关闭或清理。

我的应用程序启用了JTA,因此一切都由我的容器(Websphere)控制。以下是我的log4j.xml文件:

<?xml version="1.0"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration debug="true" xmlns:log4j="http://jakarta.apache.org/log4j/">

    <!-- CONSOLE normally used in desktop environment -->
    <appender name="console" class="org.apache.log4j.ConsoleAppender">
        <param name="Encoding" value="UTF-8" />
        <param name="Threshold" value="DEBUG"/>
        <param name="Target" value="System.out" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d [%-8X{context}] %-5p %-40.40c{2} - %m%n"/>
        </layout> 
    </appender>

    <appender name="FILE_APPENDER" class="org.apache.log4j.DailyRollingFileAppender">
        <param name="File" value="C:\\proj\\was\\logs\\spring.log"/>
        <param name="DatePattern" value="'-'yyyy-MM-dd'.txt'"/>
        <param name="Threshold" value="DEBUG"/>
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %-4p [%t] %C{2} - %m%n"/>
        </layout>
    </appender>


    <!-- Spring -->
    <logger name="org.springframework.transaction" additivity="false">
        <level value="DEBUG" />
        <appender-ref ref="FILE_APPENDER"/>
    </logger>

    <logger name="org.springframework.orm.jpa.EntityManagerFactoryUtils" additivity="false">
        <level value="DEBUG" />
        <appender-ref ref="FILE_APPENDER"/>
    </logger>

    <logger name="org.springframework.orm.jpa" additivity="false">
        <level value="DEBUG" />
        <appender-ref ref="FILE_APPENDER"/>
    </logger>



     <root>
        <level value="DEBUG" />
        <appender-ref ref="console" />
        <appender-ref ref="FILE_APPENDER" />
    </root> 

</log4j:configuration>

我也尝试了许多解决方案,比如这个,但都没有帮助。请问我错在哪里?


你的问题是什么?你没有任何日志吗?你缺少日志吗?请注意,Spring使用SLF4J,因此您需要slf4j-log4j12 jar才能在log4j上记录东西。 - wargre
@wargre 我需要将Spring内部的logger.debug()日志记录到我的控制台或已配置的文件中。我已经配置了log4j.xml并拥有必要的JAR包,但仍无法打印日志。我将尝试您提供的slf4j-log4j12 JAR包建议,但是我应该下载哪个版本的JAR包呢? - ngCoder
3个回答

1

从您的评论来看,似乎您没有适配器 slf4j 到 log4j。或者有另一个适配器。

要检查正在使用的适配器,请使用以下代码:

StaticLoggerBinder binder = StaticLoggerBinder.getSingleton();
System.out.println(binder.getLoggerFactoryClassStr());

如果不是log4j12适配器显示:

  • 检查war文件,你应该在WEB-INF/lib目录下拥有一个slf4j-api-xxxx.jar。
  • 将slf4j-log4j12-xxxx.jar(同一版本)放入WEB-INF/lib目录下
  • 如果有logback-xxxxx.jar,请将其删除,否则slf4j会将其记录下来
  • 如果有log4j-over-slf4j-xxxx.jar,请将其删除,否则可能会将log4j日志重定向到slf4j,然后再重定向到log4j等等。
  • 可能会有其他的适配器(例如slf4j-jcl-xxxx.jar)需要被删除。

我的lib文件夹中有以下日志记录jar包 log4j-1.2.9.jar slf4j.api-1.6.1.jar slf4j.jdk14-1.6.1.jar slf4j-log4j12-1.7.12.jar commons-logging.jar commons-logging-1.1.1.jar ------------ 我仍然无法打印日志,我错在哪里了 - ngCoder
我尝试了那段代码,它打印出了"org.slf4j.impl.JDK14LoggerFactory"。 - ngCoder
现在我已经完全移除了 slf4j.jdk14-1.6.1.jar 的依赖,并且它会打印出 "org.slf4j.impl.Log4jLoggerFactory"。 - ngCoder
它在我的\MyApp-EAR\resources\properties\desktop\log4j.xml中,该文件被定义为我的类路径值。 - ngCoder
让我们在聊天中继续这个讨论 - wargre
显示剩余4条评论

0

日志层次结构

在大多数日志系统中,日志记录器具有父子关系,其中子级继承以下内容:

  • 级别
  • 附加器
  • 资源束

从父记录器继承。根记录器位于继承顶部。子记录器将根据additivity将日志事件发送到父记录器。如果为False,则不会将日志发送到父记录器。

因此,从您的原始配置中,您没有允许与Spring相关的记录器将日志发送到根记录器。

建议

现在我们了解到应该将additivity设置为true,并将log4j配置更改为以下内容:

<logger name="org.springframework.transaction" additivity="true"/>

<logger name="org.springframework.orm.jpa.EntityManagerFactoryUtils" additivity="true"/>

<logger name="org.springframework.orm.jpa" additivity="true"/>

 <root>
    <level value="DEBUG" />
    <appender-ref ref="console" />
    <appender-ref ref="FILE_APPENDER" />
</root> 

更多

  • 这里这里是我写的关于slf4j & log4j & logback的博客文章,Spring使用它们,你可以阅读以增强对日志记录的理解;
  • 如果你改变了additivity但仍然无法在控制台/文件中看到日志,我建议你在EntityManagerFactoryUtils中的任何日志记录行上设置断点,然后逐步执行代码以查看问题所在;

更新

EntityManagerFactoryUtils的记录器,在源代码中可以看到,不是slf4j或log4j,而是commons logging。因此,有关此类的log4j配置将无法工作。

import org.apache.commons.logging.Log;

private static final Log logger = LogFactory.getLog(EntityManagerFactoryUtils.class);

为了使您的配置生效,您应该做一些桥接工作
  • 从spring-orm中排除commons-logging.jar
  • 添加jcl-over-slf4j.jar
  • 确保您有slf4j-api和slf4j-log4j

它进入了Jdk14Logger 1.2版本的方法public void debug(Object message) { log(Level.FINE, String.valueOf(message), null); } 仍然无法打印日志。 - ngCoder
我没有使用Maven,而是使用Ant构建的传统应用程序,那么如何实现第一步?从spring-orm中排除commons-logging.jar。 - ngCoder
好的,我没有使用Ant,所以你可以尝试使用这个链接这个问题 - Tony

0

看起来需要清理一下classpath上的Jars,但为了做到这一点,我们需要了解每个Jar的作用。

log4j-1.2.9.jar 是Log4j的实现。使用Log4j进行日志记录以及读取log4j配置文件都需要它。

slf4j.api-1.6.1.jar 是Slf4j API库,仅在您或某些第三方依赖项使用Slf4j进行日志记录时才需要。考虑到您已经在classpath中拥有它,这似乎很可能发生。这使您可以通过Slf4J API写入日志,例如:

private static final Logger LOG = org.slf4j.LoggerFactory.getLogger(MyLoggingClass.class);

slf4j.jdk14-1.6.1.jar 是一个针对Slf4j的JDK 1.4,也被称为java.util.logging绑定,用于在使用Slf4j时作为日志引擎使用java.util.logging。显然,我们将使用log4j作为日志实现,而不是java.util.logging,因此应将其删除。

slf4j-log4j12-1.7.12.jar 是针对Slf4j的log4j 1.2绑定,用于将日志从Slf4j路由到您的Log4j实现。如果需要 slf4j.api-1.6.1.jar ,则仅需要这个。但是,版本应该协调以避免冲突。

commons-logging-1.1.1.jarcommons-logging.jar 据我所知,这两者都是commons logging框架。这是Spring使用的日志框架。但是,您应该只有一个在类路径上,我建议使用显示其版本的那个。

如果您的类路径上有正确的Jars,那么commons logging应该能够为您选择正确的日志实现(在您的情况下是Log4j)。如果不是这种情况,请明确地将一个名为commons-logging.properties的文件放在您的类路径根目录下,并添加以下行:

org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4jLogger

强制使用Log4j作为日志实现。


org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4jLogger 将其添加会抛出类未找到异常,即使JAR包存在于我的lib中。 - ngCoder
你正在运行哪个版本的WebSphere?请确认你使用的commons-logging版本足够新,支持Log4j 1.2,例如1.1.1版本。可通过启用类加载器日志记录来验证正在使用的commons-logging,使用JVM选项-verbose:class。 - JTP
IBM Websphere 8.5.5.8,是的,我有1.1.1版本。 - ngCoder

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接