Injecting dependencies into a JPA EntityListener

Posted on 18 Apr 2012

It is not possible to inject spring managed beans into a JPA EntityListener class. This is because the JPA listener mechanism should be based on a stateless class, so the methods are effectively static, and non-context aware.

In Hibernate at least this is not strictly true, since if you were (and you shouldn't) to record an entity in a field of this in a method, it's sat there next time the method comes along.

public class EntityListener {
    private Entity entity;

    @PostUpdate
    public void doStuff(Entity entity) {
        // don't try this at home, it is a BAD THING
        this.entity = entity;
        ...
    }
}

This is more than a little daft, what with the lingering reference, and the concurrency nightmare that would no doubt ensue.

No amount of AOP will save you, nothing gets injected to the 'object' representing the listener, because the implementations don't actually create instances, but uses the class method. This is a perfectly reasonable approach based on the JPA spec, so is not really a bug, but does mean that there is no bean to inject dependencies to. If you were crazy, you could pointcut each method of your listener, but by that point, you've probably lost the plot you were pursuing in the first place, and you might as well just do the whole thing with a pointcut on your target entity (this is debatable, but I will not debate it just yet).

This is certainly the case for Hibernate, and appears to be for at least two of the other major providers (Open JPA, eclipse - ok, so I tested the effect, but didn't read all the source code for those, because life is too short, and I'd already spent too long reading most of Hibernate).

Of course you could provide access to services through static methods, or a singleton of some sort, but we're all convinced that's an anti-pattern, right?

StackOverflow Flair

profile for Simon Elliston Ball at Stack Overflow, Q&A for professional and enthusiast programmers