Initializing Log4J with Spring?

92,212

Solution 1

You could configure your Log4j listener in the web.xml instead of the spring-context.xml

<context-param>
    <param-name>log4jConfigLocation</param-name>
    <param-value>/WEB-INF/classes/log4j.web.properties</param-value>
</context-param>

<listener>
    <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>

So it is up before Spring starts.

Solution 2

Our standalone application required an SMTPAppender where the email config already exists in a spring config file and we didn't want that to be duplicated in the log4j.properties.

I put the following together to add an extra appender using spring.

<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    <property name="targetObject">
        <bean factory-method="getRootLogger"
              class="org.apache.log4j.Logger" />
    </property>
    <property name="targetMethod">
        <value>addAppender</value>
    </property>
    <property name="arguments">
        <list>
            <bean init-method="activateOptions"
                  class="org.apache.log4j.net.SMTPAppender">
                <property name="SMTPHost" ref="mailServer" />
                <property name="from" ref="mailFrom" />
                <property name="to" ref="mailTo" />
                <property name="subject" ref="mailSubject" />
                <property value="10" name="bufferSize" />
                <property name="layout">
                    <bean class="org.apache.log4j.PatternLayout">
                        <constructor-arg>
                            <value>%d, [%5p] [%t] [%c] - %m%n</value>
                        </constructor-arg>
                    </bean>
                </property>
                <property name="threshold">
                    <bean class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean"
                          id="org.apache.log4j.Priority.ERROR" />
                </property>
            </bean>
        </list>
    </property>
</bean>

We also have a log4j.properties file on the classpath which details our regular FileAppenders.

I realise this may be overkill for what you require :)

Solution 3

Rather than configuring log4j yourself in code, why not just point log4j at your (custom) configuration file's location by adding

-Dlog4j.configuration=.../conf/log4j.xml

to your server's startup properties?

Even better, just move log4j.xml to the default location - on the classpath - and let log4j configure itself automatically.

Solution 4

You can use classpath instead of hardcoded path. It works for me

<bean id="log4jInitializer" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean" depends-on="sbeHome">
    <property name="targetClass" value="org.springframework.util.Log4jConfigurer" />
    <property name="targetMethod" value="initLogging" />
    <property name="arguments">
        <list>
            <value>classpath:/conf/log4j.xml</value>
        </list>
    </property>
</bean>

Solution 5

If you are using Jetty you can add extra classpaths on a per application basis:

http://wiki.eclipse.org/Jetty/Reference/Jetty_Classloading#Adding_Extra_Classpaths_to_Jetty

This will allow you to load your log4 properties in a standard manner (from the classpath:)

in web.xml:

       <listener>
           <listener-class>org.springframework.web.util.Log4jWebConfigurer</listener-class>
       </listener>
       <context-param>
           <param-name>log4jConfigLocation</param-name>
           <param-value>classpath:${project.artifactId}-log4j.properties</param-value>
       </context-param>

in jetty-web.xml:

        <Set name="extraClasspath">
            <SystemProperty name="config.home" default="."/>/contexts/log4j
        </Set>
Share:
92,212
Dave
Author by

Dave

Architect, developer, and most importantly, user.

Updated on February 21, 2020

Comments

  • Dave
    Dave over 4 years

    I have a web app that uses Spring's Log4jConfigurer class to initialize my Log4J log factory. Basically it initializes Log4J with a config file that is off the class path.

    Here is the config:

    <bean id="log4jInitializer" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean" depends-on="sbeHome">
        <property name="targetClass" value="org.springframework.util.Log4jConfigurer" />
        <property name="targetMethod" value="initLogging" />
        <property name="arguments">
            <list>
                <value>#{ MyAppHome + '/conf/log4j.xml'}</value>
            </list>
        </property>
    </bean>
    

    However I get this error at application startup:

    log4j:WARN No appenders could be found for logger

    and tons of Spring application context initialization messages are printed to the console. I think this is because Spring is doing work to initialize my application before it has a chance to initialize my logger. In case it matters, I am using SLF4J on top of Log4J.

    Is there some way I can get my Log4jConfigurer to be the first bean initialized? or is there some other way to solve this?