I am experimenting with Javers 3.5.1's ability to report back changes that are committed. It appears that changes are only reported if they are primitives; when an object reference changes in the hierarchy of an entity, the changes is not reported back.
Here is a sample:
Javers javers = JaversBuilder.javers().build();
RegexRegisteredService svc2 = new RegexRegisteredService();
// Set a reference to something
svc2.setUsernameAttributeProvider(new DefaultRegisteredServiceUsernameProvider());
svc2.setId(345);
javers.commit("345", svc2);
// change the reference
svc2.setUsernameAttributeProvider(new AnonymousRegisteredServiceUsernameAttributeProvider());
javers.commit("345", svc2);
List<Change> changes = javers.findChanges(QueryBuilder.byInstanceId("345",
RegexRegisteredService.class).build());
System.out.println(changes.size());
The outcome of the above code snippet is 0.
Further diagnostics show that object references in the containing classes get their own id; the findChanges()
function only looks at the containing class/entity with that id, and does not traverse down the hierarchy to locate other references and properties. When in the InMemoryRepository begins to compare snapshots from history to the globalId that is passed, it will only look at the parent globalId and will not go down the list of contained classes:
Iterator it = this.getAll().iterator();
while(it.hasNext()) {
CdoSnapshot snapshot = (CdoSnapshot) it.next();
if (snapshot.getGlobalId().equals(globalId)) {
filtered.add(snapshot);
}
...
Here, the globalId
that is passed is org.apereo.cas.services.RegexRegisteredService/345
. However, nothing in this id has changed; what has really changed is mapped to org.apereo.cas.services.RegexRegisteredService/345#usernameAttributeProvider
which will never be retrieved because the above check fails the equality condition.
The hierarchy is as such:
public interface RegisteredService {}
public abstract class AbstractService implements RegisteredService {
// with setters and getters
private UsernameAttributeProviderInterface usernameAttributeProvider;
}
public class RegexRegisteredService extends AbstractService {}
How about something like this instead?
Iterator it = this.getAll().iterator();
while(it.hasNext()) {
CdoSnapshot snapshot = (CdoSnapshot) it.next();
if (snapshot.getGlobalId().value().startsWith(globalId.value())) {
filtered.add(snapshot);
}
...
Is this functionality absent in Javers, or have I missed something? Wondering if I should perhaps design my own repository class?
Turns out that I needed to do something quite simple:
final List<Change> changes = javers.findChanges(
QueryBuilder.byInstanceId("345, RegexRegisteredService.class)
.withChildValueObjects()
.build());
Reference: https://javers.org/documentation/jql-examples/#child-value-objects-filter