Envers fails when an entity has dynamic-component

Description

hi,

Am working with hibernate version 3.6.0.Final. Envers fails during initialization when an entity has dynamic-component.

Hibernate.cfg.xml -
<hibernate-configuration>
<session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost/company?createDatabaseIfNotExist=true&amp;useUnicode=true&amp;characterEncoding=utf-8</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>

<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">1</property>
<property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>

<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
<!-- Drop and re-create the database schema on startup -->
<property name="hbm2ddl.auto">create</property>

</session-factory>
</hibernate-configuration>

There is only 1 entity in this test case -
Employee.java:

import ...
@Audited
public class Employee implements java.io.Serializable {

private Long id;
private String name ;
@NotAudited
private Map customProperties = new HashMap(); // maps to dynamic-component
.. getter/setter ...

Hibernate mapping (using xml as dynamic-component is not available as annotation)
<hibernate-mapping default-access="property">

<class name="com.company.domain.Employee" table="EMPLOYEE">

<id name="id" column="id">
<generator class="native"/>
</id>

<property name="name" type="string" column="name" length="255" not-null="false"/>

<dynamic-component insert="true" name="customProperties" optimistic-lock="true" unique="false" update="true" >
</dynamic-component>

</class>

</hibernate-mapping>

HibernateUtil -
private static SessionFactory buildSessionFactory() {
try {
// Create the SessionFactory from hibernate.cfg.xml
AuditEventListener auditEventListener = new AuditEventListener();
Configuration configuration = new Configuration();
configuration.getEventListeners().setPostInsertEventListeners(new PostInsertEventListener[]{auditEventListener});
configuration.getEventListeners().setPostUpdateEventListeners(new PostUpdateEventListener[]{auditEventListener});
configuration.getEventListeners().setPostDeleteEventListeners(new PostDeleteEventListener[]{auditEventListener});
return configuration.configure().buildSessionFactory();
}
catch (Throwable ex) {
// Make sure you log the exception, as it might be swallowed
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}

Main class -
public class App
{
public static void main( String[] args )
{
System.out.println( "Hello World!" );

App app = new App();
app.createAndStore();
app.createAndStoreVersion();
HibernateUtil.getSessionFactory().close();
}

private void createAndStore() {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();

Employee emp = new Employee();
emp.setName("name");
session.save(emp);
session.getTransaction().commit();
}

private void createAndStoreVersion() {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();

Employee emp = (Employee) session.get(Employee.class, 1L);
emp.setName("updated name");
session.save(emp);
session.getTransaction().commit();
}

}

Initialization fails, log is:
Caused by: java.lang.NullPointerException
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:247)
at org.hibernate.annotations.common.util.ReflectHelper.classForName(ReflectHelper.java:143)
at org.hibernate.annotations.common.reflection.java.JavaReflectionManager.classForName(JavaReflectionManager.java:117)
at org.hibernate.envers.configuration.metadata.reader.AuditedPropertiesReader$ComponentPropertiesSource.<init>(AuditedPropertiesReader.java:269)
at org.hibernate.envers.configuration.metadata.reader.AuditedPropertiesReader$ComponentPropertiesSource.<init>(AuditedPropertiesReader.java:263)
at org.hibernate.envers.configuration.metadata.reader.AuditedPropertiesReader.addFromProperties(AuditedPropertiesReader.java:105)
at org.hibernate.envers.configuration.metadata.reader.AuditedPropertiesReader.addPropertiesFromClass(AuditedPropertiesReader.java:89)
at org.hibernate.envers.configuration.metadata.reader.AuditedPropertiesReader.read(AuditedPropertiesReader.java:67)
at org.hibernate.envers.configuration.metadata.reader.AnnotationsMetadataReader.getAuditData(AnnotationsMetadataReader.java:114)
at org.hibernate.envers.configuration.EntitiesConfigurator.configure(EntitiesConfigurator.java:80)
at org.hibernate.envers.configuration.AuditConfiguration.<init>(AuditConfiguration.java:97)
at org.hibernate.envers.configuration.AuditConfiguration.getFor(AuditConfiguration.java:129)
at org.hibernate.envers.event.AuditEventListener.initialize(AuditEventListener.java:335)
at org.hibernate.event.EventListeners$1.processListener(EventListeners.java:198)
at org.hibernate.event.EventListeners.processListeners(EventListeners.java:181)
at org.hibernate.event.EventListeners.initializeListeners(EventListeners.java:194)
... 6 more

After some debugging I found that a dynamic-component doesn't have class attribute (it is always java.util.HashMap), envers tries to look it up and fails.

Secondly, I coudln't figure out how to attach envers listeners via hibernate.cfg.xml, so used run time configuration.
All the three approaches failed -
1. <property name="hibernate.ejb.event.post-insert">org.hibernate.ejb.event.EJB3PostInsertEventListener,org.hibernate.envers.event.AuditEventListener</property>
2. <listener class="org.hibernate.envers.event.AuditEventListener" type="post-insert"/> (DTD validation fails)
3. <event type="post-insert">
<listener class="org.hibernate.envers.event.AuditEventListener"/>
</event> (DTD validation fails).

Also tracked in forum - https://forum.hibernate.org/viewtopic.php?f=1&t=1009975

Junit to reproduce this scenario is attached. Execute App.java, you'll need mysql.

regards,
Rajeev

Attachments

1

Activity

Brett MeyerMarch 7, 2014 at 5:30 PM

Bulk closing rejected tickets in "resolved" state.

AdamASeptember 24, 2013 at 8:30 AM

Convered by

Former userAugust 16, 2011 at 2:58 AM

Adam, please assign as appropriate.
Thanks,
Gail

RajeevMay 5, 2011 at 8:22 AM

Abdurrahman Nasr, didn't find any workaround. So am not using envers.

Abdurrahman NasrMay 4, 2011 at 6:05 PM

isn't there any work around for this bug. 2 months passed and this issue is still opened

Out of Date

Details

Assignee

Reporter

Components

Affects versions

Priority

Created March 11, 2011 at 7:30 AM
Updated March 7, 2014 at 5:30 PM
Resolved September 24, 2013 at 8:30 AM