Panache when used with method reference

See original GitHub issue

Describe 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 -a or ver:
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 --version or gradlew --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:open
  • Created 3 years ago
  • Reactions:1
  • Comments:12 (11 by maintainers)

github_iconTop GitHub Comments

1reaction
FroMagecommented, Mar 30, 2020

Given:

class Top {
 static void foo(){}
}
class Bottom extends Top {
}

Bottom.foo() will be encoded as INVOKESTATIC Bottom.foo while Bottom::foo will be encoded as an INDY calling INVOKESTATIC Top.foo.

0reactions
stuartwdouglascommented, Jul 8, 2020

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.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Simplified Hibernate ORM with Panache - Quarkus
You can reference a named query instead of a (simplified) HQL query by prefixing its name with the '#' character. You can also...
Read more >
Panache - Active Record Pattern - Thorben Janssen
It provides methods to find all records, find one record by its primary key, and persist, update, or remove a database record. In...
Read more >
Panache: Query by Specification, Criteria or Example
Today, when using Hibernate with Panache, you must write your queries as ... play well if people uses setters/getters as they can now...
Read more >
REST API using Quarkus and Panache | by Manollo Guedes
As mentioned before, Panache has a focus on turning our entity management easier. To do that, it gives us a utility belt having...
Read more >
quarkus reactive getting started PUT and DELETE operations
... using method reference with withTransaction . On the other hand, one can use Panache. ... This is how method reference works in...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found