November 29
Configuring log4j through Spring
by Don Brinker
As I mentioned in a previous post, in order to have different log4j settings in different environments without an environment-specific build, you need to allow Spring to manage the log4j configuration. Now there is currently no way to specify that in the Application Context itself, but a post in the Spring Support Forums suggests an alternate approach.
If you define the following custom bean:
package com.molecular.util.logging; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Log4jConfigurer; /** * A simple Spring Bean that allows log configuration to be managed in the Application Context * * Originally by Daniel Rijkhof (daniel.rijkhof@gmail.com) */ public class Log4jDirectConfigurer implements InitializingBean { private String location; private long refreshInterval; public void afterPropertiesSet() throws Exception { if (location == null) { return; } if (refreshInterval == 0) { Log4jConfigurer.initLogging(location); } else { Log4jConfigurer.initLogging( location, refreshInterval); } } // Attribute injectors public void setLocation(String location) { this.location = location; } public void setRefreshInterval(long refreshInterval){ this.refreshInterval = refreshInterval; } }
You can then define the location of the log4j configuration in the Spring Context. Remembering that in the earlier discussion we were using the system property env to denote the environment we’re running:
<bean id="log4jDirectConfigurer" class="com.molecular.util.logging.Log4jDirectConfigurer"> <property name="location" value="classpath:log4j-${env}.properties"/> <property name="refreshInterval" value="0"/> </bean>
Alternately, you can store the name of the log file in the system properties file. This is useful when the file name will vary wildly between installations:
<bean id="log4jDirectConfigurer" class="com.molecular.util.logging.Log4jDirectConfigurer"> <property name="location" value="${logging.location}"/> <property name="refreshInterval" value="0"/> </bean>
In either case, there’s no need to call the code directly, since Spring will execute afterPropertiesSet automatically during the setup phase.Now as with everything, this has limitations. This only handles information that is logged following bean initialization. Anything that happens during initialization (either in Spring or in your own code) will not be logged to these files. If your application does very little at initialization (which is fairly common) this may still work for you.
Edit: As Ken pointed out below, I’d removed a log directory from the underlying code, but forgotten to remove it from the configs. That’s fixed now.