Quarkus: @Inject PgPool NullPointerException in Reactive Router and Scheduled

Created on 27 Oct 2019  ·  13Comments  ·  Source: quarkusio/quarkus

Describe the bug
Will occur when Reactive Router and Scheduler exists at the same project.

Expected behavior
Pgpool should be successfully inject

Actual behavior
PgPool NullPointerException

To Reproduce

@ApplicationScoped
public class ExampleScheduler {

    @Inject
    PgPool pgPool; // <-- NullPointerException

    @Scheduled(every = "5s")
    public void foo() {
        RowSet<Row> join =
                pgPool.query("insert into test (def) values ('a');").toCompletableFuture().join();
    }
}

@ApplicationScoped
public class ExampleResource2 {
    @Inject
    PgPool pgPool;  // <-- NullPointerException

    @Route(path = "/q", methods = HttpMethod.GET)
    public void q(RoutingContext ctx) {
        pgPool.query("insert into test (def) values ('a');").whenCompleteAsync(
                (rows, throwable) -> {
                    if (throwable == null) {
                        ctx.response().setStatusCode(200);
                    } else {
                        ctx.response().setStatusCode(500);
                    }
                }
        );
    }
}

Log
ExampleScheduler:

2019-10-27 16:22:46,026 ERROR [org.qua.cor.ErrorLogger] (DefaultQuartzScheduler_Worker-2) Job (io.quarkus.scheduler.Scheduler.1_io.fandi.ExampleScheduler_ScheduledInvoker_foo_857c24ac2465d8fccbbb4da185456525ff0c404a threw an exception.: org.quartz.SchedulerException: Job threw an unhandled exception. [See nested exception: java.lang.NullPointerException]
        at org.quartz.core.JobRunShell.run(JobRunShell.java:213)
        at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573)
Caused by: java.lang.NullPointerException
        at io.fandi.ExampleScheduler.foo(ExampleScheduler.java:20)
        at io.fandi.ExampleScheduler_Subclass.foo$$superaccessor1(ExampleScheduler_Subclass.zig:236)
        at io.fandi.ExampleScheduler_Subclass$$function$$1.apply(ExampleScheduler_Subclass$$function$$1.zig:47)
        at io.quarkus.arc.interceptors.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:55)
        at io.quarkus.arc.ActivateRequestContextInterceptor.aroundInvoke(ActivateRequestContextInterceptor.java:22)
        at io.quarkus.arc.ActivateRequestContextInterceptor_Bean.intercept(ActivateRequestContextInterceptor_Bean.zig:94)
        at io.quarkus.arc.interceptors.InterceptorInvocation.invoke(InterceptorInvocation.java:41)
        at io.quarkus.arc.interceptors.AroundInvokeInvocationContext.perform(AroundInvokeInvocationContext.java:42)
        at io.quarkus.arc.interceptors.InvocationContexts.performAroundInvoke(InvocationContexts.java:32)
        at io.fandi.ExampleScheduler_Subclass.foo(ExampleScheduler_Subclass.zig:194)
        at io.fandi.ExampleScheduler_ClientProxy.foo(ExampleScheduler_ClientProxy.zig:176)
        at io.fandi.ExampleScheduler_ScheduledInvoker_foo_857c24ac2465d8fccbbb4da185456525ff0c404a.invoke(ExampleScheduler_ScheduledInvoker_foo_857c24ac2465d8fccbbb4da185456525ff0c404a.zig:45)
        at io.quarkus.scheduler.runtime.QuartzScheduler$InvokerJob.execute(QuartzScheduler.java:252)
        at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
        ... 1 more

ExampleResource2:

