How can I fix random Kotlin exceptions when using the Java SDK/API?
Symptom: you receive random exceptions relating to Kotlin, or other exceptions similar to:
|
|
This may be caused by transitive dependency errors. This FAQ will help you to resolve such errors.
General information
When working with the Java SDK/API, there may be some conflicts with transitive dependencies. To resolve these conflicts, you must first know all the dependencies required by sdk-java
, and their versions.
This information is available at https://git.itextsupport.com/projects/DITO/repos/sdk/browse/sdk-java/src/main/resources/NOTICE.txt.
Guarantee
We can only guarantee correct operation of the iText DITO Java SDK/API when using specific versions of transitive dependencies (i.e., the versions that are specified in the NOTICE.txt file). So let's say you have the sdk-java
dependency in your project:
<dependency>
<groupId>com.itextpdf.dito</groupId>
<artifactId>sdk-java</artifactId>
<version>${sdk.java.version}</version>
</dependency>
that has the following dependency:
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-a</artifactId>
<version>${artifact.a.version}</version>
</dependency>
In this case, if your project contains the same dependency but with a different version, then there is a conflict. If Maven has resolved this version conflict in favor of a version that doesn't come from sdk-java
, then there is a chance that either some functionality in sdk-java
will not work as expected, or some exceptions will be thrown.
Example of resolving conflicts with transitive dependencies
Suppose there is such a case when Maven decided to use a transitive dependency not from sdk-java
but from some other dependency. As a concrete example, you can look at the following Spring Boot pom.xml
file:
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.9.RELEASE</version>
</parent>
<groupId>com.example</groupId>
<artifactId>demo-1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo-1</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<repositories>
<repository>
<id>dito</id>
<name>DITO Repository</name>
<url>https://repo.itextsupport.com/dito</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.itextpdf.dito</groupId>
<artifactId>sdk-java</artifactId>
<version>2.0.5</version>
</dependency>
</dependencies>
</project>
Here you can see that the sdk-java
dependency with version 2.0.5
is used:
<dependency>
<groupId>com.itextpdf.dito</groupId>
<artifactId>sdk-java</artifactId>
<version>2.0.5</version>
</dependency>
Note: the problem is reproducible on sdk-java versions 1.4.4 and higher.
When such a pom.xml
is used, it may be the case that some methods (e.g. convertTemplateFromPackage
in PdfProducer
) will throw some exceptions (in the case of convertTemplateFromPackage
it would be java.lang.NoClassDefFoundError:kotlin/KotlinNothingValueException).
To fix this the first thing you should do is to investigate the project dependency tree as well as information about selected versions
mvn dependency:tree -Dverbose=true
and make sure that the versions of project dependencies that are used in sdk-java
match the versions in the NOTICE.txt file. In our particular case, the project uses the org.jetbrains.kotlin:kotlin-stdlib:1.3.72
dependency. The version 1.3.72
does not match the version in NOTICE.txt, which in turn leads to the exception described above. So, to fix this, you have several options:
1 The first one is adding the desired transitive dependency version as a direct dependency. You can do this in the following way:
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>1.4.30</version>
</dependency>
In this case org.jetbrains.kotlin:kotlin-stdlib:1.4.30
will be used according to the tree depth. The resulting pom.xml
will look like this:
pom.xml with correct version of org.jetbrains.kotlin:kotlin-stdlib dependency
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.9.RELEASE</version>
</parent>
<groupId>com.example</groupId>
<artifactId>demo-1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo-1</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<repositories>
<repository>
<id>dito</id>
<name>DITO Repository</name>
<url>https://repo.itextsupport.com/dito</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>1.4.30</version>
</dependency>
<dependency>
<groupId>com.itextpdf.dito</groupId>
<artifactId>sdk-java</artifactId>
<version>2.0.5</version>
</dependency>
</dependencies>
</project>
2 The second one is by using the dependencyManagement section (this section helps Maven to determine the version to select for specified dependencies):
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>1.4.30</version>
</dependency>
</dependencies>
</dependencyManagement>
pom.xml with dependencyManagement section
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.9.RELEASE</version>
</parent>
<groupId>com.example</groupId>
<artifactId>demo-1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo-1</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<repositories>
<repository>
<id>dito</id>
<name>DITO Repository</name>
<url>https://repo.itextsupport.com/dito</url>
</repository>
</repositories>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>1.4.30</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.itextpdf.dito</groupId>
<artifactId>sdk-java</artifactId>
<version>2.0.5</version>
</dependency>
</dependencies>
</project>
3 Moreover in some cases you can use the exclusions section to exclude a transitive dependency and avoid any conflict. avoid any conflicts
Important note: we recommend you explicitly define the following dependencies as they usually cause conflicts:
org.jetbrains.kotlin:kotlin-reflect
org.jetbrains.kotlin:kotlin-stdlib-common
org.jetbrains.kotlin:kotlin-stdlib-jdk7
org.jetbrains.kotlin:kotlin-stdlib-jdk8
org.jetbrains.kotlin:kotlin-stdlib
org.jetbrains.kotlinx:kotlinx-datetime-jvm
org.jetbrains.kotlinx:kotlinx-html-jvm
org.jetbrains.kotlinx:kotlinx-serialization-core-jvm
org.jetbrains.kotlinx:kotlinx-serialization-json-jvm
Important note: when upgrading the sdk-java
version, don't forget to check transitive dependencies again to avoid similar issues.