grueny
grueny

Reputation: 91

How to disable AuditEntityListener (Spring Data) temporary?

We use Spring Data with die AuditEntityListener to update the change-user and the changedate. But for our migration (Spring Batch) of old data we need to set the create-user and the change-user manualy, but we cannot disable the functionality of the AuditEntityListener. We also use envers in some entities, so I can't implement the AuditEntityListener by myself.

Do I have to copy my entity-classes?

Upvotes: 2

Views: 780

Answers (1)

tiempo
tiempo

Reputation: 140

I have exactly the same problem, and this is how I ended up resolving it. I am using Spring Boot 3.2

  1. Declare a custom audit entity listener
public class CustomAuditEntityListener extends AuditingEntityListener {

    public CustomAuditEntityListener(ObjectFactory<AuditingHandler> auditingHandler) {
        super.setAuditingHandler(auditingHandler);
    }

    @PrePersist
    public void customPrePersist(Object target) {
        try {
            Field uuidField = target.getClass().getSuperclass().getDeclaredField("createdAt");
            uuidField.setAccessible(true);
            Object uuidValue = uuidField.get(target);
            if (uuidValue == null)
                super.touchForCreate(target);
            uuidField.setAccessible(false);
        } catch (NoSuchFieldException | IllegalAccessException ignored) { }
    }

    @PreUpdate
    public void customPreUpdate(Object target) {
        try {
            Field uuidField = target.getClass().getSuperclass().getDeclaredField("updatedAt");
            uuidField.setAccessible(true);
            Object uuidValue = uuidField.get(target);
            if (uuidValue == null)
                super.touchForUpdate(target);
            uuidField.setAccessible(false);
        } catch (NoSuchFieldException | IllegalAccessException ignored) { }
    }

    private Class<?> getClass(Object target) {
        return ProxyUtils.getUserClass(target);
    }
}
  1. Apply the listener to the entity used for auditing
@MappedSuperclass
@EntityListeners(CustomAuditEntityListener.class)
@JsonIgnoreProperties(
        value = {"createdAt", "updatedAt"},
        allowGetters = true
)
@Setter
public abstract class DateAudit implements Serializable {

  @CreatedDate
  @Column(updatable = false)
  @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "UTC")
  private Instant createdAt;

  @LastModifiedDate
  @Column
  @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "UTC")
  private Instant updatedAt;

  public Instant getCreatedAt() {
    if(this.createdAt != null)
      return LocalDateTime.ofInstant(this.createdAt, ZoneOffset.UTC).toInstant(ZoneOffset.UTC);

    return null;
  }

  public Instant getUpdatedAt() {
    if(this.updatedAt != null)
      return LocalDateTime.ofInstant(this.updatedAt, ZoneOffset.UTC).toInstant(ZoneOffset.UTC);

    return null;
  }
}

The above entity is used like so:

public class EntityIWantToHaveAudit extends DateAudit {

// properties
}

With the above configuration, when I migrate old data that already have a createdAt and an updatedAt they are not overwritten. For new entities the auditing works as expected.

Upvotes: 1

Related Questions