2

I've dynamoDB database, in which I've a table named user. I want to log auditing (CreatedBy, LastModifiedBy, CreatedDate, LastModifiedDate)in this table.

I've found JPA auditing (from here) and MongoDB auditing with annotations @EnableJpaAuditing and @EnableMongoAuditing respectively. But obviously they are not working with dynamoDB.

Here is my abstract class for auditing:

    @DynamoDBDocument
public abstract class PQSSAbstractAuditingEntity implements Serializable{
    @CreatedBy
    @JsonIgnore
    @DynamoDBAttribute
    private String createdBy;

    @LastModifiedBy
    @JsonIgnore
    @DynamoDBAttribute
    private String lastModifiedBy;

    @CreatedDate
    @JsonIgnore
    @DynamoDBAttribute
    private Date createdDate;

    @LastModifiedDate
    @JsonIgnore
    @DynamoDBAttribute
    private Date lastModifiedDate = new Date();

    public String getCreatedBy() {
        return createdBy;
    }

    public void setCreatedBy(String createdBy) {
        this.createdBy = createdBy;
    }

    public String getLastModifiedBy() {
        return lastModifiedBy;
    }

    public void setLastModifiedBy(String lastModifiedBy) {
        this.lastModifiedBy = lastModifiedBy;
    }

    public Date getCreatedDate() {
        return createdDate;
    }

    public void setCreatedDate(Date createdDate) {
        this.createdDate = createdDate;
    }

    public Date getLastModifiedDate() {
        return lastModifiedDate;
    }

    public void setLastModifiedDate(Date lastModifiedDate) {
        this.lastModifiedDate = lastModifiedDate;
    }
}

I've assigned dates to respective fields but I've to set createdBy and lastModifiedBy depending on the logged in user. So I've to fetch the dynamically at runtime, when ever new entry is added into the database. I know how to set these fields statically but the problem is how to make annotations aware of these changes at run time.

As I mentioned, I've found AuditAware for JPA and mongo. I need the same for dynamoDB.

Any help will be appreciated. As I'm new to Spring boot.

Kaushal28
  • 5,377
  • 5
  • 41
  • 72
  • I would suggest you get that meta information from the Utils class. Apart from this, it's always good to have version field @DynamoDBVersionAttribute for optimistic locking, especially while auditing. Use Spring data repo for dynamoDb to perform the crud operations – Yati Sawhney Feb 16 '18 at 12:15
  • Sorry, but this is so high level explanation. can you please give an example? – Kaushal28 Feb 16 '18 at 13:13
  • I am also confused how it can be implemented. @YatiSawhney please provide an example for how it can be implemented. I am using dynamodb and extends repositories with crudrepository. – ADARSH K Feb 12 '20 at 06:37

2 Answers2

4

The question is already some years old but if somebody has also that problem, following solution works..

The problem is, that @EnableDynamoDBAuditing and @EnableDynamoDBRepositories don't work properly together. To solve this problem you have to add both annotations to you configuration class, create AuditorAware and DateTimeProvider beans and add all your entities/documents to your DynamoDBMappingContext manually.

PersistenceConfiguration.java

@Configuration
@EnableDynamoDBAuditing(auditorAwareRef = "userAuditing", dateTimeProviderRef = "dateAuditing")
@EnableDynamoDBRepositories(basePackages = "your.repository.package.name")
public class PersistenceConfiguration {

    @Bean
    public AuditorAware<String> userAuditing() {
        return () -> Optional.of("TestUser"); //get username from SecurityContext
    }

    @Bean
    public DateTimeProvider dateAuditing() {
        return CurrentDateTimeProvider.INSTANCE;
    }

    @Bean
    public DynamoDBMappingContext dynamoDBMappingContext() {
        DynamoDBMappingContext mappingContext = new DynamoDBMappingContext();

        //add your 'entities' manually 
        mappingContext.getPersistentEntity(YourEntity.class); 

        return mappingContext;
    }

    // do further configuration stuff...
}

YourEntity.java

@DynamoDBTable(tableName = "YourEntity")
public class YourEntity {
   @CreatedDate
   @DynamoDBAttribute
   @DynamoDBTypeConverted(converter = LocalDateTimeConverter.class)
   private LocalDateTime createdOn;

   @CreatedBy
   @DynamoDBAttribute
   private String createdBy;

   @LastModifiedDate
   @DynamoDBAttribute
   @DynamoDBTypeConverted(converter = LocalDateTimeConverter.class)
   private LocalDateTime updatedOn;

   @LastModifiedBy
   @DynamoDBAttribute
   private String updatedBy;

   // add further properties...
}

I know that there are some other solutions like @DynamoDBAutoGeneratedTimestamp and the usage of their strategies, but in my mind that's the cleanest solution regarding the use of spring.

lhaidacher
  • 161
  • 4
2

The annotaion @DynamoDBAutoGeneratedTimestamp can be used along with DynamoDBAutoGenerateStrategy to audit the item.

Strategy CREATE (Use this for Create audit):-

@DynamoDBAutoGeneratedTimestamp(strategy=DynamoDBAutoGenerateStrategy.CREATE)
 public Date getCreatedDate() { return createdDate; }
 public void setCreatedDate(Date createdDate) { this.createdDate = createdDate; }

Strategy ALWAYS (Use this if you want last modified date):-

 @DynamoDBAutoGeneratedTimestamp(strategy=DynamoDBAutoGenerateStrategy.ALWAYS)
 public Date getLastUpdatedDate() { return lastUpdatedDate; }
 public void setLastUpdatedDate(Date lastUpdatedDate) { this.lastUpdatedDate = lastUpdatedDate; }

If you want both create timestamp and last modified timestamps, please create two different attributes. One attribute should use CREATE strategy and other one should use ALWAYS strategy.

AutoGeneratedTimeStamp

notionquest
  • 37,595
  • 6
  • 111
  • 105
  • Hey, Thanks for the response, but my problem is not saving dates, I want to save `CreatedBy` and `LastModifiedBy`. – Kaushal28 Feb 16 '18 at 13:12
  • CreatedBy and LastModifiedBy are user ids which you need to set in your application. – notionquest Feb 16 '18 at 13:14
  • yes, But in my application, different users logs in and the updates they database, so I want to set these fields by getting currently logged in user dynamically. – Kaushal28 Feb 16 '18 at 13:16
  • I know how to set these fields statically but the problem is how to make annotations aware of these changes at run time? – Kaushal28 Feb 16 '18 at 13:18