Panache when used with method reference
See original GitHub issueDescribe the bug
Quarkus fails to augment a Panache operation when using method reference rather than a the corresponding method invocation in a lambda expression (like in a map).
Expected behavior Method reference should works just as standard method invocation
Actual behavior Whenver a method reference to a Panache Operation is used the operation fails with a stack trace indicating the Panache method has not been augmented
Caused by: java.lang.IllegalStateException: This method is normally automatically overridden in subclasses: did you forget to annotate your entity with @Entity?
at io.quarkus.hibernate.orm.panache.runtime.JpaOperations.implementationInjectionMissing(JpaOperations.java:411)
at io.quarkus.hibernate.orm.panache.PanacheEntityBase.findById(PanacheEntityBase.java:104)
at java.base/java.util.Optional.map(Optional.java:265)
at org.acme.FruitResource.getFruitNameWithMethodReference(FruitResource.java:35)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:167)
at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:130)
at org.jboss.resteasy.core.ResourceMethodInvoker.internalInvokeOnTarget(ResourceMethodInvoker.java:621)
at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:487)
at org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invokeOnTarget$2(ResourceMethodInvoker.java:437)
at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:362)
at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:439)
at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:400)
at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:374)
at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:67)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:488)
To Reproduce
Steps to reproduce the behavior:
Here you have a reproducer:
https://github.com/danielpetisme/panache-method-reference-issue
Simply clone and go with ./mvnw compile test
In a nutshell
@GET
@Path("/with-method-invocation/{id}")
@Produces(MediaType.TEXT_PLAIN)
public String getFruitNameWithMethodInvocation(@PathParam("id") Long id) {
return Optional.of(id).map(it -> Fruit.<Fruit>findById(it)).map(it -> it.name.toUpperCase()).orElse("Error");
}
@GET
@Path("/with-method-reference/{id}")
@Produces(MediaType.TEXT_PLAIN)
public String getFruitNameWithMethodReference(@PathParam("id") Long id) {
return Optional.of(id).map(Fruit::<Fruit>findById).map(it -> it.name.toUpperCase()).orElse("Error");
}
@Test
public void testWithMethodReference() {
given()
.when().get("/fruits/with-method-reference/1")
.then()
.statusCode(200)
.body(is("APPLE"));
}
@Test
public void testWithMethodInvocation() {
given()
.when().get("/fruits/with-method-invocation/1")
.then()
.statusCode(200)
.body(is("APPLE"));
}
The second test will fail
Configuration
# Add your application.properties here, if applicable.
Screenshots (If applicable, add screenshots to help explain your problem.)
Environment (please complete the following information):
- Output of
uname -aorver:
Darwin Daniels-MacBook-Pro.local 18.7.0 Darwin Kernel Version 18.7.0: Thu Jan 23 06:52:12 PST 2020; root:xnu-4903.278.25~1/RELEASE_X86_64 x86_64
- Output of
java -version:
openjdk version "11.0.4" 2019-07-16
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.4+11)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.4+11, mixed mode)
- GraalVM version (if different from Java):
- Quarkus version or git rev:
1.3.0.Final - Build tool (ie. output of
mvnw --versionorgradlew --version):
Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f)
Maven home: /Users/daniel/.m2/wrapper/dists/apache-maven-3.6.3-bin/1iopthnavndlasol9gbrbg6bf2/apache-maven-3.6.3
Java version: 11.0.4, vendor: AdoptOpenJDK, runtime: /Users/daniel/.jabba/jdk/adopt@1.11.0-4/Contents/Home
Default locale: en_GB, platform encoding: UTF-8
OS name: "mac os x", version: "10.14.6", arch: "x86_64", family: "mac"
Additional context (Add any other context about the problem here.)
Issue Analytics
- State:
- Created 3 years ago
- Reactions:1
- Comments:12 (11 by maintainers)
Top Related StackOverflow Question
Given:
Bottom.foo()will be encoded asINVOKESTATIC Bottom.foowhileBottom::foowill be encoded as an INDY callingINVOKESTATIC Top.foo.It looks like this information is still available in the type in the BootstrapMethods attribute. Looking at the example in jclasslib you can infer that the type is Fruit.
This won’t be super simple to do though, it looks like ASM does not have direct support for this attribute. In theory you would do this at the same time as the field access enhancement, look through the BootstrapMethods table for access to PanacheEntityBase, and then change the type based on the signature.