views:

217

answers:

1

Hello. My current build lead has a great idea in theory - construct a custom Log4J appender that takes in Spring-managed beans and uses them to log errors to various other sources than just the standard log file. However, other than creating a singleton initialized at startup with the application context (code in just a moment), I can't seem to think of any other options of retrieving a Spring managed bean in a Log4J appender.

public class SpringSingleton implements ApplicationContextAware {
    private static ApplicationContext context;
    public SpringSingleton() {
        super();
    }
    public static ApplicationContext getContext() {
        return SpringSingleton.context;
    }
    public void setApplicationContext(ApplicationContext context) {
        if(SpringSingleton.context != null) {
            throw new IllegalStateException("Context is already set!");
        }
        SpringSingleton.context = context;
    }
}

Ideally, these properties could be set just like beans in Spring via dependency injection - the bean references will never change, no matter how many appenders are initialized. Any ideas?

+1  A: 

You're going to have a boostrap problem since log4j has to be initialized before Spring. Whether you're using a custom configuration or Log4j's standard initializer, it has to be up before application context is.

Now, you could in theory make your custom appenders "lazily" initialize themselves (either via approach you've suggested above or by making appenders themselves "semi" singletons - e.g. appender class has a static instance field which gets populated by afterPropertiesSet() method; that way you can create appender itself as bean within Spring) but it seems somewhat messy and inconsistent.

Another approach is to dynamically reconfigure Log4j once Spring context is initialized; e.g. write a listener to catch a ContextStartedEvent, obtain all beans of type Appender from the context and add them to Log4j configuration. This will also allow you to create your appenders as beans but avoid singleton mess somewhat.

ChssPly76
Oooh...I like the listener idea. I'll pass that along. I'll wait for additional answers, though, as you don't seem to be quite hurting for rep :) +1.
MetroidFan2002
Hey, hey - to misquote Rich Texan from Simpsons (http://www.imdb.com/title/tt1023430/quotes) "I've worked hard to ill-get this rep" :-)
ChssPly76
Good stuff. Apparantly we already do have a BeanFactoryPostProcessor implementation that does allow setting an additional appenders array, so we'll use that, but since no-one has answered the question and this certainly fits, you get more rep :)
MetroidFan2002