You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Quarkus Native(GraalVM)下ElasticSearch Java客户端JsonProviderImpl缺失异常

Quarkus Native模式下Elasticsearch Java客户端找不到Parsson JsonProviderImpl的问题

环境

  • Quarkus 2.16.6.Final
  • Elasticsearch 8.7
  • GraalVM Native镜像模式

核心代码

UpdateByQuery实现

try (Reader query = new StringReader(/*my json query String*/)) {
  var request = UpdateByQueryRequest.of(fn -> fn.index(index).withJson(query));

  return client.updateByQuery(request);
} catch (IOException e) {
  throw new RuntimeException(e);
}

Elasticsearch客户端初始化

var credsProv = new BasicCredentialsProvider();

credsProv.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));

var restClient = RestClient.builder(HttpHost.create(host)).setHttpClientConfigCallback(
    hc -> hc.disableAuthCaching().setDefaultCredentialsProvider(credsProv)).build();

var transport = new RestClientTransport(restClient, new JacksonJsonpMapper());

var client = new ElasticsearchAsyncClient(transport);

异常信息

Caused by: jakarta.json.JsonException: Provider org.eclipse.parsson.JsonProviderImpl not found
at jakarta.json.spi.JsonProvider.newInstance(JsonProvider.java:160)
at jakarta.json.spi.JsonProvider.provider(JsonProvider.java:144)
at co.elastic.clients.json.JsonpUtils.findProvider(JsonpUtils.java:65)
... 54 more
Caused by: java.lang.ClassNotFoundException: org.eclipse.parsson.JsonProviderImpl
    at java.base@17.0.7/java.lang.Class.forName(DynamicHub.java:1132)
    at java.base@17.0.7/java.lang.Class.forName(DynamicHub.java:1105)
    at jakarta.json.spi.JsonProvider.newInstance(JsonProvider.java:157)

Maven依赖配置

<dependency>
    <groupId>co.elastic.clients</groupId>
    <artifactId>elasticsearch-java</artifactId>
    <version>8.7.0</version>
    <exclusions>
        <exclusion>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
        </exclusion>
        <exclusion>
            <groupId>jakarta.json</groupId>
            <artifactId>jakarta.json-api</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.eclipse.parsson</groupId>
            <artifactId>parsson</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>jakarta.json</groupId>
    <artifactId>jakarta.json-api</artifactId>
    <version>2.1.1</version>
    <scope>compile</scope>
</dependency>
<dependency>
    <groupId>org.eclipse.parsson</groupId>
    <artifactId>parsson</artifactId>
    <version>1.1.1</version>
    <scope>compile</scope>
</dependency>

问题

代码在常规JVM模式下运行正常,但GraalVM Native模式执行时抛出上述异常,已按要求添加依赖但问题未解决。


解决方案

1. 显式注册SPI实现

GraalVM原生镜像不会自动扫描SPI配置,需手动注册:

  • 在项目src/main/resources/META-INF/services目录下创建jakarta.json.spi.JsonProvider文件
  • 文件内容仅一行:org.eclipse.parsson.JsonProviderImpl

2. 使用Quarkus官方Elasticsearch扩展(推荐)

Quarkus的扩展会自动处理原生镜像兼容性,无需手动配置SPI和反射:

  • 添加依赖:
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-elasticsearch-rest-client</artifactId>
</dependency>
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-elasticsearch-java-client</artifactId>
</dependency>
  • 注入客户端替代手动初始化:
@Inject
ElasticsearchAsyncClient client;

3. 手动配置GraalVM反射元数据

若坚持手动初始化客户端,需添加反射配置文件:

  • 在src/main/resources/META-INF/native-image目录下创建reflect-config.json
  • 内容如下:
[
  {
    "name": "org.eclipse.parsson.JsonProviderImpl",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true
  }
]

原因分析

常规JVM在运行时通过SPI机制自动发现META-INF/services中的配置,加载JsonProvider实现;而GraalVM原生镜像在构建阶段就完成了类的静态打包,不会在运行时动态扫描SPI,因此必须提前告知需要包含这些类。


内容的提问来源于stack exchange,提问作者Abhinab Kanrar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 06:25:01