Hi all,
I've struggled for a couple of hours to get an EntityListener to work with hibernate 4.3.7. The listener is configured in orm.xml instead of using annotations.
The background is that our application is divided in different maven modules and the imortant ones here are:
persistence (the persistence archive containing only the entities)
ejb (containing all ejbs, etc.)
Now I could easily put the listener into the persistence package and use annotations to register it on the entity. However in this case the listener needs access to some business logic residing in some ejbs. So the listener needs to be in the ejb module. We also have our persistence.xml inside the ejb module. That way I thought I could simply register the listener using xml instead of annotations.
The important parts from my persistence.xml:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"
xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=" http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="logiq-pu" transaction-type="JTA">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<!-- <provider>org.hibernate.ejb.HibernatePersistence</provider> -->
<jta-data-source>java:jboss/datasources/logiq</jta-data-source>
<!-- <non-jta-data-source>java:jboss/datasources/logiqUnmanaged</non-jta-data-source> -->
<mapping-file>META-INF/mapping.xml</mapping-file>
<class>...</class>
... more class definitions ...
<!-- Validation modes: AUTO, CALLBACK, NONE -->
<validation-mode>CALLBACK</validation-mode>
<properties>
<property name="javax.persistence.sharedCache.mode" value="DISABLE_SELECTIVE"/>
<!-- Hibernate -->
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.use_sql_comments" value="true"/>
<!--<property name="hibernate.enable_lazy_load_no_trans" value="true"/>-->
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect"/>
<!-- EHcache config -->
<property name="hibernate.cache.region.factory_class"
value="org.hibernate.cache.ehcache.EhCacheRegionFactory"/>
<property name="hibernate.cache.use_second_level_cache" value="true"/>
<property name="hibernate.cache.use_query_cache" value="true"/>
<property name="hibernate.default_batch_fetch_size" value="10"/>
<property name="hibernate.jdbc.batch_size" value="50"/>
<property name="hibernate.generate_statistics" value="false"/>
<property name="hibernate.event.merge.entity_copy_observer" value="log"/>
<!-- openJPA -->
<!-- <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/> -->
<!--<property name="javax.persistence.validation.group.pre-persist" value="javax.validation.groups.Default"/>-->
<!--<property name="javax.persistence.validation.group.pre-update" value="javax.validation.groups.Default"/>-->
<!--<property name="javax.persistence.validation.group.pre-remove" value=""/>-->
<!--<property name="hibernate.ejb.event.pre-insert"-->
<!--value="somepackage.db.generator.GenerateSequenceEventListener"/>-->
<!--<property name="hibernate.ejb.event.pre-collection-update"-->
<!--value="somepackage.ejb.validation.BeanValidationCollectionEventListener"/>-->
<!--<property name="hibernate.ejb.event.pre-collection-remove"-->
<!--value="somepackage.ejb.validation.BeanValidationCollectionEventListener"/>-->
<!-- HIBERNATE SEARCH -->
<property name="hibernate.search.default.directory_provider" value="filesystem"/>
<property name="hibernate.search.default.indexBase" value="${search.index.dir}"/>
</properties>
</persistence-unit>
</persistence>
And the mapping.xml as defined in persistence.xml:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence/orm http://xmlns.jcp.org/xml/ns/persistence/orm_2_1.xsd"
version="2.1">
<entity class="somepackage.db.entities.OrderItemService">
<entity-listeners>
<entity-listener class="somepackage.ejb.jpa.OrderItemServiceEntityListener">
<pre-persist method-name="onPrePersist"/>
</entity-listener>
</entity-listeners>
</entity>
</entity-mappings>
mapping.xml definetly gets parsed. So if the xml is invalid or I put a typo in the classname I'm getting errors. But the listener is never called.
After a couple of hours and some torn out hair, I started to dig into the hibernate sources and found JpaIntegrator. line 143 and following register the callbacks by using LegacyCallbackProcessor.processCallbacksForEntity. However this method only uses reflection to detect the JPA annotations. I've to use xml to define my listeners.
Does hibernate support registering JPA EntityListeners via xml at all and am I just missing the code that handles this? Or is this not supported at all? And if it is supported, why does my setup never call the listener as defined?
Any help is appreciated.
Cheers,
Thomas