java.lang.NullPointerException
    at io.fandi.ExampleResource2.q(ExampleResource2.java:18)
    at io.fandi.ExampleResource2_ClientProxy.q(ExampleResource2_ClientProxy.zig:174)
    at io.fandi.ExampleResource2_RouteHandler_q_c3af2559b576a94e7bb5fbf45d499d016a0d48d1.handle(ExampleResource2_RouteHandler_q_c3af2559b576a94e7bb5fbf45d499d016a0d48d1.zig:47)
    at io.quarkus.vertx.http.runtime.VertxHttpRecorder$ResumeHandler.handle(VertxHttpRecorder.java:572)
    at io.quarkus.vertx.http.runtime.VertxHttpRecorder$ResumeHandler.handle(VertxHttpRecorder.java:559)
    at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:986)
    at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:95)
    at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:130)
    at io.vertx.ext.web.handler.impl.BodyHandlerImpl$BHandler.doEnd(BodyHandlerImpl.java:296)
    at io.vertx.ext.web.handler.impl.BodyHandlerImpl$BHandler.end(BodyHandlerImpl.java:276)
    at io.vertx.ext.web.handler.impl.BodyHandlerImpl.lambda$handle$0(BodyHandlerImpl.java:87)
    at io.vertx.core.http.impl.HttpServerRequestImpl.onEnd(HttpServerRequestImpl.java:530)
    at io.vertx.core.http.impl.HttpServerRequestImpl.lambda$pendingQueue$1(HttpServerRequestImpl.java:118)
    at io.vertx.core.streams.impl.InboundBuffer.handleEvent(InboundBuffer.java:237)
    at io.vertx.core.streams.impl.InboundBuffer.drain(InboundBuffer.java:224)
    at io.vertx.core.streams.impl.InboundBuffer.lambda$fetch$0(InboundBuffer.java:277)
    at io.vertx.core.impl.ContextImpl.executeTask(ContextImpl.java:369)
    at io.vertx.core.impl.EventLoopContext.lambda$executeAsync$0(EventLoopContext.java:38)
    at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163)
    at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:416)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:515)
    at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:918)
    at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    at java.lang.Thread.run(Thread.java:748)
kinbug triagout-of-date

Most helpful comment

Thanks for the reproducers. I'll look into it.

Le jeu. 19 déc. 2019 à 18:42, TomasHofman notifications@github.com a
écrit :

I can also reproduce this. Happens with following dependencies:

<dependency>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-vertx</artifactId>
</dependency>
<dependency>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-vertx-web</artifactId>
</dependency>
<dependency>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-reactive-pg-client</artifactId>
</dependency>
<dependency>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-jsonb</artifactId>
</dependency>

The injection starts to work when I change quarkus-jsonb dependency to
quarkus-resteasy-jsonb.

Code is just simple application-scoped bean:

public class PullRequestLoggerRoutes {

@Inject
PgPool client;

@PostConstruct
void config() {
    client.query("DROP TABLE IF EXISTS pull_requests");
}

}

Quarkus version 1.0.1.Final.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/quarkusio/quarkus/issues/4900?email_source=notifications&email_token=AALOLNS7UTWZUPUZ4U2MTGTQZOXAJA5CNFSM4JFQT44KYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEHKL3AI#issuecomment-567590273,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AALOLNV7BBL6MA72E3M3GD3QZOXAJANCNFSM4JFQT44A
.

All 13 comments

@tsegismont can you have a look?

I've tried to reproduce it but failed so far.

In my application.properties, I have:

quarkus.datasource.url=vertx-reactive:postgresql://localhost:5432/rest-crud
quarkus.datasource.username=restcrud
quarkus.datasource.password=restcrud

I've added the following dependencies:

    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-resteasy-jsonb</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-vertx-web</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-scheduler</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-reactive-pg-client</artifactId>
    </dependency>

Can you give me more details?

dependenies not include quarkus-resteasy-jsonb

<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-vertx-web</artifactId>
</dependency>
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-scheduler</artifactId>
</dependency>
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-reactive-pg-client</artifactId>
</dependency>

Could you try again ?

In some cases,I can reproduce the bug ,but it's random.
It's easier to reproduce this error in dev mode:
mvn compile quarkus:dev
When an error occurs I modified the code and call a restful route to cause hot replace,then it works.( please see the log below). I guess it may be related to the initialization order of some instances.

