JAXB Issues

JAXB library missing

Problem
Exception in thread "main" java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException
at somewhere.in.your.Code
Caused by: java.lang.ClassNotFoundException: javax.xml.bind.JAXBException
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:582)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:185)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:496)
... 1 more
Solution

This means the code cannot see the JAXB library DU. You will need to set up a library ref from your SLEE component to the supplied library

LibraryID[name=jaxb-runtime-glassfish,vendor=org.glassfish.jaxb,version=2.4.0-b2]

The JAXB API and other runtime dependencies will be visible transitively.

Classloader issues with JAXB unmarshalling

Problem

Classloader is not visible.

Caused by: java.lang.ClassNotFoundException: com.sun.xml.bind.v2.ContextFactory
at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:471)
at com.opencloud.util.MultiparentClassLoader.findClass(MultiparentClassLoader.java:305)
at com.opencloud.util.MultiparentClassLoader.loadClassNoResolve(MultiparentClassLoader.java:187)
at com.opencloud.util.MultiparentClassLoader.loadClass(MultiparentClassLoader.java:205)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:315)
at javax.xml.bind.ServiceLoaderUtil.nullSafeLoadClass(ServiceLoaderUtil.java:120)
at javax.xml.bind.ServiceLoaderUtil.safeLoadClass(ServiceLoaderUtil.java:155)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:267)
Solution

Code to create a JAXBContext for deserialisation may need to be created using a Classloader that has visibility of the JAXB library. Use the classloader aware variant of the JAXBContext factory method.

Use JAXBContext.newInstance(String contextPath, Classloader classloader) over JAXBContext.newInstance(Class…​ classesToBeBound)

- c = JAXBContext.newInstance(type);
+ c = JAXBContext.newInstance(type.getPackageName(), type.getClassLoader());

The classloader associated with the class containing the code should work.

Guava Issues

Guava has been upgraded to resolve some issues. There are several API changes, common issues include:

Objects.toStringHelper()

Problem
[oc-javac] /some/where/in/my/Code.java:46: error: cannot find symbol
[oc-javac] return Objects.toStringHelper("ZhRequest")
[oc-javac] ^
[oc-javac] symbol: method toStringHelper(String)
[oc-javac] location: class Objects
Solution

Guava moved this function to MoreObjects, update code to use MoreObjects.toStringHelper()

