Code using PODAM can fail when run under Java 9 due to javax.xml.ws.Holder no longer being on the classpath:
java.lang.NoClassDefFoundError: javax/xml/ws/Holder
at uk.co.jemos.podam.api.PodamFactoryImpl.fillCollection(PodamFactoryImpl.java:1210)
at uk.co.jemos.podam.api.PodamFactoryImpl.resolveCollectionValueWhenCollectionIsPojoAttribute(PodamFactoryImpl.java:1081)
at uk.co.jemos.podam.api.PodamFactoryImpl.manufactureAttributeValue(PodamFactoryImpl.java:943)
at uk.co.jemos.podam.api.PodamFactoryImpl.populateReadWriteField(PodamFactoryImpl.java:840)
at uk.co.jemos.podam.api.PodamFactoryImpl.populatePojoInternal(PodamFactoryImpl.java:616)
at uk.co.jemos.podam.api.PodamFactoryImpl.manufacturePojoInternal(PodamFactoryImpl.java:526)
at uk.co.jemos.podam.api.PodamFactoryImpl.doManufacturePojo(PodamFactoryImpl.java:429)
at uk.co.jemos.podam.api.PodamFactoryImpl.manufacturePojo(PodamFactoryImpl.java:151)
at test.PodamJava9Test.failOnMissingJaxWsDependency(PodamJava9Test.java:23)
Unlike previous versions, Java 9 does not include the JAX-WS on the classpath by default. This means that code written and compiled against Java 8, but run under Java 9 can fail due to these classes not being on the classpath.
A workaround is to add the jaxws-api as a dependency in the POM.
Fix
While this could be fixed by adding jaxws-api as a dependency to pom.xml, I would argue that this is not the right fix. The only class being used is javax.xml.ws.Holder, and none of the actual JAX-WS functionality is being used. It seems like PODAM should just write its own Holder class and use that, e.g.:
public class Holder<T> {
public T value;
public Holder() {
}
public Holder(T value) {
this.value = value;
}
}
It looks like the Holder is only used for TypeManufacturerUtil.findCollectionSize() as a way for that class to change the AttributeStrategy to use in the case of a PodamCollection annotation. Alternatively, this could be refactored to no longer change the strategy to use via a method side effect, but instead have it be part of the return value.
Test Case
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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>podam-java9</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<java.version>1.8</java.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>uk.co.jemos.podam</groupId>
<artifactId>podam</artifactId>
<version>7.1.1.RELEASE</version>
<scope>test</scope>
</dependency>
<!-- Enabling this dependency allows this to work in Java 9 -->
<!--<dependency>-->
<!--<groupId>javax.xml.ws</groupId>-->
<!--<artifactId>jaxws-api</artifactId>-->
<!--<version>2.3.0</version>-->
<!--<scope>test</scope>-->
<!--</dependency>-->
</dependencies>
</project>
PodamJava9Test.java
package test;
import org.junit.Test;
import uk.co.jemos.podam.api.PodamFactoryImpl;
import java.util.List;
public class PodamJava9Test {
private static class Pojo {
private List<String> listProperty;
public List<String> getListProperty() {
return listProperty;
}
public void setListProperty(List<String> listProperty) {
this.listProperty = listProperty;
}
}
@Test
public void failOnMissingJaxWsDependency() {
new PodamFactoryImpl().manufacturePojo(Pojo.class);
}
}
$ java -version
java version "9.0.4"
Java(TM) SE Runtime Environment (build 9.0.4+11)
Java HotSpot(TM) 64-Bit Server VM (build 9.0.4+11, mixed mode)
$ mvn test
[...]
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.229 sec <<< FAILURE!
failOnMissingJaxWsDependency(test.PodamJava9Test) Time elapsed: 0.103 sec <<< ERROR!
java.lang.NoClassDefFoundError: javax/xml/ws/Holder
at uk.co.jemos.podam.api.PodamFactoryImpl.fillCollection(PodamFactoryImpl.java:1210)
at uk.co.jemos.podam.api.PodamFactoryImpl.resolveCollectionValueWhenCollectionIsPojoAttribute(PodamFactoryImpl.java:1081)
at uk.co.jemos.podam.api.PodamFactoryImpl.manufactureAttributeValue(PodamFactoryImpl.java:943)
at uk.co.jemos.podam.api.PodamFactoryImpl.populateReadWriteField(PodamFactoryImpl.java:840)
at uk.co.jemos.podam.api.PodamFactoryImpl.populatePojoInternal(PodamFactoryImpl.java:616)
at uk.co.jemos.podam.api.PodamFactoryImpl.manufacturePojoInternal(PodamFactoryImpl.java:526)
at uk.co.jemos.podam.api.PodamFactoryImpl.doManufacturePojo(PodamFactoryImpl.java:429)
at uk.co.jemos.podam.api.PodamFactoryImpl.manufacturePojo(PodamFactoryImpl.java:151)
at test.PodamJava9Test.failOnMissingJaxWsDependency(PodamJava9Test.java:23)
[...]
Results :
Tests in error:
failOnMissingJaxWsDependency(test.PodamJava9Test): javax/xml/ws/Holder
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0
Code using PODAM can fail when run under Java 9 due to
javax.xml.ws.Holder
no longer being on the classpath:Unlike previous versions, Java 9 does not include the JAX-WS on the classpath by default. This means that code written and compiled against Java 8, but run under Java 9 can fail due to these classes not being on the classpath.
A workaround is to add the
jaxws-api
as a dependency in the POM.Fix
While this could be fixed by adding
jaxws-api
as a dependency topom.xml
, I would argue that this is not the right fix. The only class being used isjavax.xml.ws.Holder
, and none of the actual JAX-WS functionality is being used. It seems like PODAM should just write its ownHolder
class and use that, e.g.:It looks like the Holder is only used for TypeManufacturerUtil.findCollectionSize() as a way for that class to change the AttributeStrategy to use in the case of a PodamCollection annotation. Alternatively, this could be refactored to no longer change the strategy to use via a method side effect, but instead have it be part of the return value.
Test Case
pom.xml
PodamJava9Test.java
This test case passes when run in Java 8.