8

i have a simple question. Its possible to add dependency injection via @Ressource or @Autowired to the Hibernate Eventlistener?

I will show you my entitymanagerfactory configuration:

<bean id="entityManagerFactory" class="org.hibernate.ejb.EntityManagerFactoryImpl">
    <qualifier value="entityManagerFactory" />
    <constructor-arg>
        <bean
            class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
            <property name="persistenceUnitManager">
                <bean
                    class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManagerr">
                    <property name="defaultDataSource" ref="dataSource" />
                </bean>
            </property>
            <property name="dataSource" ref="dataSource" />
            <property name="persistenceUnitName" value="mis" />
            <property name="persistenceProviderClass" value="org.hibernate.ejb.HibernatePersistence" />
            <property name="jpaProperties" ref="jpa.properties" />
            <property name="jpaDialect" ref="jpaDialect" />
            <property name="jpaVendorAdapter">
                <bean
                    class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                    <property name="generateDdl" value="true" />
                    <property name="database">
                        <util:constant
                            static-field="org.springframework.orm.jpa.vendor.Database.POSTGRESQL" />
                    </property>
                    <property name="showSql" value="true" />
                </bean>
            </property>

        </bean>
    </constructor-arg>
</bean>

At the moment i register my listener via jpa.properties,

hibernate.ejb.event.load=com.example.hibernate.events.LoadEvent

but in this case i have no spring injection in my listener. I found a solution, but this use the sessionFactory and not the entitymanager oder can i modifiy the sessionfactory in my context? Hopefully someone have a nice idea or solutionhow to deal with this problematic!

Big thanks!

Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588
moohkooh
  • 917
  • 1
  • 10
  • 25

1 Answers1

16

If you used SessionFactory, this would be the configuration:

<bean id="mySessionFactory"
    class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <!-- Stripped other stuff -->
    <property name="eventListeners">
        <map>
            <entry key="pre-load">
                <bean class="com.mycompany.MyCustomHibernateEventListener1" />
            </entry>
            <entry key="pre-persist">
                <bean class="com.mycompany.MyCustomHibernateEventListener2" />
            </entry>
        </map>
    </property>
</bean>

But since you are using JPA, I'm afraid you need to use AOP as outlined in this thread

Or you can

  1. store the ApplicationContext in a ThreadLocal or a custom holder class and expose it through a static method
  2. have a base class for your listeners something like this:

Base class:

public abstract class ListenerBase{

    protected void wireMe(){
        ApplicationContext ctx = ContextHelper.getCurrentApplicationContext();
        ctx.getAutowireCapableBeanFactory().autowireBean(this);
    }

}

Now in your lifycycle methods call wireMe() first.


Update:

Here is a sample implementation of ContextHelper:

public final class ContextHelper implements ApplicationContextAware{

    private static final ContextHelper INSTANCE = new ContextHelper();
    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(final ApplicationContext applicationContext){
        this.applicationContext = applicationContext;
    }

    public static ApplicationContext getCurrentApplicationContext(){
        return INSTANCE.applicationContext;
    };

    public static ContextHelper getInstance(){
        return INSTANCE;
    }

    private ContextHelper(){
    }

}

Wire it in your Spring Bean configuration like this:

<bean class="com.mycompany.ContextHelper" factory-method="getInstance" />
Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588
  • Hi, thank you for your respone. Can you please tell me where i find the ContextHelper? Ich have one from Hibernate.search.util. and Hibernate.search.event and there have no methods "getCurrentApplicationContext()" – moohkooh Nov 11 '10 at 07:49
  • It's a class you need to create. I have now attached a sample version. – Sean Patrick Floyd Nov 11 '10 at 08:06
  • Big big thanks, it works. I cant tell you, how much you helped me!! Big big thanks!! – moohkooh Nov 11 '10 at 08:20
  • 1
    I just wanted to point out this excellent article: http://baard.rehn.no/node/51 Slightly different approach, same end result. I liked it because it kept the IOC container choice separate from the EntityListener. I used a single class that implemented InitializingBean and DependencyInjector. In theory I should be able to switch from Spring to some other container and the Persistence layer is unaware. I did declare the listener on my @Entity classes. I set the default listener through Spring applicationContext.xml - I don't want the classes to be aware that they're being listened to. – Doug Moscrop Jan 13 '11 at 20:13