New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EntityType and ValueObjectType spawning/interring not working properly with Serializable interface (or other parent interfaces) #601

Closed
philippeboyd opened this Issue Nov 17, 2017 · 4 comments

Comments

Projects
None yet
2 participants
@philippeboyd

philippeboyd commented Nov 17, 2017

So I've encountered a weird bug (or feature?) in Javers. The method ReflectionUtil.calculateHierarchyDistance() calculates the distance to be used in TypeMapperState.findNearestAncestor(). However, in the latter method there's this check if(distances.get(0).isMax()) that will allow a null value to be returned by the method to be then used as an Optional.ofNullable(prototype) in the TypeMapperState.infer which will cause the prototype to NOT be present in the TypeFactory.infer() method which will then allow the javatype to be passed to inferFromAnnotations and eventually end up as an EntityType and not a ValueObjectType.

Here is my class hierarchy:

AbstractPermission -> Permission
AbstractPermission -> Role

Here are the logs :

With Serializable interface on parent class

o.j.core.metamodel.type.TypeFactory      : javersType of interface java.io.Serializable inferred as ValueObjectType

o.j.core.metamodel.type.TypeFactory      : javersType of class org.javers.mongo.javersmongoproblem.domain.Permission inferred as EntityType
o.j.core.metamodel.type.TypeFactory      : javersType of class java.lang.String inferred as ValueType, it's used as id-property type

o.j.core.metamodel.type.TypeFactory      : javersType of java.util.Set<java.lang.String> spawned as SetType from prototype SetType{baseType:interface java.util.Set}

o.j.core.metamodel.type.TypeFactory      : javersType of class org.javers.mongo.javersmongoproblem.domain.Role spawned as ValueObjectType from prototype ValueObjectType{baseType:interface java.io.Serializable}

o.j.core.metamodel.type.TypeFactory      : javersType of java.util.Set<org.javers.mongo.javersmongoproblem.domain.Permission> spawned as SetType from prototype SetType{baseType:java.util.Set<java.lang.String>}

Without Serializable interface on parent class

o.j.core.metamodel.type.TypeFactory      : javersType of interface java.io.Serializable inferred as ValueObjectType

o.j.core.metamodel.type.TypeFactory      : javersType of class org.javers.mongo.javersmongoproblem.domain.Permission inferred as EntityType
o.j.core.metamodel.type.TypeFactory      : javersType of class java.lang.String inferred as ValueType, it's used as id-property type

o.j.core.metamodel.type.TypeFactory      : javersType of java.util.Set<java.lang.String> spawned as SetType from prototype SetType{baseType:interface java.util.Set}

o.j.core.metamodel.type.TypeFactory      : javersType of class org.javers.mongo.javersmongoproblem.domain.Role inferred as EntityType
o.j.core.metamodel.type.TypeFactory      : javersType of class java.lang.String inferred as ValueType, it's used as id-property type

o.j.core.metamodel.type.TypeFactory      : javersType of java.util.Set<org.javers.mongo.javersmongoproblem.domain.Permission> spawned as SetType from prototype SetType{baseType:java.util.Set<java.lang.String>}

When AbstractPermission doesn't implement Serializable both object are known as EntityType during.

When AbstractPermission implements Serializable, Role object will get spawned as ValueObjectType from prototype ValueObjectType{baseType:interface java.io.Serializable} and will get the following error when getting changes

QueryBuilder jqlQuery2 = QueryBuilder.byInstanceId(permissionReadUser.getId(), Permission.class);
List<Change> changes2 = javers.findChanges(jqlQuery2.build());

Will throw a :

Caused by: org.javers.common.exception.JaversException: MANAGED_CLASS_MAPPING_ERROR: given javaClass 'class org.javers.mongo.javersmongoproblem.domain.Permission' is mapped to ValueObjectType, expected EntityType

It's a really complex problem and I'm pretty sure ReflectionUtil.calculateHierarchyDistance() isn't calculating something right...

You can test my case with my repository https://github.com/philippeboyd/javers-issue-managed-type

@bartoszwalacik

This comment has been minimized.

Member

bartoszwalacik commented Nov 17, 2017

Interesting case. Thanks for providing the runnable test. I will take a look at this.

@philippeboyd

This comment has been minimized.

philippeboyd commented Nov 17, 2017

I just found a workaround. Instead of letting Javers creating those Managed Type, I copied the Javers bean from the JaversMongoAutoConfiguration class and explicitly registered my Classes like so :

@DependsOn("mongoTemplate")
@Bean
public Javers javers(MongoTemplate mongoTemplate, JaversProperties javersProperties) {
	return JaversBuilder.javers()
		.withListCompareAlgorithm(ListCompareAlgorithm.valueOf(javersProperties.getAlgorithm().toUpperCase()))
		.withMappingStyle(MappingStyle.valueOf(javersProperties.getMappingStyle().toUpperCase()))
		.withNewObjectsSnapshot(javersProperties.isNewObjectSnapshot())
		.withPrettyPrint(javersProperties.isPrettyPrint())
		.withTypeSafeValues(javersProperties.isTypeSafeValues())
		.registerJaversRepository(new MongoRepository(mongoTemplate.getDb()))
		.withPackagesToScan(javersProperties.getPackagesToScan())
		.registerEntities(Role.class, Permission.class) // <-- added line
		.build();
}

I'll leave this open for you @bartoszwalacik if you want to dig a little deeper.

@bartoszwalacik

This comment has been minimized.

Member

bartoszwalacik commented Nov 18, 2017

It's a good workaround, you can register your types explicitly but type inferring should also work. I will check why it doesn't.

bartoszwalacik added a commit that referenced this issue Nov 20, 2017

bartoszwalacik added a commit that referenced this issue Nov 23, 2017

@bartoszwalacik

This comment has been minimized.

Member

bartoszwalacik commented Nov 24, 2017

fix released in 3.7.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment