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).
Any pointers on how to make envers work with dynamic-component ? Let me know if I should file JIRA for this.
regards, Rajeev
|