2019-10-29 09:51:20,009 INFO [io.quarkus] (main) Installed features: [cdi, reactive-mysql-client, resteasy, resteasy-jsonb, scheduler, vertx, vertx-web] ===Schedule error! ===Schedule error! ===Schedule error! ===Schedule error! ===Schedule error! ===Schedule error! ===Schedule error! ===Schedule error! 2019-10-29 09:52:01,148 INFO [io.qua.dev] (vert.x-worker-thread-0) Changed source files detected, recompiling [C:\temp\code-with-quarkus\src\main\java\org\acme\ReactiveStudentRoutes.java] 2019-10-29 09:52:01,939 INFO [io.quarkus] (vert.x-worker-thread-0) Quarkus stopped in 0.021s 2019-10-29 09:52:01,941 INFO [io.qua.dep.QuarkusAugmentor] (vert.x-worker-thread-0) Beginning quarkus augmentation 2019-10-29 09:52:02,090 INFO [io.qua.resteasy] (build-13) Resteasy running without servlet container. 2019-10-29 09:52:02,090 INFO [io.qua.resteasy] (build-13) - Add quarkus-undertow to run Resteasy within a servlet container 2019-10-29 09:52:02,115 INFO [io.qua.dep.QuarkusAugmentor] (vert.x-worker-thread-0) Quarkus augmentation completed in 174ms 2019-10-29 09:52:02,282 INFO [io.quarkus] (vert.x-worker-thread-0) Quarkus 0.26.1 started in 0.343s. Listening on: http://0.0.0.0:8888 2019-10-29 09:52:02,283 INFO [io.quarkus] (vert.x-worker-thread-0) Profile dev activated. Live Coding activated. 2019-10-29 09:52:02,284 INFO [io.quarkus] (vert.x-worker-thread-0) Installed features: [cdi, reactive-mysql-client, resteasy, resteasy-jsonb, scheduler, vertx, vertx-web] 2019-10-29 09:52:02,284 INFO [io.qua.dev] (vert.x-worker-thread-0) Hot replace total time: 1.138s ===Schedule OK:677 ===Schedule OK:677 ===Schedule OK:677 ===Schedule OK:677

Here is my test code:
code-with-quarkus.zip

@fandiluo
I try my code with not include quarkus-resteasy-jsonb dependenies,random occurrence of fault.

I provide my code. Please try it!
code

I have the same issue trying to create a simple MQTT -> Postgres flow.
PgPool dependency does not get injected.
Does the PgPool entity not get created on time?

Code:

@ApplicationScoped
public class Application extends RouteBuilder {

    @ConfigProperty(name = "mqtt.topic")
    public String mqttTopic;

    @ConfigProperty(name = "mqtt.broker.url")
    public String mqttBrokerUrl;

    @ConfigProperty(name = "app.logger.name")
    public String loggerName;

    @ConfigProperty(name = "app.batch.size")
    public int batchSize;

    @ConfigProperty(name = "app.batch.timeout")
    public int batchTimeout;

    @Inject
    public PgPool db;

    @PostConstruct
    public void init() {
        if (db == null) {
            throw new IllegalArgumentException("db property not initialized");
        }
    }

    @Override
    public void configure() throws Exception {

        System.out.println("Batch size:"+batchSize);
        System.out.println("Batch timeout:" + batchTimeout);

        from("paho:" + mqttTopic + "?brokerUrl=" + mqttBrokerUrl)
                .process()
                    .exchange(extractTopicMessage)
                .aggregate(constant(true), AggregationStrategies.groupedBody())
                    .completionSize(batchSize)
                    .completionTimeout(batchTimeout)
                    .process()
                        .body(List.class, list -> {
                            System.out.println("Received: " + list.size());
                            saveEvents(list);
                        });
    }

    private Consumer<Exchange> extractTopicMessage = exchange -> {
        System.out.println("Processing...");
        Message msg = exchange.getIn();
        String topic = (String) msg.getHeader(PahoConstants.MQTT_TOPIC);
        byte[] payload = msg.getBody(byte[].class);

        msg.setBody(new TopicEvents(topic, payload));
    };

    private void saveEvents(List<TopicEvents> events) {

        List<Tuple> tuples = events.stream()
                .map(event -> Tuple.of(event.topic, Buffer.buffer(event.payload), event.getJson()))
                .collect(Collectors.toList());

        db.preparedBatch(
                "INSERT INTO event_log (topic, data, json) VALUES ($1, $2, $3) RETURNING (id)",
                tuples,
                res -> {
                    if (res.succeeded()) {
                        System.out.println("Inserted events" + res.result().rowCount());
                    } else {
                        System.out.println("Insert failed:" + res.cause());
                    }
                }
        );
    }

