Cannot invoke "org.hibernate.envers.internal.entities.EntityConfiguration.getRelationDescription(String)" because "entCfg" is null

137 views Asked by At

I'm migrating from Hibernate Envers 5.x to 6. In my project there are a few entities with many-to-many relationships, the junction tables are represented with entities, having a few additional fields. In these entities both sides of the relationship are @ManyToOne fields.

@Audited(withModifiedFlag = true)
@Entity
public class Document {

    @Id
    @GeneratedValue
    private Long id;

    @Lob
    private String title;

    @OneToMany(mappedBy = "document", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER)
    @OrderBy("position")
    private List<DocumentAuthorEmployee> authors;
...
@Audited(withModifiedFlag = true)
@Entity
public class DocumentAuthorEmployee {

    @Id
    @GeneratedValue
    private Long id;

    @ManyToOne
    @JoinColumn(name = "document_id")
    private Document document;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "employee_id")
    private Employee employee;

    private int position;

    private String note;
...
@Audited(withModifiedFlag = true)
@Entity
public class Employee {
    @Id
    @GeneratedValue
    private Long id;

    @Column(nullable = false, length = 1000)
    private String name;
...

I have a custom RevisionListener which checks for the last two revisions of the modified entity and creates a diff from it. In this listener the AuditReader#find method throws a NullPointerException:

java.lang.NullPointerException: Cannot invoke "org.hibernate.envers.internal.entities.EntityConfiguration.getRelationDescription(String)" because "entCfg" is null
    at org.hibernate.envers.internal.entities.EntitiesConfigurations.getRelationDescription(EntitiesConfigurations.java:101) ~[hibernate-envers-6.2.17.Final.jar:6.2.17.Final]
    at org.hibernate.envers.internal.entities.mapper.relation.ToOneIdMapper.isIgnoreNotFound(ToOneIdMapper.java:226) ~[hibernate-envers-6.2.17.Final.jar:6.2.17.Final]
    at org.hibernate.envers.internal.entities.mapper.relation.ToOneIdMapper.nullSafeMapToEntityFromMap(ToOneIdMapper.java:171) ~[hibernate-envers-6.2.17.Final.jar:6.2.17.Final]
    at org.hibernate.envers.internal.entities.mapper.relation.ToOneIdMapper.nullSafeMapToEntityFromMap(ToOneIdMapper.java:152) ~[hibernate-envers-6.2.17.Final.jar:6.2.17.Final]
    at org.hibernate.envers.internal.entities.mapper.relation.AbstractToOneMapper.mapToEntityFromMap(AbstractToOneMapper.java:57) ~[hibernate-envers-6.2.17.Final.jar:6.2.17.Final]
    at org.hibernate.envers.internal.entities.mapper.MultiPropertyMapper.mapToEntityFromMap(MultiPropertyMapper.java:201) ~[hibernate-envers-6.2.17.Final.jar:6.2.17.Final]
    at org.hibernate.envers.internal.entities.EntityInstantiator.createInstanceFromVersionsEntity(EntityInstantiator.java:90) ~[hibernate-envers-6.2.17.Final.jar:6.2.17.Final]
    at org.hibernate.envers.internal.entities.EntityInstantiator.addInstancesFromVersionsEntities(EntityInstantiator.java:153) ~[hibernate-envers-6.2.17.Final.jar:6.2.17.Final]
    at org.hibernate.envers.query.internal.impl.AbstractAuditQuery.applyProjections(AbstractAuditQuery.java:352) ~[hibernate-envers-6.2.17.Final.jar:6.2.17.Final]
    at org.hibernate.envers.query.internal.impl.EntitiesAtRevisionQuery.list(EntitiesAtRevisionQuery.java:139) ~[hibernate-envers-6.2.17.Final.jar:6.2.17.Final]
    at org.hibernate.envers.query.internal.impl.AbstractAuditQuery.getSingleResult(AbstractAuditQuery.java:119) ~[hibernate-envers-6.2.17.Final.jar:6.2.17.Final]
    at org.hibernate.envers.internal.reader.AuditReaderImpl.find(AuditReaderImpl.java:122) ~[hibernate-envers-6.2.17.Final.jar:6.2.17.Final]
    at org.hibernate.envers.internal.reader.AuditReaderImpl.find(AuditReaderImpl.java:95) ~[hibernate-envers-6.2.17.Final.jar:6.2.17.Final]
    at org.hibernate.envers.internal.reader.AuditReaderImpl.find(AuditReaderImpl.java:89) ~[hibernate-envers-6.2.17.Final.jar:6.2.17.Final]
    at com.github.csaadaam.envers.manytoone.npe.listener.RevisionListener.entityChanged(RevisionListener.java:20) ~[classes/:na]
    at org.hibernate.envers.internal.revisioninfo.DefaultRevisionInfoGenerator.entityChanged(DefaultRevisionInfoGenerator.java:98) ~[hibernate-envers-6.2.17.Final.jar:6.2.17.Final]
    at org.hibernate.envers.internal.synchronization.EntityChangeNotifier.entityChanged(EntityChangeNotifier.java:46) ~[hibernate-envers-6.2.17.Final.jar:6.2.17.Final]
    at org.hibernate.envers.internal.synchronization.AuditProcess.executeInSession(AuditProcess.java:126) ~[hibernate-envers-6.2.17.Final.jar:6.2.17.Final]
    at org.hibernate.envers.internal.synchronization.AuditProcess.doBeforeTransactionCompletion(AuditProcess.java:175) ~[hibernate-envers-6.2.17.Final.jar:6.2.17.Final]
    at org.hibernate.envers.internal.synchronization.AuditProcessManager$1.doBeforeTransactionCompletion(AuditProcessManager.java:47) ~[hibernate-envers-6.2.17.Final.jar:6.2.17.Final]
    at org.hibernate.engine.spi.ActionQueue$BeforeTransactionCompletionProcessQueue.beforeTransactionCompletion(ActionQueue.java:1012) ~[hibernate-core-6.2.17.Final.jar:6.2.17.Final]
    ... 42 common frames omitted

There is a change in the ToOneIdMapper class since hibernate 6.0 that might be causing the issue: https://github.com/hibernate/hibernate-orm/commit/b384b37f395f14f5e64c6b6d4d00e0868d62fe01#diff-3435a0e26ab386be275368ac69b447f002655fba8802e9d6d9397d5176b6af17L161

In 5.x there used to be a check for whether the referenced entity is audited, and since it is, it was skipped in 5.x: if ( !referencedEntity.isAudited())

Now it tries to get the referencingEntityName, but since the map contains no $type$, it is null and later in the EntitiesConfigurations#getRelationDescription it causes a NPE, because neither of the paths provide an EntityConfiguration here:

final EntityConfiguration entCfg;
if ( isVersioned( entityName ) ) {
    entCfg = get( entityName );
}
else {
    entCfg = getNotVersionEntityConfiguration( entityName );
}

So it throws a NPE here: https://github.com/hibernate/hibernate-orm/blob/6.2/hibernate-envers/src/main/java/org/hibernate/envers/internal/entities/EntitiesConfigurations.java#L101

I haven't found anything about it in the migration docs, am i missing something?

I've created a repo for showcasing my issue: https://github.com/csaadaam/envers-manytoone-npe

Any help would be greatly appreciated.

0

There are 0 answers