Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Abstraction layer over PanacheRepositoryBase #5885

Closed
lssoares opened this issue Nov 29, 2019 · 14 comments · Fixed by #6191
Closed

Abstraction layer over PanacheRepositoryBase #5885

lssoares opened this issue Nov 29, 2019 · 14 comments · Fixed by #6191
Labels
Milestone

Comments

@lssoares
Copy link

Describe the bug
When implementing an abstraction over the PanacheRepositoryBase, I get the error when calling findById method:

org.hibernate.UnknownEntityTypeException: Unable to locate persister: org.acme.base.AbstractBaseLongEntity

Expected behavior
findById() should work when using an Abstraction layer, as findAll() just works.

Actual behavior
(Describe the actual behavior clearly and concisely.)

To Reproduce
Steps to reproduce the behavior:

  1. clone this repo: https://github.com/lssoares/panache-abstraction-problem
  2. run ./mvn clean package && mvn quarkus:dev
  3. Use swagger to execute the following webservice: http://0.0.0.0:8080/example/1

Additional context
1.Calling the endpoint that uses findAll() works fine: http://0.0.0.0:8080/example
2. If you edit ExampleRepository.java and swap the lines indicated there, both endpoints will work.

@lssoares lssoares added the kind/bug Something isn't working label Nov 29, 2019
@loicmathieu
Copy link
Contributor

@issoares can you provides your Quarkus version, the list of features you use (from the qtartup log), your entity and the complete stacktrace please ?

@lssoares
Copy link
Author

lssoares commented Dec 2, 2019

@loicmathieu project was created using Quarkus website (https://code.quarkus.io/).

Quarkus version and features current being loaded:

mvn quarkus:dev
[INFO] Scanning for projects...
[INFO] 
[INFO] ---------------------< org.acme:code-with-quarkus >---------------------
[INFO] Building code-with-quarkus 1.0.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- quarkus-maven-plugin:1.0.1.Final:dev (default-cli) @ code-with-quarkus ---
Listening for transport dt_socket at address: 5005
2019-11-29 18:51:04 INFO  [org.acm.ApplicationMonitor]] (main) Connection Established: H2/TEST
2019-11-29 18:51:04 INFO  [io.quarkus]] (main) Quarkus 1.0.1.Final started in 2.840s. Listening on: http://0.0.0.0:8080
2019-11-29 18:51:04 INFO  [io.quarkus]] (main) Profile dev activated. Live Coding activated.
2019-11-29 18:51:04 INFO  [io.quarkus]] (main) Installed features: [agroal, cdi, hibernate-orm, hibernate-orm-panache, jdbc-h2, narayana-jta, resteasy, resteasy-jsonb, smallrye-openapi, swagger-ui]

Stacktrace:

