views:

573

answers:

3

Hi,

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);
A: 

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>
bmargulies
The beens is well initialised, but i still got message from org.springframework.* in stdout.
Antoine Claval
A: 

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
skaffman
+1  A: 

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>
axtavt
Indeed, slf4j seems the way to go. But changing of logging framework for some ( annoying ) un-controled error message seems overkill to me.Or maybe the switch from log4j to slf4j is pain-less ? ( i'm sure that theoricly yes, but i doubt )
Antoine Claval
You shouldn't change your logging framework, because slf4j is only a facade. The config I posted works fine with log4j logging in your code.
axtavt