    private class TopicEvents {

        private final String topic;
        private final byte[] payload;

        public TopicEvents(String topic, byte[] payload) {
            this.topic = topic;
            this.payload = payload;
        }

        public String getTopic() {
            return topic;
        }

        public byte[] getPayload() {
            return payload;
        }

        public String getJson() {
            return null;
        }
    }
}

Config:

quarkus.log.level=DEBUG

quarkus.http.port=9100

mqtt.broker.url=tcp://localhost:1883
mqtt.topic=application/#

app.logger.name=eventlog
# timeout in millis
app.batch.timeout=2000
app.batch.size=100
app.schema.create=true

# Database
quarkus.datasource.url=vertx-reactive:postgresql://localhost:5432/eventlog
quarkus.datasource.username=eventlog
quarkys.datasource.password=eventlog

My dependencies are

  <dependencies>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-junit5</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.apache.camel.quarkus</groupId>
      <artifactId>camel-quarkus-log</artifactId>
    </dependency>
    <dependency>
      <groupId>org.apache.camel.quarkus</groupId>
      <artifactId>camel-quarkus-microprofile-metrics</artifactId>
    </dependency>
    <dependency>
      <groupId>org.apache.camel.quarkus</groupId>
      <artifactId>camel-quarkus-paho</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-reactive-pg-client</artifactId>
    </dependency>
  </dependencies>

I can also reproduce this. Happens with following dependencies:

    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-vertx</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-vertx-web</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-reactive-pg-client</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-jsonb</artifactId>
    </dependency>

The injection starts to work when I change quarkus-jsonb dependency to quarkus-resteasy-jsonb.

Code is just simple application-scoped bean:

@ApplicationScoped
public class PullRequestLoggerRoutes {

    @Inject
    io.vertx.axle.pgclient.PgPool client;

    @PostConstruct
    void config() {
        client.query("DROP TABLE IF EXISTS pull_requests");
    }
}

Quarkus version 1.0.1.Final.

Thanks for the reproducers. I'll look into it.

Le jeu. 19 déc. 2019 à 18:42, TomasHofman notifications@github.com a
écrit :

I can also reproduce this. Happens with following dependencies:

<dependency>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-vertx</artifactId>
</dependency>
<dependency>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-vertx-web</artifactId>
</dependency>
<dependency>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-reactive-pg-client</artifactId>
</dependency>
<dependency>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-jsonb</artifactId>
</dependency>

The injection starts to work when I change quarkus-jsonb dependency to
quarkus-resteasy-jsonb.

Code is just simple application-scoped bean:

public class PullRequestLoggerRoutes {

@Inject
PgPool client;

@PostConstruct
void config() {
    client.query("DROP TABLE IF EXISTS pull_requests");
}

}

Quarkus version 1.0.1.Final.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/quarkusio/quarkus/issues/4900?email_source=notifications&email_token=AALOLNS7UTWZUPUZ4U2MTGTQZOXAJA5CNFSM4JFQT44KYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEHKL3AI#issuecomment-567590273,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AALOLNV7BBL6MA72E3M3GD3QZOXAJANCNFSM4JFQT44A
.

@yuhaibohotmail I downloaded your code but can't reproduce (even after removing resteasy-jackson-jsonb dependency)

@fandiluo I tried to download your code but the link has expired.

Can one of you please share on GitHub a reproducer project? Without commented code and a list of reproduction steps, expectations/failures? Thank you

I just tried different versions.
Found that 1.1.0 does not happen.
But 1.0.1 and 1.0.0 exist this bug

@tsegismont Try it. Thanks!
https://github.com/fandiluo/reproduce

@fandiluo if it's fixed on 1.1.0 I would recommend to upgrade to this version.

@cescoffier there will be no other 1.0.x release correct?

Yes, there are no 1.0.x release planned. It's now 1.1.x and 1.2.x

Was this page helpful?
0 / 5 - 0 ratings