cqengine icon indicating copy to clipboard operation
cqengine copied to clipboard

Java 14 -> IllegalStateException: Could not resolve sufficient generic type information

Open Verdoso opened this issue 5 years ago • 7 comments

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!

Verdoso avatar Aug 28 '20 19:08 Verdoso

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 avatar Oct 02 '20 21:10 npgall

@npgall @Verdoso a new version of typetools has been released 20 days ago, and judging by the changelog, it resolves this issue.

sheinbergon avatar Apr 29 '21 12:04 sheinbergon

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)

lvitaly avatar Sep 25 '21 17:09 lvitaly

@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);

lvitaly avatar Sep 27 '21 13:09 lvitaly

@npgall, maybe you have some ideas?

lvitaly avatar Sep 27 '21 14:09 lvitaly

Arrays.asList().getClass() already added in kryo v5.0.0 default serialisers (see Kryo.java#L225), so it can be dropped.

lvitaly avatar Sep 30 '21 14:09 lvitaly

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

lvitaly avatar Sep 30 '21 16:09 lvitaly