Java 14 -> IllegalStateException: Could not resolve sufficient generic type information
Hi, I have an application that runs fine with Java 8 and 11 but if I run it with Java 14, I get this error:
Caused by: java.lang.IllegalStateException: Could not resolve sufficient generic type information from the given function of type: org.greeneyed.epl.librarian.model.Libro$$Lambda$569/0x0000000801026440, resolved: [class net.jodah.typetools.TypeResolver$Unknown, class net.jodah.typetools.TypeResolver$Unknown]. If the function you supplied was created from a lambda expression, then it's likely that the host JVM does not allow the generic type information to be read from lambda expressions. Alternatively, if you supplied a class-based implementation of the function, then you must ensure that you specified the generic types of the function when it was compiled. As a workaround, you can use the counterpart methods in QueryFactory which allow the generic types to be specified explicitly.
at com.googlecode.cqengine.query.QueryFactory.validateSimpleFunctionGenericTypes(QueryFactory.java:1136)
at com.googlecode.cqengine.query.QueryFactory.resolveSimpleFunctionGenericTypes(QueryFactory.java:1122)
at com.googlecode.cqengine.query.QueryFactory.attribute(QueryFactory.java:900)
at org.greeneyed.epl.librarian.model.Libro.<clinit>(Libro.java:42)
The code where it breaks is a simple attribute definition:
public static final SimpleAttribute<Libro, Integer> LIBRO_ID = attribute(LIBRO_ID_PARAM,Libro::getId);
Where getId() returns an Integer.
The solution is to change the attribute defition so it includes the type attributes explicitely
public static final SimpleAttribute<Libro, Integer> LIBRO_ID = attribute(Libro.class, Integer.class, LIBRO_ID_PARAM,Libro::getId);
and that way, it works with all JDKs.
It might be a JDK or TypeResolver limitation, and it is documented, but I wanted to open an issue so people looking for a solution would be able to find it easily.
Cheers!
Thanks for reporting this actually. This is definitely something that I think CQEngine should support if possible on Java 14.
Right now, there is actually no official support to read generic types from lambda expressions. Each specific JVM requires a different method to achieve that.
Currently CQEngine uses a helpful library called TypeTools to do this. It implements those different strategies depending on the host JVM.
My guess is that in Java 14, the internal APIs were changed such that Type Tools can't do that. When this happens CQEngine will then throw that exception you saw.
This might be the root cause: https://github.com/jhalterman/typetools/issues/56
Unfortunately I don't see a newer version of TypeTools yet, which might support newer JVMs. So I am not sure what we can do about it currently. I'll keep this issue open until we can find a solution.
@npgall @Verdoso a new version of typetools has been released 20 days ago, and judging by the changelog, it resolves this issue.
Same for Eclipse Temurin JDK 17
Exception in thread "main" java.lang.ExceptionInInitializerError
at com.company.jl.service.cache.Cache.<init>(Cache.java:27)
at com.company.jl.App.main(App.java:38)
Caused by: java.lang.IllegalStateException: Could not resolve sufficient generic type information from the given function of type: com.company.jl.service.cache.Members$$Lambda$137/0x0000000800e1bd28, resolved: [class net.jodah.typetools.TypeResolver$Unknown, class net.jodah.typetools.TypeResolver$Unknown]. If the function you supplied was created from a lambda expression, then it's likely that the host JVM does not allow the generic type information to be read from lambda expressions. Alternatively, if you supplied a class-based implementation of the function, then you must ensure that you specified the generic types of the function when it was compiled. As a workaround, you can use the counterpart methods in QueryFactory which allow the generic types to be specified explicitly.
at com.googlecode.cqengine.query.QueryFactory.validateSimpleFunctionGenericTypes(QueryFactory.java:1136)
at com.googlecode.cqengine.query.QueryFactory.resolveSimpleFunctionGenericTypes(QueryFactory.java:1122)
at com.googlecode.cqengine.query.QueryFactory.attribute(QueryFactory.java:900)
at com.company.jl.service.cache.Members.<clinit>(Members.java:30)
... 2 more
openjdk version "17" 2021-09-14
OpenJDK Runtime Environment Temurin-17+35 (build 17+35)
OpenJDK 64-Bit Server VM Temurin-17+35 (build 17+35, mixed mode, sharing)
@sheinbergon, I have tried to update typetools to v0.6.3, antlr4 to v4.9.2, and kryo to v5.2.0, but I got exceptions with kryo-serializers in tests. Particularly in the next rows
kryo.register(Arrays.asList().getClass(), new ArraysAsListSerializer());
UnmodifiableCollectionsSerializer.registerSerializers(kryo);
SynchronizedCollectionsSerializer.registerSerializers(kryo);
@npgall, maybe you have some ideas?
Arrays.asList().getClass() already added in kryo v5.0.0 default serialisers (see Kryo.java#L225), so it can be dropped.
I bumped dependencies and disabled serializers above (see https://github.com/lvitaly/cqengine/commit/393fc030c799f04e81b9e1f77bf6e0e25fdf2af3). Only one test failed, and two skipped in the result. So my application is running fine with the build from this commit.
testEqualsAndHashCode(com.googlecode.cqengine.attribute.ReflectiveAttributeTest) Time elapsed: 0.588 sec <<< FAILURE!
java.lang.AssertionError: EqualsVerifier found a problem in class com.googlecode.cqengine.attribute.ReflectiveAttribute.
-> Reflexivity: == used instead of .equals() on field: field
If this is intentional, consider suppressing Warning.REFERENCE_EQUALITY
For more information, go to: http://www.jqno.nl/equalsverifier/errormessages
at nl.jqno.equalsverifier.api.SingleTypeEqualsVerifierApi.verify(SingleTypeEqualsVerifierApi.java:306)
at com.googlecode.cqengine.attribute.ReflectiveAttributeTest.testEqualsAndHashCode(ReflectiveAttributeTest.java:76)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:252)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:141)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:112)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189)
at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165)
at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:115)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75)
Caused by: nl.jqno.equalsverifier.internal.exceptions.AssertionException
at nl.jqno.equalsverifier.internal.util.Assert.assertEquals(Assert.java:25)
at nl.jqno.equalsverifier.internal.checkers.fieldchecks.ReflexivityFieldCheck.checkValueReflexivity(ReflexivityFieldCheck.java:95)
at nl.jqno.equalsverifier.internal.checkers.fieldchecks.ReflexivityFieldCheck.execute(ReflexivityFieldCheck.java:47)
at nl.jqno.equalsverifier.internal.checkers.FieldInspector.check(FieldInspector.java:29)
at nl.jqno.equalsverifier.internal.checkers.FieldsChecker.check(FieldsChecker.java:61)
at nl.jqno.equalsverifier.api.SingleTypeEqualsVerifierApi.verifyWithExamples(SingleTypeEqualsVerifierApi.java:413)
at nl.jqno.equalsverifier.api.SingleTypeEqualsVerifierApi.performVerification(SingleTypeEqualsVerifierApi.java:369)
at nl.jqno.equalsverifier.api.SingleTypeEqualsVerifierApi.verify(SingleTypeEqualsVerifierApi.java:304)
... 33 more
Results :
Failed tests: testEqualsAndHashCode(com.googlecode.cqengine.attribute.ReflectiveAttributeTest): EqualsVerifier found a problem in class com.googlecode.cqengine.attribute.ReflectiveAttribute.(..)
Tests run: 10825, Failures: 1, Errors: 0, Skipped: 2