title: Using Hibernate 4's Integrator pattern and Spring's dependency injection
body: <p>I'm used to using Spring to do my dependency injection like so:</p>
  
  <pre><code>&lt;context:component-scan base-package="org.emmerich.myapp" /&gt;
  </code></pre>
  
  <p>and then annotating my dependent classes with <code>Autowired</code> like so:</p>
  
  <pre><code>public class DependentClass {
  
      @Autowired
      private Dependency dependency;
  
  }
  </code></pre>
  
  <p>However, with the changes in Hibernate 4.0, we're now advised to use the new <code>Integrator</code> interface for service discovery. This includes adding event listeners for triggers such as <code>postUpdate</code>, <code>postDelete</code> etc.</p>
  
  <p>Unfortunately, this doesn't play nicely with dependency injection through annotated dependencies. I have the following setup:</p>
  
  <p>An integrator I have defined to add my listener to the <code>ServiceFactory</code>. This is referenced in the file <code>META-INF/services/org.hibernate.integrator.spi.Integrator</code>.</p>
  
  <pre><code>public class MyIntegrator implements Integrator {
  
      private MyListener listener;
  
      public MyIntegrator() {
          listener = new MyListener();
      }
  
      @Override
      public void integrate(Configuration configuration,
                            SessionFactoryImplementor sessionFactory,
                            SessionFactoryServiceRegistry serviceRegistry) {
      final EventListenerRegistry eventRegistry =
          serviceRegistry.getService(EventListenerRegistry.class);
  
      eventRegistry.prependListeners(EventType.POST_COMMIT_INSERT, listener);
  
  }
  </code></pre>
  
  <p>I also have defined the class <code>MyListener</code>, which looks like your typical event listener.</p>
  
  <pre><code>@Component
  public class MyListener implements PostInsertEventListener {
  
      @Autowired
      private Dependent dependent;
  
      public void onPostInsert(PostInsertEvent event) {
           // dependent == null
      }
  
  }
  </code></pre>
  
  <p>Unforunately, as shown by the comment, this doesn't work. I guess it's because I'm instantiating <code>MyListener</code> inside <code>MyIntegrator</code>, it doesn't pick up the component and doesn't autowire components. However, if I try this:</p>
  
  <pre><code>@Component
  public class MyIntegrator {
  
       @Autowired
       private MyListener listener;
  
       ...
  }
  </code></pre>
  
  <p>Then the listener isn't autowired.</p>
  
  <p>Firstly, it feels wrong whilst using Spring to have to do <code>new MyListener()</code>. I expect to be able to define that as an autowired dependency and have Spring create a singleton for me. My question is this:</p>
  
  <p>What's the best approach to using dependency injection with the new Integrator interface? The Integrators are used to build a SessionFactory, and so when they're asked to integrate themselves I guess there isn't an application context available. Because of that, any beans I require in the Integrator need to be created the "old fashioned" way and won't receive the autowiring on them.</p>
  
  <p>I'm quite new to the world of Spring, would you say this is something that I should expect to see? I understand that I'm in a different scope of the application when I'm in the SessionFactory, but is there a way to obtain a reference to the bean and enable autowire even though I'm creating it via <code>new</code>?</p>
  
  <p>The solution I came up with used <code>ApplicationContextAware</code>. It meant that <code>MyListener</code> received a reference to the <code>ApplicationContext</code> whenever the context was available, and I referenced the beans from the context on method calls, rather than on bean construction. Creating a bean with <code>new</code> doesn't limit this, so Spring still gives me the application context:</p>
  
  <pre><code>@Component
  public class MyListener implements PostInsertEventListener, ApplicationContextAware {
  
      private static ApplicationContext context;
  
      public void onPostInsert(PostInsertEvent event) {
           // getDependent() == correct!
      }
  
      public void setApplicationContext(ApplicationContext context) throws BeanException {
          this.context = context;
      }
  
      public Dependent getDependent() {
          return context.getBean(Dependent.class);
      }
  
  }
  </code></pre>
  
  <p>Is there a better way?</p>