javers / javers

JaVers - object auditing and diff framework for Java
http://javers.org
Apache License 2.0
1.35k stars 353 forks source link

Add a method to fetch Snapshots or Changes by (multiple) local ID without the need of TypeName or Class #1011

Open nishkarsh opened 3 years ago

nishkarsh commented 3 years ago

Requirement I am working on a project that involves Entities (saved in Mongo) to be associated with IDs as properties. For example, A User has addressId that references Address being a separate Entity since it follows a separate lifecycle. All the changes to these entities are being audited using Javers in a central repository (through a Microservice). As a part of the functionality, I need to display consolidated audit logs on a Web UI. Trouble is the fetching of the audits for multiple entities of different types. Since the methods to build a JqlQuery take either a TypeName or a Class along with the instance IDs, the clients always need to have more knowledge than they should have to fetch the logs.

Describe the solution you'd like Since our entities have unique IDs (UUID), there should be no need of supplying the TypeName or the entity Class to fetch the CdoSnapshots or the Changes since the clients have access to the main entity and the IDs of the associated entities that they can use directly. At the same time, there could be a method that would accept multiple instanceIds without the Class or TypeName. Either this or there should be scope to supply a custom FilterDefinition to the QueryBuilder to allow defining a custom matcher where we could use different criteria for matching a CdoSnapshot or Changes.

Describe alternatives you've considered One of the alternatives we have right now is to annotate each and every entity with a @TypeName across microservices and the client knowing all these TypeName for each of the properties of the main entity to be able to fetch the audits. This is a huge overkill. Even with that, there is no way of fetching the audits for multiple entities and instanceIds together limited by pages.

bartoszwalacik commented 3 years ago

Hi, since a client know an Id of an object, why it in the same time doesn't know its type name?

nishkarsh commented 3 years ago

Hey @bartoszwalacik! Thanks for the question. The reason to avoid clients from knowing the exact TypeName is for simplicity. The exact types or the class names along with the package names need not be known by the clients. When IDs are unique, there is no reason to hardcode the type-names or the full path-names of the classes it's dealing with as it would lead to unneeded maintenance overhead. The client fetches the parent entity and gets to know the IDs of everything that's associated and should be able to fetch Audits for all of them with just that much information.

bartoszwalacik commented 3 years ago

Doesn't look like a common use case for me, but fair enough to be implemented. Are you going to contribute? Change should be implemented for both Mongo and SQL repositories. Database indexing is the issue, I don't know if existing indexes would work when queried only by id, it should be checked before starting any work in code.

nishkarsh commented 3 years ago

Hey @bartoszwalacik! Thanks for the response. I will spend some time in verifying if the existing indexes would work with this. I will also discuss the changes that might be required before proceeding.

michaelkrog commented 1 year ago

I second this.

In our case we have a Spring boot based library that can be used in multiple services. One of the things it supplies is Javers - but being an external library it won't know anything about all the entities that are persisted in the application it is used in.

But what we do have is unique ids that's is prefixed with the data type, fx. a Contact could have the id cont-1234, Note could have note-1234. In other words our id's are unique AND carry the type in them.

Therefore it could be awesome to be able to simply get its changes by QueryBuilder.byInstanceId("cont-1234").

What we need to do now is to add @TypeName to all entities with the type part of our id(fx. @TypeName("cont")) and then retrieve them by extracting the type part from the id before resolving:

var type = id.split("-")[0]; // Get 'cont' from 'cont-1234'
var query = QueryBuilder.byInstanceId(id, type).build();