[hibernate-issues] [Hibernate-JIRA] Created: (HHH-6003) Envers fails when an entity has dynamic-component

Rajeev (JIRA) noreply at atlassian.com
Fri Mar 11 00:31:08 EST 2011


Envers fails when an entity has dynamic-component
-------------------------------------------------

                 Key: HHH-6003
                 URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-6003
             Project: Hibernate Core
          Issue Type: Bug
          Components: envers
    Affects Versions: 3.6.0
         Environment: Windows 7, java version "1.6.0_18" (32 bit), hibernate-core-3.6.0.Final, mysql-5.1.45-win32
            Reporter: Rajeev
         Attachments: myproject.tar

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

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://opensource.atlassian.com/projects/hibernate/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        


More information about the hibernate-issues mailing list