I have a Couchbase document for which I'd like to enable auditing:
@Document(expiry = 0, expiryUnit = TimeUnit.DAYS, touchOnRead = true)
public class Entity {
@Id
@GeneratedValue(strategy = GenerationStrategy.USE_ATTRIBUTES, delimiter = ":")
private String id;
@IdAttribute(order = 0)
private String type;
@IdAttribute(order = 1)
private String entityGuid;
@Version
private long version;
private String firstName;
private String lastName;
private LocalDate dateOfBirth;
@CreatedDate
private LocalDateTime createTimeStamp;
@LastModifiedDate
private LocalDateTime lastUpdateTimeStamp;
@CreatedBy
private String createdBy;
@LastModifiedBy
private String lastUpdatedBy;
...
My configuration:
@Data
@Configuration
@EnableCouchbaseAuditing
@EnableConfigurationProperties(CouchbaseProperties.class)
public class EntityCouchConfig extends AbstractCouchbaseConfiguration {
...
@Bean
public AuditorAware<String> couchAuditing() {
return () -> Optional.of("my-entity-service");
}
}
It was my expectation that when performing update operations through the Couchbase template like replaceById()
and upsertById()
, spring-data would preserve the document's @CreatedDate
and @CreatedBy
fields, only updating the @LastModifiedDate
and @LastModifiedBy
.
This, however, seems not to be the case. When I perform an update, the document's @Created
fields are updated as well. This seems counterintuitive, and would suggest that I first need to pull the document, transfer the @Created
fields, and then save that, explicitly making two calls.
I have read the spring-data-couchbase documentation on auditing but it's pretty sparse on the expected behavior here.
Is retrieving the document to capture the creation info and then updating the only way to do this, or am I implementing auditing wrong?
So my question was based on a flawed premise, because performing Couchbase template operations like upsert()
and replaceById()
will never perform any auditing logic.
To get auditing to work, it must be used in conjunction with a Couchbase Repository's save()
method.
The other important bit is that auditing won't do away with two calls to the database if your caller wants to update an entity and doesn't have the current version number and the current auditing data.
In order for spring-data auditing to work on an update operation, you must supply an entity with all audit fields (@CreatedDate/By, @LastModifiedDate/By) and the current version number. That means if your caller doesn't have this information, you must conduct a find call to retrieve it followed by a save once you have added that data to your entity. Only then will the auditing intelligently preserve the original @Createdxx
fields while updating the @Lastxx
fields.