Description
Clear description of my expectations versus reality
Comparing java.nio.file.Path
objects fails with an java.lang.reflect.InaccessibleObjectException
when building the object graph when trying to make the classes sun.nio.fs.UnixFileSystem
(or respectively sun.nio.fs.WindowsFileSystem
) accessible.
We tried the following to get around the Problem:
JaversBuilder#registerIgnoredClass(Path.class)
does not help- Building a
CustomPropertyComparator
for the wrapping type could be a solution, but is not feasible for us, since the type is rather complicated. - Neither can we use the
@DiffIgnore
annotation as we do not have control over the compared type
However, I think all these solutions would trigger the Graph build anyway, and to not prevent the exception.
I would expect Javers to:
- have an option to compare
Path
objects as theirtoString
interpretation - be able to compare Objects of the type
Path
- have an option to ignore
Path
objects (which it might have already once the reflection exception is fixed)
Additionally, if a field is marked as ignored, it may not be necessary to be included in the graph building process.
The issue appears analogue on Windows with WindowsFileSystem
and WindowsPath.fs.
Here is a full stack trace:
java.lang.reflect.InaccessibleObjectException: Unable to make field private final sun.nio.fs.WindowsFileSystem sun.nio.fs.WindowsPath.fs accessible: module java.base does not "opens sun.nio.fs" to unnamed module @63e2203c
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354)
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297)
at java.base/java.lang.reflect.Field.checkCanSetAccessible(Field.java:178)
at java.base/java.lang.reflect.Field.setAccessible(Field.java:172)
at org.javers.common.reflection.JaversMember.setAccessibleIfNecessary(JaversMember.java:95)
at org.javers.common.reflection.JaversMember.<init>(JaversMember.java:47)
at org.javers.common.reflection.JaversMember.<init>(JaversMember.java:39)
at org.javers.common.reflection.JaversField.<init>(JaversField.java:17)
at org.javers.common.reflection.JaversFieldFactory.createJField(JaversFieldFactory.java:43)
at org.javers.common.reflection.JaversFieldFactory.getAllFields(JaversFieldFactory.java:31)
at org.javers.common.reflection.ReflectionUtil.getAllFields(ReflectionUtil.java:125)
at org.javers.common.reflection.ReflectionUtil.getAllPersistentFields(ReflectionUtil.java:110)
at org.javers.core.metamodel.scanner.FieldBasedPropertyScanner.getMembers(FieldBasedPropertyScanner.java:19)
at org.javers.core.metamodel.scanner.PropertyScanner.scan(PropertyScanner.java:27)
at org.javers.core.metamodel.scanner.ClassScanner.scan(ClassScanner.java:19)
at org.javers.core.metamodel.type.TypeFactory$JavaRichType.lambda$new$0(TypeFactory.java:196)
at org.javers.core.metamodel.type.TypeFactory$JavaRichType.getScan(TypeFactory.java:209)
at org.javers.core.metamodel.type.TypeFactory.inferFromAnnotations(TypeFactory.java:164)
at org.javers.core.metamodel.type.TypeFactory.lambda$infer$4(TypeFactory.java:107)
at java.base/java.util.Optional.orElseGet(Optional.java:364)
at org.javers.core.metamodel.type.TypeFactory.infer(TypeFactory.java:107)
at org.javers.core.metamodel.type.TypeMapper.lambda$getJaversType$0(TypeMapper.java:110)
at org.javers.core.metamodel.type.TypeMapperEngine.computeIfAbsent(TypeMapperEngine.java:111)
at org.javers.core.metamodel.type.TypeMapper.getJaversType(TypeMapper.java:110)
at org.javers.core.metamodel.type.TypeMapper.getJaversManagedType(TypeMapper.java:170)
at org.javers.core.metamodel.type.TypeMapper.getJaversManagedType(TypeMapper.java:161)
at org.javers.core.metamodel.object.GlobalIdFactory.createId(GlobalIdFactory.java:45)
at org.javers.core.graph.LiveCdoFactory.create(LiveCdoFactory.java:37)
at org.javers.core.graph.EdgeBuilder.buildSingleEdge(EdgeBuilder.java:33)
at org.javers.core.graph.ObjectGraphBuilder.buildSingleEdges(ObjectGraphBuilder.java:107)
at org.javers.core.graph.ObjectGraphBuilder.buildEdges(ObjectGraphBuilder.java:97)
at org.javers.core.graph.ObjectGraphBuilder.buildGraphFromCdo(ObjectGraphBuilder.java:65)
at org.javers.core.graph.ObjectGraphBuilder.buildGraph(ObjectGraphBuilder.java:54)
at org.javers.core.graph.LiveGraphFactory.createLiveGraph(LiveGraphFactory.java:38)
at org.javers.core.diff.DiffFactory.buildGraph(DiffFactory.java:102)
at org.javers.core.diff.DiffFactory.compare(DiffFactory.java:55)
at org.javers.core.JaversCore.compare(JaversCore.java:176)
Steps To Reproduce
This issue can be reproduced by a simple test:
@Test
void testJaversBuilder() {
var javers = JaversBuilder.javers().build()
javers.compare(Path.of("foo"), Path.of("bar"))
}
A more elaborate test with a wrapping value-object class can be found here:
https://gist.github.com/LitschiW/ec39565305cf2fc911ddd4ad3f708f39
Javers' Version
7.3.6
also fails on 6.14.0
Additional context
According to microsoft/playwright-java#423 this issue might be related to google/gson#1875 which is unfortunately already marked fixed. Apparently, sun.nio.fs.UnixFileSystem
and sun.nio.fs.WindowsFileSystem
are package internal classes and therefore cannot be accessed via refection anymore in Java >=16 requiring an additional adapter.