]
Gail Badner reassigned HHH-6003:
--------------------------------
Assignee: Adam Warski (was: Gail Badner)
Adam, please assign as appropriate.
Thanks,
Gail
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
Assignee: Adam Warski
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&useUnicode=true&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.
For more information on JIRA, see: