In my previous article JPA Auditing: Persisting Audit Logs Automatically using EntityListeners, I have discussed how we can use Spring Data JPA automate Auditing and automatically create audit logs or history records and update CreatedBy, CreatedDate, LastModifiedBy, LastModifiedDate properties.

So in order to save history records for our File entity, we were trying to auto-wire EntityManager inside our FileEntityListener class and we have come to know that we can not do this.

We can not inject any Spring-managed bean in the EntityListener because EntityListeners are instantiated by JPA before Spring inject anything into it. EntityListeners are not managed Spring so Spring cannot inject any Spring-managed bean e.g. EntityManager in the EntityListeners.

And this case is not just with EntityListeners, you can not auto wire any Spring-managed bean into another class (i.e. utility classes) which is not managed by Spring.

Because it is a very common problem and can also arise with other classes so I tried to come out with a common solution which will not just solve this problem but will also help us getting Spring managed beans in other places.

AutoWiring-Spring-Beans-Into-Classes-Not-Managed-By-Spring-Like-JPA-Entity-Listeners

So I have created one utility class to fetch any bean according to our requirement.

@Service
public class BeanUtil implements ApplicationContextAware {

    private static ApplicationContext context;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        context = applicationContext;
    }

    public static <T> T getBean(Class<T> beanClass) {
        return context.getBean(beanClass);
    }

}

Now to get any a bean in class we will just need call the BeanUtil.getBean(YourClass.class) and pass the class type to it and we will get the bean.

For Example in our case, we were trying to get the EntityManager bean inside FileEntityListener, we can simply do it by writing BeanUtil.getBean(EntityManager.class).

public class FileEntityListener {

    private void perform(File target, Action action) {
        EntityManager entityManager = BeanUtil.getBean(EntityManager.class);
        entityManager.persist(new FileHistory(target, action));
    }

}

You can find complete code on this Github Repository and please feel free to provide your valuable feedback.
Next Post Newer Posts Previous Post Older Posts Home