3

Am trying to make a JPA Entity Listener aware of the spring context by marking it as @Configurable. But the injected spring beans are null. Am able to make JPA entities aware of the Spring context using the same technique. Am using Spring(core and data-jpa) as infrastructure. Any ideas on how to acheive this using JPA Entity Listeners or spring data-jpa?

@Configurable
@Scope("singleton")
public class AggregateRootListener {
    private static Logger log = LoggerFactory.getLogger(AggregateRootListener.class);

    @Autowired
    private EventHandlerHelper eventHandlerHelper;

    @PostPersist
    @PostUpdate
    public void publishEvents(BaseAggregateRoot aggregateRoot){
        log.info(aggregateRoot.getEvents().toString());
        aggregateRoot.getEvents().stream()
            .forEach(event -> {
                eventHandlerHelper.notify(event, aggregateRoot);
                log.info("Publishing " + event + " " + aggregateRoot.toString());
            });
    }
}

and the BaseAggregateRoot code

@Configurable
@Scope("prototype")
@MappedSuperclass
@EntityListeners(AggregateRootListener.class)
public abstract class  BaseAggregateRoot extends BaseDomain{
    public static enum AggregateStatus {
        ACTIVE, ARCHIVE
    }

    @EmbeddedId
    @AttributeOverrides({
          @AttributeOverride(name = "aggregateId", column = @Column(name = "ID", nullable = false))})
    protected AggregateId aggregateId;



    @Version
    private Long version;
}
FFL
  • 669
  • 7
  • 22
  • 1
    There is an other dublicate: http://stackoverflow.com/questions/12155632/injecting-a-spring-dependency-into-a-jpa-entitylistener -- but I think http://stackoverflow.com/questions/8616146/eventlisteners-using-hibernate-4-0-with-spring-3-1-0-release has the better answer – Ralph Jan 29 '15 at 13:27
  • The solution in both the questions use Hibernate or Eclipse Link. I want to find out if there is a JPA implementation agnostic solution. The solution should not be specific for a framework and should be based on JPA Entity Listener. – FFL Jan 30 '15 at 07:57
  • https://deepintojee.wordpress.com/2012/02/05/spring-managed-event-listeners-with-jpa/ -- the other way would use `@Configurable` and AspectJ, then you could `@Autowire` in Instances that are created by `new` – Ralph Jan 30 '15 at 10:19

1 Answers1

11

Event Listener mechanism is a JPA concept and is implemented by the JPA provider. I don't think Spring creates event listener class instances - they are rather created by the JPA provider (Hibernate, EclipseLink, etc.). Therefore, the regular Spring injection would not work with event listener class instances. The author of this post seems to have come to the same conclusion.


That said, I do use Spring managed beans in JPA event listeners. The solution I use was developed to get hold of Spring bean instances in all classes that are not managed by Spring. It involves creating the following class:

@Component
public class SpringApplicationContext implements ApplicationContextAware {
  private static ApplicationContext CONTEXT;

  public void setApplicationContext(final ApplicationContext context)
              throws BeansException {
    CONTEXT = context;
  }

  public static <T> T getBean(Class<T> clazz) { return CONTEXT.getBean(clazz); }
}

This class caches the Spring application context at initial load. The context is then used to look up Spring managed beans.

Using the class is then as simple as SpringApplicationContext.getBean(FooService.class).

All the usual Spring semantics, such as, bean lifecycle, bean scope and transitive dependencies are taken care of.

manish
  • 19,695
  • 5
  • 67
  • 91
  • What is the benefit of this abstraction over simply injecting `ApplicationContext` into the desired location? – Will Faithfull Feb 28 '17 at 10:23
  • @WillFaithfull, this is for cases where a class that is not a Spring-managed bean requires a Spring-managed bean instance. Autowiring will not work in such cases because the consumer class is not managed by Spring. – manish Feb 28 '17 at 11:35
  • Oh, now I see - I didn't notice the `static` modifier. It makes sense now. – Will Faithfull Feb 28 '17 at 12:31