Question

I use log4j and he work just fine. A log4j.xml file is in my classpath, i use appender and category... again, it's work just fine for my code or code of other librairy.

But the spring classes continue to flood stdout with message i want to log elsewhere. It's beggin to be anoying.

Offending message : org.springframework.jms : some error.... More generally, all classes of the org.springframework package send message to stdout.

So i put this in my log4j.xml :

<appender name="JMS-ERROR" class="org.apache.log4j.RollingFileAppender">
    <param name="File" value="tms.logs.folder/tms.logs.files.prefix-jms-error.log"/>
    <param name="Append" value="true"/>
    <param name="MaxFileSize" value="1000KB"/>
    <param name="MaxBackupIndex" value="2"/>
    <layout class="org.apache.log4j.PatternLayout">
        <param name="ConversionPattern" value="**DVIDEA** %d{dd.MM.yyyy HH:mm:ss} %c  %m%n"/>
    </layout>
    <filter class="org.apache.log4j.varia.LevelRangeFilter">
        <param name="LevelMin" value="DEBUG" />
        <param name="LevelMax" value="FATAL" />
    </filter>
</appender>


<category name="org.springframework.jms" additivity="false">
    <appender-ref ref="JMS-ERROR"/>
</category>

It's work with other librairie. Why not spring ?

I do some research, and it's appeart that Spring use common-logging, and not log4j. It's that a possible cause ? Any workaround ?

I have try to add a log4jConfigurationListener to my web.xml. he's working but i stil dont have any control over the spring error message.

<context-param>
   <param-name>log4jConfigLocation</param-name>
   <param-value>classpath:log4j.xml</param-value>
</context-param>
<context-param>
   <param-name>log4jRefreshInterval</param-name>
   <param-value>10000</param-value>
</context-param>
<listener>
   <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>

Edit :

Some more info :

  • i use Tomcat 5.5
  • a log4j.property ( old log4j config ) is still present for historical reason. I'v try to remove it => no change.

EDIT 2 : I use the following workaround, but i'm not happy with it : it's not configurable

java.util.logging.Logger springLogger = Logger.getLogger("org.springframework.jms");
springLogger.setLevel(Level.OFF);

No correct solution

OTHER TIPS

Note that in the Spring samples they are using slf4j to route log messages from Commons Logging to log4j. In Maven's pom.xml it looks this way:

<!-- Exclude Commons Logging -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>org.springframework.context</artifactId>
    <version>${spring.version}</version>
    <exclusions>
        <!-- Exclude Commons Logging in favor of SLF4j -->
        <exclusion>
            <groupId>org.apache.commons</groupId>
            <artifactId>com.springsource.org.apache.commons.logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>

<!-- Add slf4j API -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>com.springsource.slf4j.api</artifactId>
    <version>${slf4j.version}</version>
</dependency>

<!-- Add Commons Logging -> slf4j bridge -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>com.springsource.slf4j.org.apache.commons.logging</artifactId>
    <version>${slf4j.version}</version>
    <scope>runtime</scope>
</dependency>

<!-- Add slf4j -> log4j bridge -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>com.springsource.slf4j.log4j</artifactId>
    <version>${slf4j.version}</version>
    <scope>runtime</scope>
</dependency>

You might need:

<bean id="log4jInitialization"
    class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
        <property name="targetClass"
            value="org.springframework.util.Log4jConfigurer" />
        <property name="targetMethod" value="initLogging" />
        <property name="arguments">
            <list>
                <value>conf/log4j.xml</value>
            </list>
        </property>
    </bean>

Spring uses Apache Commons Logging, which in turn decides whether to use STDOUT (via java.util.logging) or Log4j. If you're getting Spring output on STDOUT, then commons-logging hasn't located log4j for some reason.

If you set the system property org.apache.commons.logging.diagnostics.dest, commons-logging can be configured to log its diagnostics, telling you what steps it is taking to determine in log4j is present.

So in your tomcat startup script, set the system property, e.g.

-Dorg.apache.commons.logging.diagnostics.dest=STDOUT

You must use SLF4J, and include the bridge to the logging platform you want (log4j) but you must also exclude commons-logging from all the other places it might be pulled in. It helps to have an IDE to do this, or you can put a dummy entry in for commons-logging. For details on that, see the SLF4J FAQ entry

A previous answer mentioned using the com.springsource artifacts, however if you are using Maven Central the right way to do it is:

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.7.10</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.10</version>
</dependency>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow