views:

273

answers:

1

I'm using Envers to audit different fields of my entities. The framework works in general but it seems to have problems with some kinds of entity mapping. All former problems I could solve myself... but this time I'm stuck.

When inserting some entity into the database I get the following exception:

Caused by: java.lang.NullPointerException
    at org.hibernate.envers.event.AuditEventListener.generateBidirectionalCollectionChangeWorkUnits(AuditEventListener.java:108)

I'm not completly sure which entity causes this because it is fired during flush() and the complex application inserts many different entities within one larger transaction.

We are using some HibernateEventListener that fires right before that exception... so I suppose that entity is the cause. The persistence.xml is configured this way:

  <property name="hibernate.ejb.event.post-insert" value="com.xyz.hibernate.events.listeners.MyListener,org.hibernate.envers.event.AuditEventListener" />

If this is true than the entity is the following (excerpt):

@Entity
@Table(name = Property.TABLE_NAME, uniqueConstraints = @UniqueConstraint(columnNames = { "ENTITY_ID", "DESCRIPTOR_ID", "PROMOLEVEL_ID" }))
public class Property extends AbstractEntity {
private static final long serialVersionUID = 1L;

public static final String TABLE_NAME = "E_BUSINESS_PROPERTIES";
public static final String PROPERTY_ENTITY = "entity";
public static final String PROPERTY_DESCRIPTOR = "descriptor";
public static final String PROPERTY_PROMOLEVEL = "promolevel";

@Audited
@ManyToOne(optional = false)
private ProjectPropertyDescriptor descriptor;

@Audited
@ManyToOne
private ExtendedEntity entity;

@Audited
@ManyToOne
private AbstractPromotionLevel promolevel;

@Audited
@OneToMany(cascade = { CascadeType.ALL }, mappedBy = PropertyValue.PROPERTY_PROPERTY)
private List<PropertyValue> propertyValues = new ArrayList<PropertyValue>();

// some accessors stripped!

}

Does anyone have an idea where to look for? As soon as we disable Envers everything works fine. But we need envers to generate a history of changes.

+2  A: 

I found the solution of my problem. So I'll share it for others.

The reference to the ExtendedEntity caused the problem. ExtendedEntity is an audited class with different subclasses. But Envers does not automatically mark the subclass as audited. The subclass must use the @Audited annotation for the class or any own fields to be audited by Envers.

So a reference to any sublass of ExtendedEntity, that was audited, worked. In my case I've referenced another subclass that was not audited by Envers - and so the NullPointerException was thrown. By simply adding the @Audited annotation to that empty extension of the ExtendedEntity class (no own properties... just a subclass to distinguish another type of entity) and creation of the related versioning table in the database I could close that gap and solve my problem.

Remember to mark subclasses with @Audited at any own field or the class itself - otherwise they aren't audited and you might come across the exact same problem.

Daniel Bleisteiner
thanks, this is exactly what i was looking for.
Anthony Bishopric