- import com.google.common.base.Objects;
+ import com.google.common.base.MoreObjects;
@Override
public String toString() {
-  return Objects.toStringHelper("Code")
+  return MoreObjects.toStringHelper("Code")

Iterators.emptyIterator()

Problem
[oc-javac] /somewhere/in/your/Code.java:71: error: <T>emptyIterator() is not public in Iterators; cannot be accessed from outside package
[oc-javac] when(empty.iterator()).thenReturn(Iterators.<CassandraRow>emptyIterator());
[oc-javac] ^
[oc-javac] where T is a type-variable:
[oc-javac] T extends Object declared in method <T>emptyIterator()
Solution

Use Collections.<T>emptyIterator()

MoreExecutors.sameThreadExecutor() has disappeared

Solution

Replace MoreExecutors.sameThreadExecutor() with MoreExecutors.directExecutor()

Misc Issues

Problems with Javadoc validation

Solution

Fix the javadoc. More recent versions of Java are stricter with validation.

Commonly seen tag problems are:

  • @link used when class is inaccessible. Suggest changing to @code as previously it would not have worked.

  • @return used for void methods. Can be solved by removing tag.

  • Mismatched {}. Can be solved by adding missing brackets.

Another common problem is the source set being incorrect meaning javadoc cannot find the required classes. This can usually be fixed by either moving the files to where javadoc is looking, or telling javadoc to look somewhere else.

JDK11 FilePermission change

Problem

At deployment or at runtime,

java.security.AccessControlException: access denied ("java.io.FilePermission" "xxxxx" "read")
Solution

From OpenJDK9: it removes pathname canonicalization from FilePermission creation, thus calculations of the equals() and implies() methods will be based on the raw path string one provides in "new FilePermission(path, action)". details: http://mail.openjdk.java.net/pipermail/jdk9-dev/2016-October/005062.html

By default Rhino startup scripts use -Djdk.io.permissionsUseCanonicalPath=true to work around this behaviour.

JRE removal from JDK11

Problem

JRE is removed from JDK11, paths originally with jre will be broken.

Solution

Some paths wll need updating, for example, path jre/lib/security/cacerts will be lib/security/cacerts

Guice has moved

Problem
[ivy:resolve] ::::::::::::::::::::::::::::::::::::::::::::::
[ivy:resolve] :: UNRESOLVED DEPENDENCIES ::
[ivy:resolve] ::::::::::::::::::::::::::::::::::::::::::::::
[ivy:resolve] :: com.google#guice;4.2.2: not found
[ivy:resolve] ::::::::::::::::::::::::::::::::::::::::::::::
[ivy:resolve]
Solution

Organisation name has changed, need to update ivy dependency

manually:

- <dependency org="com.google" name="guice" rev="${guice.ivy.revision}" conf="self,impl -> war,util" />
+ <dependency org="com.google.inject" name="guice" rev="${guice.ivy.revision}" conf="self,impl -> war,util" />

OR automatically for a whole repo:

find . -name ivy.xml -exec grep 'dependency.*org="com.google".*name="guice"' {} \; \
-exec sed --in-place '/dependency.*name="guice"/s/org="com.google"/org="com.google.inject"/' {} \; \
-exec grep 'dependency.*name="guice"' {} \; -print

Log4j has moved

Problem
[ivy:resolve] ::::::::::::::::::::::::::::::::::::::::::::::
[ivy:resolve] :: UNRESOLVED DEPENDENCIES ::
[ivy:resolve] ::::::::::::::::::::::::::::::::::::::::::::::
[ivy:resolve] :: apache#log4j;2.11.2: not found
[ivy:resolve] ::::::::::::::::::::::::::::::::::::::::::::::
[ivy:resolve]
Solution

manually:

- <dependency org="apache" name="log4j" rev="${log4j.ivy.revision}" conf="self -> api" />
+ <dependency org="org.apache.logging.log4j" name="log4j" rev="${log4j.ivy.revision}" conf="self -> api" />

OR automatically for a whole repo:

find . -name ivy.xml -exec grep 'dependency.*org="apache".*name="log4j"' {} \; \
-exec sed --in-place '/dependency.*name="log4j"/s/org="apache"/org="org.apache.logging.log4j"/' {} \; \
-exec grep 'dependency.*name="log4j"' {} \; -print

SLF4J 1.7.25 works differently with log4j 2.11.2

Problem
[junit] Failed to instantiate SLF4J LoggerFactory
[junit] Caused an ERROR
[junit] Reported exception:
[junit] org/apache/log4j/Level
[junit] java.lang.NoClassDefFoundError: org/apache/log4j/Level
Solution

Change the conf for slf4j from log4j to log4j-bridge thus manually:

- <dependency org="org.slf4j" name="slf4j" rev="${slf4j.ivy.revision}" conf="self -> api,log4j" />
+ <dependency org="org.slf4j" name="slf4j" rev="${slf4j.ivy.revision}" conf="self -> api,log4j-bridge" />

OR automatically for a whole repo:

find . -name ivy.xml -exec grep 'dependency.*org="org.slf4j".*name="slf4j".*conf=".*log4j' {} \; \
-exec sed -E --in-place '/dependency.*name="slf4j"/s/conf="([^"]+)log4j([";,])/conf="\1log4j-bridge\2/' {} \; \
-exec grep 'dependency.*name="slf4j"' {} \; -print

Local Name Service Common Module Removed

Solution

Local-Name-Service was a common module that could be used to specify host names that should resolve to the loopback address in a system property (com.opencloud.localnameservice.names). It was heavily dependent on a package in the JDK called sun.net.spi.nameservice, which was removed in JDK9 and there does not appear to be a library to re-add it. Fortunately there is a new built in system property that can be used to achieve the same effect: jdk.net.hosts.file. The structure of this file is equivalent to that of the /etc/hosts file.

Problems With Jarjar

Solution

Switch from using third-party library to using ant-jarjar common module. See changes to sdk-tools for an example.

STU Fails To Connect To Cassandra

Cassandra is not yet officially supported on JDK11, so for the time being we will continue to run in on JDK8. STU has been set up to do this but it requires that a copy of JDK8 is installed on your system and you have an environment variable called JDK1_8_HOME set to point at it.

Previous page