Matthias
Matthias

Reputation: 12269

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

I am developing an application targeting a Java EE 8 application server (JBoss/Wildfly).

However, one of the dependencies (elasticsearch api) is already using jakarta.json.* classes which results in a ClassCastException at runtime:

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

That is because the org.classfish.json.JsonProviderImpl in my classpath (org.classfish:javax.json:1.1.4) is still using javax.json classes.

However, as both org.glassfish:jakarta.json and org.classfish:javax.json define the same class org.classfish.json.JsonProviderImpl (one using the javax.json.* classes and one using the jakarta.json.* classes...), I am unable to simply include both maven artifacts.

The implementation of JsonProviderImpl (in both artifacts!) basically returns the following by default:

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

When both org.glassfish:jakarta.json and org.classfish:javax.json are on the classpath, this will cause issue for any of the implementations which will get the JsonProviderImpl from the other package.

What can I do to resolve this?

Upvotes: 4

Views: 5628

Answers (2)

Matthias
Matthias

Reputation: 12269

For reference: This has been fixed by the Elastic team: They have switched from the Glassfish implementation

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

to Eclipse Parsson:

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

Upvotes: 3

Matthias
Matthias

Reputation: 12269

One workaround seems to be to use the maven shade plugin to basically "rename" the package org.glassfish.json in the "new" org.glassfish:jakarta.json to 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>

Then, one can create the file src/main/resources/META-INF/services/jakarta.json.spi.JsonProvider with the following content:

jakarta.org.glassfish.json.JsonProviderImpl

This will tell the implementation of jakarta.json.spi.JsonProvider to use the shaded version of the JsonProviderImpl (from the org.glassfish:jakarta.json artifact - which uses the jakarta.json.* classes) instead of the JsonProviderImpl (with the same name from org.glassfish:javax.json).

Upvotes: 1

Related Questions