Search code examples
javajavers

Record Map Changes with JaVers


Is it possible to record changes to values in a Map with JaVers?

I would like to record all changes (Add, Update and Remove) to my RecordStore object so that I have an audit trail of what has happened. At the moment, I'm using the following code, and committing after every change.

private Map<String, Record> records = new HashMap<>();
private Javers history = JaversBuilder.javers().build();

public RecordStore(){
    history.commit("user", records);
}

public void addRecord(Record a){
    records.put(a.getId(), a);
    history.commit("user", records);
}
public void removeRecord(Record a){
    records.remove(a.getId());
    history.commit("user", records);
}
public void updateRecord(Record a){
    records.put(a.getId(), a);
    history.commit("user", records);
}

public String printHistory(){
    List<Change> changes = history.findChanges(QueryBuilder.anyDomainObject().build());
    return history.processChangeList(changes, new SimpleTextChangeLog());
}

However, the change list produced by JaVers (printHistory()) only has EntryAdded and EntryRemoved records in it. Worse than that, it is using the changed value throughout the log rather than only after the change. I've not used JaVers before, so any help getting it to work as desired would be appreciated. A test class using the RecordStore is below:

public static void main(String[] args){
    RecordStore store = new RecordStore();

    Record a1 = new Record();
    a1.setStart(0);
    a1.setEnd(5);
    a1.setValue("James");
    store.addRecord(a1);

    Record a2 = new Record();
    a2.setStart(10);
    a2.setEnd(15);
    a2.setValue("Jimmy");
    store.addRecord(a2);

    Record a3 = new Record();
    a3.setStart(20);
    a3.setEnd(25);
    a3.setValue("Jimbo");
    store.addRecord(a3);

    a2.setValue("JIMMY");
    store.updateRecord(a2);

    store.removeRecord(a1);

    System.out.println(store.printHistory());
}

Solution

  • Usually, you commit domain objects one by one, for example:

    public void addRecord(Record a){
        records.put(a.getId(), a);
        history.commit("user", a);
    }
    public void removeRecord(Record a){
        records.remove(a.getId());
        history.commitShallowDelete("user", a);
    }
    public void updateRecord(Record a){
        records.put(a.getId(), a);
        history.commit("user", a); 
    }
    

    but then, Record should be mapped as Entity type (with @Id).