Search code examples
quarkusquarkus-panache

PanacheReactive on Scheduled IllegalStateException: Session/EntityManager


I am trying to execute a stupid query from @Scheduled method using an ApplicationScoped PanacheRepository

@ApplicationScoped
public class MyRepo implements PanacheRepository<MyEntity> {

then I have the following

@Inject
MyRepo repo;

@Scheduled(every = "${cache.refreshRate}", delayed = "20s")
public Uni<Void> scheduleRefresh() {
    return repo.listAll().replaceWithVoid();
}

And I am getting the following exception

(vert.x-eventloop-thread-0) Error occurred while executing task for trigger IntervalTrigger [id=1_org.xx.xxxxx.infrastructure.importer.Importer_ScheduledInvoker_scheduleRefresh_520a27e95be32ee7cfd3163651929119f1ff17fe, interval=300000]: java.lang.IllegalStateException: Session/EntityManager is closed at org.hibernate.internal.AbstractSharedSessionContract.checkOpen(AbstractSharedSessionContract.java:407) at org.hibernate.engine.spi.SharedSessionContractImplementor.checkOpen(SharedSessionContractImplementor.java:148) at org.hibernate.reactive.session.impl.ReactiveSessionImpl.checkOpen(ReactiveSessionImpl.java:1558) at org.hibernate.internal.AbstractSharedSessionContract.checkOpenOrWaitingForAutoClose(AbstractSharedSessionContract.java:413) at

EDIT

The application runs correctly locally (postgres on docker) but fails on the cloud (gcp + cloudsql)


Solution

  • I think this is a bug in Quarkus.

    This workaround should work:

    @ApplicationScoped
    public class SchedulerBean {
    
        @Inject
        Mutiny.SessionFactory factory;
    
        @Scheduled(every = "${cache.refreshRate}", delayed = "20s")
        Uni<Void> scheduleRefresh() {
            return factory.withSession( SchedulerBean::refresh );
        }
    
        private static Uni<Void> refresh(Mutiny.Session s) {
            return s.createQuery( "from MyEntity" ).getResultList().replaceWithVoid();
        }
    }
    

    You can rewrite it with criteria, if you prefer something programmatic:

        private static Uni<Void> refresh(Mutiny.Session s) {
                CriteriaQuery<MyEntity> query = factory
                        .getCriteriaBuilder()
                        .createQuery( MyEntity.class );
                query.from( MyEntity.class );
                return s.createQuery( query ).getResultList().replaceWithVoid();
        }