Quarkus Mongodb 在本机构建中更改流 NullPointerException
Posted
技术标签:
【中文标题】Quarkus Mongodb 在本机构建中更改流 NullPointerException【英文标题】:Quarkus Mongodb change stream NullPointerException in native build 【发布时间】:2021-08-12 21:50:51 【问题描述】:我正在构建一个 quarkus 应用程序,它将 mongodb 更改流功能与响应式客户端一起使用。
如果我从 Intellij 本地启动应用程序,一切正常,但是当我构建本机应用程序并在 docker 映像中运行它时,我收到此错误
2021-05-24 14:32:51,983 INFO [org.mon.dri.connection] (main) Opened connection [connectionIdlocalValue:13, serverValue:220678] to cluster0-shard-00-02.plt2x.mongodb.net:27017
2021-05-24 14:32:52,146 INFO [org.mon.dri.connection] (main) Closed connection [connectionIdlocalValue:13, serverValue:220678] to cluster0-shard-00-02.plt2x.mongodb.net:27017 because the pool has been closed.
2021-05-24 14:32:52,197 ERROR [io.qua.run.Application] (main) Failed to start application (with profile prod): java.lang.NullPointerException
at com.mongodb.client.model.changestream.ChangeStreamDocumentCodec.<init>(ChangeStreamDocumentCodec.java:45)
at com.mongodb.client.model.changestream.ChangeStreamDocument.createCodec(ChangeStreamDocument.java:296)
at com.mongodb.reactivestreams.client.internal.ChangeStreamPublisherImpl.<init>(ChangeStreamPublisherImpl.java:65)
at com.mongodb.reactivestreams.client.internal.MongoCollectionImpl.watch(MongoCollectionImpl.java:277)
at io.quarkus.mongodb.impl.ReactiveMongoCollectionImpl.watch(ReactiveMongoCollectionImpl.java:360)
at com.eventmanager.event.EventService.initOrderStream(EventService.java:89)
at com.eventmanager.event.EventService.init(EventService.java:46)
at com.eventmanager.event.EventService_Bean.create(EventService_Bean.zig:376)
at com.eventmanager.event.EventService_Bean.create(EventService_Bean.zig:392)
at io.quarkus.arc.impl.AbstractSharedContext.createInstanceHandle(AbstractSharedContext.java:96)
at io.quarkus.arc.impl.AbstractSharedContext.access$000(AbstractSharedContext.java:14)
at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:29)
at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:26)
at io.quarkus.arc.impl.LazyValue.get(LazyValue.java:26)
at io.quarkus.arc.impl.ComputingCache.computeIfAbsent(ComputingCache.java:69)
at io.quarkus.arc.impl.AbstractSharedContext.get(AbstractSharedContext.java:26)
at io.quarkus.arc.impl.ClientProxies.getApplicationScopedDelegate(ClientProxies.java:17)
at com.eventmanager.event.EventService_ClientProxy.arc$delegate(EventService_ClientProxy.zig:67)
at com.eventmanager.event.EventService_ClientProxy.arc_contextualInstance(EventService_ClientProxy.zig:82)
at com.eventmanager.event.EventService_Observer_Synthetic_d70cd75bf32ab6598217b9a64a8473d65e248c05.notify(EventService_Observer_Synthetic_d70cd75bf32ab6598217b9a64a8473d65e248c05.zig:94)
at io.quarkus.arc.impl.EventImpl$Notifier.notifyObservers(EventImpl.java:283)
at io.quarkus.arc.impl.EventImpl$Notifier.notify(EventImpl.java:268)
at io.quarkus.arc.impl.EventImpl.fire(EventImpl.java:70)
at io.quarkus.arc.runtime.ArcRecorder.fireLifecycleEvent(ArcRecorder.java:128)
at io.quarkus.arc.runtime.ArcRecorder.handleLifecycleEvents(ArcRecorder.java:97)
at io.quarkus.deployment.steps.LifecycleEventsBuildStep$startupEvent1144526294.deploy_0(LifecycleEventsBuildStep$startupEvent1144526294.zig:87)
at io.quarkus.deployment.steps.LifecycleEventsBuildStep$startupEvent1144526294.deploy(LifecycleEventsBuildStep$startupEvent1144526294.zig:40)
at io.quarkus.runner.ApplicationImpl.doStart(ApplicationImpl.zig:609)
at io.quarkus.runtime.Application.start(Application.java:90)
at io.quarkus.runtime.ApplicationLifecycleManager.run(ApplicationLifecycleManager.java:100)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:66)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:42)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:119)
at io.quarkus.runner.GeneratedMain.main(GeneratedMain.zig:29)
我使用这个命令来构建原生应用,因为我需要在 windows 上本地构建它并在 heroku 上 delpoy:
mvn package -Pnative -Dquarkus.native.container-build=true -Dquarkus.native.builder-image=quay.io/quarkus/ubi-quarkus-native-image:21.0.0-java11
这是我初始化更改流并在集合上启动监视的类和方法
@Inject
ReactiveMongoClient mongoClient;
private void initOrderStream()
ReactiveMongoDatabase database = mongoClient.getDatabase("database");
ReactiveMongoCollection<Order> dataCollection = database.getCollection("order", Order.class);
ChangeStreamOptions options = new ChangeStreamOptions().fullDocument(FullDocument.UPDATE_LOOKUP);
List<Bson> pipeline = Collections.singletonList(
Aggregates.match(
Filters.and(
Filters.eq("operationType", "update"),
Filters.eq("updateDescription.updatedFields.orderStatus", "PENDING")
)
)
);
Multi<ChangeStreamDocument<Order>> publisher = dataCollection.watch(pipeline, Order.class, options);
publisher.subscribe().with(eventListener.getOrderListener());
这是监听方法
public Consumer<ChangeStreamDocument<Order>> getOrderListener()
return message ->
Order order = message.getFullDocument();
saveEvent(order);
;
不明白错误,查看了空指针异常所在的mongo客户端库的类的源码,发现错误在构造函数中
ChangeStreamDocumentCodec(final Class<TResult> fullDocumentClass, final CodecRegistry codecRegistry)
ClassModelBuilder<ChangeStreamDocument> classModelBuilder = ClassModel.builder(ChangeStreamDocument.class);
((PropertyModelBuilder<TResult>) classModelBuilder.getProperty("fullDocument")).codec(codecRegistry.get(fullDocumentClass));
((PropertyModelBuilder<OperationType>) classModelBuilder.getProperty("operationType")).codec(OPERATION_TYPE_CODEC);
ClassModel<ChangeStreamDocument> changeStreamDocumentClassModel = classModelBuilder.build();
PojoCodecProvider provider = PojoCodecProvider.builder()
.register(MongoNamespace.class)
.register(UpdateDescription.class)
.register(TruncatedArray.class)
.register(changeStreamDocumentClassModel)
.build();
CodecRegistry registry = fromRegistries(fromProviders(provider, new BsonValueCodecProvider()), codecRegistry);
this.codec = (Codec<ChangeStreamDocument<TResult>>) (Codec<? extends ChangeStreamDocument>) registry.get(ChangeStreamDocument.class);
空指针所在的行是这一行:
((PropertyModelBuilder<TResult>) classModelBuilder.getProperty("fullDocument")).codec(codecRegistry.get(fullDocumentClass));
所以我尝试删除 fullDocument 选项,但错误仍然存在。
只有当我在 docker 中运行应用程序时才会导致此错误的任何想法? 谢谢
【问题讨论】:
【参考方案1】:这刚刚修复 here 并将在 1.13.5
和 2.0.0.Alpha4
中提供
【讨论】:
非常感谢,新版本一切正常。我现在有一个使用相同代码和场景的新问题,我想使用 ChangeStreamDocument 类的方法 message.getResumeToken() 将 resumeToken 保存在侦听器中,但它始终为空。你能帮助我吗?我应该打开一个新问题吗? 我开了一个新问题***.com/questions/67898783/…。以上是关于Quarkus Mongodb 在本机构建中更改流 NullPointerException的主要内容,如果未能解决你的问题,请参考以下文章
在本机编译期间,如何在 Quarkus maven 插件中将参数添加到 GraalVM?
如何通过 REST API 微服务(使用 Express 构建)将 MongoDB 更改流与节点 js 一起使用
使用 Testcontainers + Quarkus + MongoDB 进行集成测试