2019-11-29 18:51:12 ERROR [io.qua.ver.htt.run.QuarkusErrorHandler]] (vert.x-worker-thread-3) HTTP Request to /example/1 failed, error id: 8b177e56-17b9-4f02-802f-b2906e432875-1: org.jboss.resteasy.spi.UnhandledException: java.lang.IllegalArgumentException: Unable to locate persister: org.acme.base.AbstractBaseLongEntity
        at org.jboss.resteasy.core.ExceptionHandler.handleApplicationException(ExceptionHandler.java:106)
        at org.jboss.resteasy.core.ExceptionHandler.handleException(ExceptionHandler.java:372)
        at org.jboss.resteasy.core.SynchronousDispatcher.writeException(SynchronousDispatcher.java:209)
        at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:496)
        at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:252)
        at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:153)
        at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:363)
        at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:156)
        at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:238)
        at io.quarkus.resteasy.runtime.standalone.RequestDispatcher.service(RequestDispatcher.java:73)
        at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.dispatch(VertxRequestHandler.java:118)
        at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.lambda$handle$0(VertxRequestHandler.java:74)
        at io.vertx.core.impl.ContextImpl.lambda$executeBlocking$2(ContextImpl.java:316)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
        at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
        at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.IllegalArgumentException: Unable to locate persister: org.acme.base.AbstractBaseLongEntity
        at org.hibernate.internal.SessionImpl.find(SessionImpl.java:3347)
        at org.hibernate.internal.SessionImpl.find(SessionImpl.java:3293)
        at io.quarkus.hibernate.orm.runtime.entitymanager.TransactionScopedEntityManager.find(TransactionScopedEntityManager.java:143)
        at io.quarkus.hibernate.orm.runtime.entitymanager.ForwardingEntityManager.find(ForwardingEntityManager.java:42)
        at io.quarkus.hibernate.orm.panache.runtime.JpaOperations.findById(JpaOperations.java:196)
        at org.acme.ExampleRepository.findById(ExampleRepository.java)
        at org.acme.ExampleRepository.findById(ExampleRepository.java)
        at org.acme.ExampleRepository_ClientProxy.findById(ExampleRepository_ClientProxy.zig:618)
        at org.acme.ExampleResource.find(ExampleResource.java:28)
        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:151)
        at org.jboss.resteasy.core.MethodInjectorImpl.lambda$invoke$3(MethodInjectorImpl.java:122)
        at java.base/java.util.concurrent.CompletableFuture.uniApplyNow(CompletableFuture.java:680)
        at java.base/java.util.concurrent.CompletableFuture.uniApplyStage(CompletableFuture.java:658)
        at java.base/java.util.concurrent.CompletableFuture.thenApply(CompletableFuture.java:2094)
        at java.base/java.util.concurrent.CompletableFuture.thenApply(CompletableFuture.java:143)
        at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:122)
        at org.jboss.resteasy.core.ResourceMethodInvoker.internalInvokeOnTarget(ResourceMethodInvoker.java:594)
        at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:468)
        at org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invokeOnTarget$2(ResourceMethodInvoker.java:421)
        at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:363)
        at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:423)
        at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:391)
        at org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invoke$1(ResourceMethodInvoker.java:365)
        at java.base/java.util.concurrent.CompletableFuture.uniComposeStage(CompletableFuture.java:1106)
        at java.base/java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:2235)
        at java.base/java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:143)
        at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:365)
        at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:477)
        ... 13 more
Caused by: org.hibernate.UnknownEntityTypeException: Unable to locate persister: org.acme.base.AbstractBaseLongEntity
        at org.hibernate.metamodel.internal.MetamodelImpl.locateEntityPersister(MetamodelImpl.java:721)
        at org.hibernate.internal.SessionImpl.locateEntityPersister(SessionImpl.java:2955)
        at org.hibernate.internal.SessionImpl.access$1800(SessionImpl.java:197)
        at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.<init>(SessionImpl.java:2684)
        at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.<init>(SessionImpl.java:2667)
        at org.hibernate.internal.SessionImpl.byId(SessionImpl.java:1122)
        at org.hibernate.internal.SessionImpl.find(SessionImpl.java:3315)
        ... 44 more

@lssoares
Copy link
Author

lssoares commented Dec 2, 2019

The entity:

@Entity
@Table(name = "example")
public class ExampleEntity extends AbstractBaseLongEntity {
    public String code;
}
@MappedSuperclass
public abstract class AbstractBaseLongEntity extends PanacheEntityBase {

    /**
     * The auto-generated ID field. This field is set by Hibernate ORM when this entity
     * is persisted.
     *
     * @see #persist()
     */
    @Id
    @GeneratedValue
    public Long id;

    @Override
    public String toString() {
        return this.getClass().getSimpleName() + "<" + id + ">";
    }
}

@loicmathieu
Copy link
Contributor

Note that you AbstractBaseLongEntity is the same code as PanacheEntity so you can use it instead.

