1

I have the following class (which is a JPA entity listener):

@Service
public class AuditLogListener {

    @Autowired
    IDomainObjectDAO domainObjectDAO;

    @PostLoad
    public void saveOldData(DomainObject obj) {
        domainObjectDAO.findAll();
        System.out.println("after Load");
    }

    @PreUpdate
    public void logChanges(DomainObject obj) {

    }

}

The filed domainObjectDAO is recognized by Spring and according to the log, is auto wired.

excerpt from the log:

[http-8080-1] DEBUG org.springframework.beans.factory.annotation.InjectionMetadata - Found injected element on class [com.legolas.entityListeners.AuditLogListener]: AutowiredFieldElement for com.legolas.dao.interfaces.IDomainObjectDAO com.legolas.entityListeners.AuditLogListener.domainObjectDAO
[http-8080-1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Eagerly caching bean 'auditLogListener' to allow for resolving potential circular references
[http-8080-1] DEBUG org.springframework.beans.factory.annotation.InjectionMetadata - Processing injected method of bean 'auditLogListener': AutowiredFieldElement for com.legolas.dao.interfaces.IDomainObjectDAO com.legolas.entityListeners.AuditLogListener.domainObjectDAO
[http-8080-1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'domainObjectDAO'
[http-8080-1] DEBUG org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor - Autowiring by type from bean name 'auditLogListener' to bean named 'domainObjectDAO'

But when checking the field in debug mode i see that the fields is null and an exception is thrown when calling the findAll() method.

Why is the filed null and is there a way to solve this?

Thank you.

Noam Nevo
  • 3,021
  • 10
  • 35
  • 49
  • see also http://stackoverflow.com/questions/4143881/spring-entitymanagerfactory-hibernate-listeners-injection – Bozho Nov 14 '10 at 19:03

1 Answers1

5

JPA listeners are instantiated by JPA provider rather than by Spring, therefore that their dependencies are not injected by Spring. That is, now you have two instances of your class - one used by JPA (without injected dependencies) and another one instantiated by Spring (you see it in the log).

So, you need to inject dependencies into an object that is not managed by Spring. You have two options:

  • Use @Configurable

  • Use some kind of static or thread-bound state to obtain a reference to ApplicationContext from your listener. For example, in a typical Spring web application you can obtain it as follows:

    RequestContextUtils.getWebApplicationContext(
        (SerlvetRequest) RequestContextHolder.currentRequestAttributes()
            .resolveReference(RequestAttributes.REFERENCE_REQUEST))
    
axtavt
  • 239,438
  • 41
  • 511
  • 482
  • I used the @Configurable Annotation and in the log i see now in the log that the bean is injected into the JPA entity manager, meaning the Bean instantiated by the JPA provider recognizes the field (an I right?), but still the field is null. – Noam Nevo Nov 14 '10 at 17:35
  • @Noam: Have you configured load time weaving, as required for `@Configurable`? – axtavt Nov 14 '10 at 18:41
  • No idea what that is, i'll check it and get back to you. – Noam Nevo Nov 15 '10 at 10:00
  • Load time weaving did not suit my needs, i went with the second option and it works fine. Thank you – Noam Nevo Nov 16 '10 at 12:53