javax.json 和 jakarta.json 在同一应用程序中:org.glassfish.json.JsonProviderImpl 无法转换为 jakarta.json.spi.JsonProvider

javax.json and jakarta.json in the same application: org.glassfish.json.JsonProviderImpl cannot be cast to jakarta.json.spi.JsonProvider

我正在开发面向 Java EE 8 应用程序服务器 (JBoss/Wildfly) 的应用程序。

但是,其中一个依赖项 (elasticsearch api) 已经在使用 jakarta.json.* classes,这会在运行时导致 ClassCastException:

java.lang.ClassCastException: org.glassfish.json.JsonProviderImpl cannot be cast to jakarta.json.spi.JsonProvider

那是因为我的class路径(org.classfish:javax.json:1.1.4)中的org.classfish.json.JsonProviderImpl还在使用javax.json classes.

但是,由于 org.glassfish:jakarta.jsonorg.classfish:javax.json 定义相同的 class org.classfish.json.JsonProviderImpl(一个使用 javax.json.* classes,另一个使用 jakarta.json.* classes...),我无法简单地包含两个 Maven 工件。

JsonProviderImpl 的实现(在两个工件中!)默认情况下基本上returns以下内容:

return Class.forName("org.glassfish.json.JsonProviderImpl");

org.glassfish:jakarta.jsonorg.classfish:javax.json 都在 class 路径上时,这将导致任何将从其他包获取 JsonProviderImpl 的实现出现问题.

我该怎么做才能解决这个问题?

一种解决方法似乎是使用 Maven 阴影插件基本上将“新”org.glassfish:jakarta.json 中的包 org.glassfish.json“重命名”为 jakarta.org.glassfish.json:

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-shade-plugin</artifactId>
      <executions>
        <execution>
          <phase>package</phase>
          <goals>
            <goal>shade</goal>
          </goals>
        </execution>
      </executions>
      <configuration>
        <filters>
          <filter>
            <artifact>org.glassfish:jakarta.json</artifact>
            <includes>
              <include>org/glassfish/json/**</include>
            </includes>
          </filter>
        </filters>
        <artifactSet>
          <includes>
            <include>org.glassfish:jakarta.json</include>
          </includes>
        </artifactSet>
        <relocations>
          <relocation>
            <pattern>org.glassfish.json</pattern>
            <shadedPattern>jakarta.org.glassfish.json</shadedPattern>
          </relocation>
        </relocations>
      </configuration>
    </plugin>
  </plugins>
</build>

然后,可以创建包含以下内容的文件src/main/resources/META-INF/services/jakarta.json.spi.JsonProvider

jakarta.org.glassfish.json.JsonProviderImpl

这将告诉 jakarta.json.spi.JsonProvider 的实现使用 JsonProviderImpl 的阴影版本(来自 org.glassfish:jakarta.json 工件 - 它使用 jakarta.json.* 类) 而不是 JsonProviderImpl(与 org.glassfish:javax.json 中的名称相同)。

供参考:This has been fixed by the Elastic team:他们已从 Glassfish 实现切换

api("org.glassfish", "jakarta.json", "2.0.1")

Eclipse Parsson:

api("jakarta.json:jakarta.json-api:2.0.1")
api("org.eclipse.parsson:parsson:1.0.0")