But I tested the same aproach and it works. The org.hibernate.UnknownEntityTypeException: Unable to locate persister exception is an Hibernate related exception and don't seems to have something to do with Panache. Can you share your application.propertiesfile? Did you use any persistence.xml file?

@lssoares
Copy link
Author

lssoares commented Dec 2, 2019

AbstractBaseLongEntity for the convenience of the example is indeed the same as PanacheEntity, but unfortunately I will have to handle other legacy database tables where the PK is a String....

I don't have a persistence.xml

and I don't see anything special in the application properties:

# Configuration file
# key = value

# Logging
quarkus.log.console.enable=true
quarkus.log.console.format=%d{yyyy-MM-dd HH:mm:ss} %-5p [%c{3.}]] (%t) %s%e%n
quarkus.log.console.level=DEBUG
quarkus.log.console.color=true

quarkus.datasource.url=jdbc:h2:tcp://localhost/mem:test
quarkus.datasource.driver=org.h2.Driver
quarkus.datasource.username=sa
quarkus.datasource.password=as

Have you had the chance to try the project I uploaded?

@lssoares
Copy link
Author

lssoares commented Dec 2, 2019

Problem is "created" on

public abstract class AbstractBaseLongRepository<T extends AbstractBaseLongEntity>
implements PanacheRepositoryBase<T, Long> {
}

Then errors occurs when have a repository that extends the class above:

@ApplicationScoped
public class ExampleRepository extends AbstractBaseLongRepository<ExampleEntity> {
} 

...But if repository implements PanacheRepostitoryBase directly, it works correctly:

@ApplicationScoped
public class ExampleRepository implements PanacheRepositoryBase<ExampleEntity, Long> {
}

@loicmathieu
Copy link
Contributor

loicmathieu commented Dec 2, 2019

You mixed Repository and Entity implementation of Panache!
If you use the repository aproach, your entities must be regular JPA entities (not extending PanacheEntity nor PanacheEntityBase).

I was misleading you, you should be able to use a Repository with an Entity.

@lssoares
Copy link
Author

lssoares commented Dec 2, 2019

@loicmathieu Thanks! you're right. I was using both....my mistake.
Changing the entity will leave me in the repository pattern but unfortunately it won't work.

public abstract class AbstractBaseLongEntity //extends PanacheEntityBase 

@lssoares lssoares closed this as completed Dec 2, 2019
@lssoares lssoares reopened this Dec 2, 2019
@loicmathieu
Copy link
Contributor

@FroMage this bug uses a similar construct to what has been fixed via #5274 but it generates a different Hibernate error. The construct seems legit to me, maybe you will have an idea about it ...

@FroMage
Copy link
Member

FroMage commented Dec 3, 2019

Perhaps it's due to a generics issue not being properly instantiated. I guess we should look at the generated bytecode for findById

@FroMage
Copy link
Member

FroMage commented Dec 3, 2019

Yeah, it looks like we're generating Session.find(AbstractBaseEntity.class, id) instead of Session.find(ExampleEntity.class, id). So it seems like a generics problem.

@FroMage
Copy link
Member

FroMage commented Dec 12, 2019

Yeah, it looks worse, the Class we inject as first param is Object:

  public long count(java.lang.String, io.quarkus.panache.common.Parameters);
    descriptor: (Ljava/lang/String;Lio/quarkus/panache/common/Parameters;)J
    flags: ACC_PUBLIC, ACC_SYNTHETIC
    Code:
      stack=3, locals=3, args_size=3
         0: ldc           #23                 // class java/lang/Object
         2: aload         1
         4: aload         2
         6: invokestatic  #38                 // Method io/quarkus/hibernate/orm/panache/runtime/JpaOperations.count:(Ljava/lang/Class;Ljava/lang/String;Lio/quarkus/panache/common/Parameters;)J
         9: lreturn

FroMage added a commit to FroMage/quarkus that referenced this issue Dec 16, 2019
Do not enhance generic/abstract repos
Use proper generics resolution when looking up the repository type
arguments
@FroMage
Copy link
Member

