Skip to content

Custom RevisionEntity class Metadata null #313

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
csh0034 opened this issue Sep 8, 2021 · 2 comments
Closed

Custom RevisionEntity class Metadata null #313

csh0034 opened this issue Sep 8, 2021 · 2 comments
Assignees
Labels
type: bug A general bug

Comments

@csh0034
Copy link

csh0034 commented Sep 8, 2021

I have a problem when using custom entities, in spring data envers 2.5.3

When Create a new DefaultRevisionMetadata or AnnotationRevisionMetadata, metadata is HibernateProxy

EnversRevisionRepositoryImpl

RevisionMetadata<?> createRevisionMetadata() {
  return metadata instanceof DefaultRevisionEntity //
    ? new DefaultRevisionMetadata((DefaultRevisionEntity) metadata, revisionType) //
    : new AnnotationRevisionMetadata<>(metadata, RevisionNumber.class, RevisionTimestamp.class, revisionType);
}

DefaultRevisionMetadata

public final class DefaultRevisionMetadata implements RevisionMetadata<Integer> {
  public Optional<Integer> getRevisionNumber() {
    return Optional.of(entity.getId());
  }
}

AnnotationRevisionMetadata

public class AnnotationRevisionMetadata<N extends Number & Comparable<N>> implements RevisionMetadata<N> {
  private final Lazy<Optional<N>> revisionNumber;

  public AnnotationRevisionMetadata(Object entity, Class<? extends Annotation> revisionNumberAnnotation,
      Class<? extends Annotation> revisionTimeStampAnnotation, RevisionType revisionType) {

    Assert.notNull(entity, "Entity must not be null!");
    Assert.notNull(revisionNumberAnnotation, "Revision number annotation must not be null!");
    Assert.notNull(revisionTimeStampAnnotation, "Revision time stamp annotation must not be null!");
    Assert.notNull(revisionType, "Revision Type must not be null!");

    this.entity = entity;
    this.revisionNumber = detectAnnotation(entity, revisionNumberAnnotation);
    this.revisionDate = detectAnnotation(entity, revisionTimeStampAnnotation);
    this.revisionType = revisionType;
  }
  
  public Optional<N> getRevisionNumber() {
    return revisionNumber.get();
  }

  private static <T> Lazy<Optional<T>> detectAnnotation(Object entity, Class<? extends Annotation> annotationType) {
    
    return Lazy.of(() -> {
      AnnotationDetectionFieldCallback callback = new AnnotationDetectionFieldCallback(annotationType);
      ReflectionUtils.doWithFields(entity.getClass(), callback);
      return Optional.ofNullable(callback.getValue(entity));
    });
  }
}

AnnotationDetectionFieldCallback

public class AnnotationDetectionFieldCallback implements FieldCallback {

  public <T> T getValue(Object source) {

    Assert.notNull(source, "Source object must not be null!");

    Field field = this.field;

    if (field == null) {
      return null;
    }

    return (T) ReflectionUtils.getField(field, source);
  }
}

DefaultRevisionMetadata calls Optional.of(entity.getId());
-> entity is HibernateProxy
-> HibernateProxy.getId();

AnnotationRevisionMetadata calls revisionNumber.get();
-> Optional.ofNullable(callback.getValue(entity))
-> ReflectionUtils.getField(field, source), @RevisionNumber annotated field value

Therefore, when using Custom RevisionEntity, the field value of the HibernateProxy
in org.springframework.data.history.Revision is null. Information about metadata is output only as null or Optional.empty.

if in custom RevisionEntity Adding @Proxy(lazy = false) causes n+1 issues similar issue

any way to solve this problem?

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Sep 8, 2021
@schauder
Copy link
Contributor

schauder commented Nov 3, 2021

The problematic code is in commons. We'd need either a way to configure the ways these values get accessed or switch to field access. But since the code is in commons we need to evaluate how that might affect other modules.

@schauder
Copy link
Contributor

schauder commented Mar 3, 2022

The plan is to check for Hibernate Proxies and handle them explicitly.

@schauder schauder added type: bug A general bug and removed status: waiting-for-triage An issue we've not yet triaged labels Mar 10, 2022
schauder added a commit to spring-projects/spring-data-jpa that referenced this issue Mar 11, 2022
We now unproxy the revision data before trying to access its data.

Closes spring-projects/spring-data-envers/issues/313
trayanus1026 pushed a commit to trayanus1026/spring-data-jpa-java that referenced this issue Aug 5, 2023
We now unproxy the revision data before trying to access its data.

Closes spring-projects/spring-data-envers/issues/313
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug A general bug
Projects
None yet
Development

No branches or pull requests

3 participants