Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate Envers and "Javassist Enhancement failed" Exception

We are using Hibernate Envers and have the following situation:

A class BusinessObjectType and a class Identity with a reference to BusinessObjectType:

@Entity
@Table( name = "ID_IDENTITY" )
@Audited
public class Identity {

    @ManyToOne
    @JoinColumn( name = "BO_TYPE_ID" )
    @IndexColumn( name = "INDEX_BO_BO_TYPE" )
    private BusinessObjectType businessObjectType;

    […]

}

We then query for all the version of Identity with:

AuditQuery auditQuery = auditReader.createQuery().forRevisionsOfEntity(
    Identity.class,
    false,
    true );
auditQuery.add( AuditEntity.id().eq( dbid ) );

@SuppressWarnings( "unchecked" )
List< Object[]> history = (List< Object[]>) auditQuery.getResultList();

If the stored identity does not have a BusinessObjectType (i.e., businessObjectType is and was null) everything works like a charm.

If the identity had a businessObjectType != null we get a "Javassist Enhancement failed" Exception:

Javassist Enhancement failed: ch.ethz.id.wai.baseclasses.BusinessObjectType

The error seems to be related to Envers trying to instantiate a BusinessObjectType but I don't really see what the problem could be (Hibernate has no problems with both objects if we don't use an AuditQuery).

The cause of the exception is

java.lang.InstantiationException: ch.ethz.id.wai.baseclasses.BusinessObjectType_$$_javassist_49

with no stack trace.

Any hint on what the problem could be?

like image 435
Matteo Avatar asked Sep 01 '11 16:09

Matteo


2 Answers

This happens inside the following class JavassistLazyInitializer A Javassist-based lazy initializer proxy.

Without having a look at full source it is difficult to comment but you can try following options.

  • Turn off Lazy loading for @ManyToOne relationship [This is a design decision so watch out if it doesn't fit in overall solution]
  • Provide a default public constructor for your entity which is causing problem[This is easier]
  • turn off reflection optimisation if not really required by setting up hibernate.bytecode.use_reflection_optimizer property to false

Let us know if this helps

like image 198
Manish Singh Avatar answered Oct 19 '22 16:10

Manish Singh


To get a more information about the exception, use the debugging facilities of your IDE to set an exception breakpoint for java.lang.InstantiationException to halt execution when the underlying exception occurs. This should show you the full stack trace, and allow you to inspect all variables on the stack.

If I had to guess, my first suspicion would be that since the association to BusinessObjectType is not mapped lazy, plain hibernate doesn't ever try to create a proxy for the class. Envers in contrast appears to do. A proxy is a subclass generated at runtime overriding all public methods. Therefore, neither the class nor any public methods (beside those inherited from Object) may be declared final, and a default constructor must be accessible to the subclass.

like image 33
meriton Avatar answered Oct 19 '22 17:10

meriton