FroMage commented Dec 16, 2019

Fix is at #6191

FroMage added a commit to FroMage/quarkus that referenced this issue Dec 16, 2019
FroMage added a commit that referenced this issue Dec 16, 2019
Fix #5885: generics break panache repo enhancer
@FroMage
Copy link
Member

FroMage commented Dec 16, 2019

Fixed.

@gsmet gsmet added this to the 1.2.0 milestone Dec 16, 2019
loicmathieu added a commit to loicmathieu/quarkus that referenced this issue Dec 19, 2019
loicmathieu added a commit to loicmathieu/quarkus that referenced this issue Jan 7, 2020
loicmathieu added a commit to loicmathieu/quarkus that referenced this issue Jan 17, 2020
fix: rename all this stuff




fix: improve test

- Use @MongoEntity
- Better SSE test

feat: optional support


chore: move to axle package


Merge reactive and blocking API into the same module


fix bug quarkusio#5885 for Axle


Remove the deleted reactive extension stage from the CI


Documentation guide
loicmathieu added a commit to loicmathieu/quarkus that referenced this issue Jan 20, 2020
fix: rename all this stuff




fix: improve test

- Use @MongoEntity
- Better SSE test

feat: optional support


chore: move to axle package


Merge reactive and blocking API into the same module


fix bug quarkusio#5885 for Axle


Remove the deleted reactive extension stage from the CI


Documentation guide
loicmathieu added a commit to loicmathieu/quarkus that referenced this issue Jan 20, 2020
fix: rename all this stuff




fix: improve test

- Use @MongoEntity
- Better SSE test

feat: optional support


chore: move to axle package


Merge reactive and blocking API into the same module


fix bug quarkusio#5885 for Axle


Remove the deleted reactive extension stage from the CI


Documentation guide
loicmathieu added a commit to loicmathieu/quarkus that referenced this issue Jan 27, 2020
fix: rename all this stuff




fix: improve test

- Use @MongoEntity
- Better SSE test

feat: optional support


chore: move to axle package


Merge reactive and blocking API into the same module


fix bug quarkusio#5885 for Axle


Remove the deleted reactive extension stage from the CI


Documentation guide
loicmathieu added a commit to loicmathieu/quarkus that referenced this issue Jan 27, 2020
fix: rename all this stuff




fix: improve test

- Use @MongoEntity
- Better SSE test

feat: optional support


chore: move to axle package


Merge reactive and blocking API into the same module


fix bug quarkusio#5885 for Axle


Remove the deleted reactive extension stage from the CI


Documentation guide
loicmathieu added a commit to loicmathieu/quarkus that referenced this issue Feb 3, 2020
fix: rename all this stuff




fix: improve test

- Use @MongoEntity
- Better SSE test

feat: optional support


chore: move to axle package


Merge reactive and blocking API into the same module


fix bug quarkusio#5885 for Axle


Remove the deleted reactive extension stage from the CI


Documentation guide
loicmathieu added a commit to loicmathieu/quarkus that referenced this issue Feb 4, 2020
fix: improve test

- Use @MongoEntity
- Better SSE test

feat: optional support


chore: move to axle package


Merge reactive and blocking API into the same module


fix bug quarkusio#5885 for Axle


Remove the deleted reactive extension stage from the CI


Documentation guide


Apply suggestions from code review

Co-Authored-By: Guillaume Smet <guillaume.smet@gmail.com>
gsmet added a commit to loicmathieu/quarkus that referenced this issue Feb 4, 2020
fix: improve test

- Use @MongoEntity
- Better SSE test

feat: optional support


chore: move to axle package


Merge reactive and blocking API into the same module


fix bug quarkusio#5885 for Axle


Remove the deleted reactive extension stage from the CI


Documentation guide


Apply suggestions from code review

Co-Authored-By: Guillaume Smet <guillaume.smet@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants