2

Using AspectJ I've injected service into non-managed domain object: This is service:

@Service
public class DomainServiceImpl implements DomainService { 
     public String getLoggerMessage(String prevMessage) {
            return String.format("Message from logger service:%s", prevMessage);
    }
}

This is domain object:

@Configurable(dependencyCheck = true)
public class DomainObject {
    private IAppenderService appenderService;
    @Autowired
    public void setAppenderService(IAppenderService appenderService) {
        this.appenderService = appenderService;
    }
    public IAppenderService getAppenderService() {
        return appenderService;
    }   

    public String formMessage(String message){      
        return appenderService.getLoggerMessage(message);
    }   
}

Following test was successfull:

@Test
    public void testAppender(){
        DomainObject domainObject = new DomainObject();
        assertNotNull(domainObject.getAppenderService());
    }

and if I add

System.out.println(new DomainObject().formMessage("test message"));

to any controller i've got expected string in console: "Message from logger service:test message"

Then I try use this service into custom slf4j appender:

@Configurable(dependencyCheck = true)
public class MyAppender extends AppenderSkeleton {  
    IAppenderService    appenderService;        
    @Autowired
    public void setAppenderService(IAppenderService appenderService) {
        this.appenderService = appenderService;
    }
    public IAppenderService getAppenderService() {
        return appenderService;
    }
    @Override
    public void close() {
    }
    @Override
    public boolean requiresLayout() {       
        return false;
    }
    @Override
    protected void append(LoggingEvent event) {     
        System.out.println(new DomainObject().formMessage(event.getMessage().toString()));
    }
}

but gotta the NPE:

java.lang.NullPointerException
    at sbk.spring.testaopjc.domain.DomainObject.formMessage(DomainObject.java:19)
    at sbk.spring.testaopjc.appender.MyAppender.append(MyAppender.java:29)
    at org.apache.log4j.AppenderSkeleton.doAppend(AppenderSkeleton.java:251)

at same time following test was successfull:

public void testAppendeSecond(){
        MyAppender appender = new MyAppender();
        assertNotNull(appender.getAppenderService());
    }

Can anybody explain me why MyAppender behaves differently in this cases? PS:My log4j.properties file:

 log4j.rootLogger=INFO, STDOUT

 log4j.appender.STDOUT=sbk.spring.testaopjc.appender.MyAppender
 log4j.appender.STDOUT.layout=org.apache.log4j.PatternLayout
 log4j.appender.STDOUT.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%M:%L - %m%n
Serhii Soboliev
  • 820
  • 1
  • 13
  • 21

2 Answers2

1

This is occuring because log4j is being bootstrapped before Spring.

The following answer may help with providing a possible solution for the issue:

log4j - Accessing spring bean from logging appender class - Stack Overflow

Community
  • 1
  • 1
bertybro
  • 600
  • 5
  • 5
0

This idea has been discussed before, maybe not in the exact same configuration, but somewhat similar. Basically, it's about using something Spring-managed in a log4j powered environment. And is not easy to do because the log4j stuff is initialized before Spring. See here another discussion on a similar subject.

Community
  • 1
  • 1
Andrei Stefan
  • 51,654
  • 6
  • 98
  • 89