Search code examples
jacksongluon-mobile

GluonMobile + Jackson = java.lang.NoClassDefFoundError: java.util.function.ToLongFunction


I'm porting a desktop JavaFx Application that requires Jackson to GluonMobile, it's my first time using this platform and I end up on the next stacktrace with a NoClassDefFoundError.

I would like to know if this requires a feature not supported by GluonMobile or if I just forgot to include something properly.

Apr 19, 2018 8:25:02 PM com.fasterxml.jackson.databind.ext.Java7Support <clinit>
WARNING: Unable to load JDK7 types (annotations, java.nio.file.Path): no Java7 support added
[WARN] java.lang.Class: Class.forName() failed to load 'javax.servlet.Servlet'. Use the -forcelinkclasses command line option or add <forceLinkClasses><pattern>javax.servlet.Servlet</pattern></forceLinkClasses> to your robovm.xml file to link it in.
ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console...
TRACE Task Catching
 java.lang.NoClassDefFoundError: java.util.function.ToLongFunction
at java.lang.VMClassLoader.findClassInClasspathForLoader(Native Method)
at java.lang.PathClassLoader.findClass(PathClassLoader.java:193)
at java.lang.ClassLoader.loadClass(ClassLoader.java:515)
at java.lang.ClassLoader.loadClass(ClassLoader.java:475)
at com.fasterxml.jackson.datatype.jsr310.ser.InstantSerializer.<init>(InstantSerializer.java:38)
at com.fasterxml.jackson.datatype.jsr310.ser.InstantSerializer.<clinit>(InstantSerializer.java:35)
at com.fasterxml.jackson.datatype.jsr310.JavaTimeModule.<init>(JavaTimeModule.java:161)
at com.general.plugin.jackson.json.JacksonObjectMapper.<clinit>(JacksonObjectMapper.java:214)
at java.lang.Class.classForName(Native Method)
at java.lang.Class.forName(Class.java:218)
at java.lang.Class.forName(Class.java:176)
at com.general.core.startup.Configuration.getSharableInstance(Configuration.java:69)
at com.general.core.startup.AbstractClient.<init>(AbstractClient.java:39)
at com.objectdb.core.startup.Client.<init>(Client.java:31)
at com.objectdb.ui.service.ClientFactory.getDBClient(ClientFactory.java:39)
at com.objectdb.ui.service.ClientTask.getDBClient(ClientTask.java:13)
at com.objectdb.ui.startup.Main$2.call(Main.java:30)
at javafx.concurrent.Task$TaskCallable.call(Task.java:1423)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.lang.Thread.run(Thread.java:837)

Solution

  • This solution is quite a workaround that requires a bit of work. Fixes Jackson 2.9.5 to work in gluon jfxmobile-plugin 1.3.10.

    1. To fix jackson-databind to be able build immutable objects with a single constructor.

    1.1 Drop the usage of the JDK8 module parameter-names since this requires a non implemented VM feature. Use instead java.beans.ConstructorProperties.

    1.2 Jackson uses for ConstructorProperties support some Interfaces from JDK8 that can be safety included as part of your project.

    java.beans.ConstructorProperties
    java.beans.Transient
    

    1.3 Force link JDK7 support

    forceLinkClasses = [
        'com.fasterxml.jackson.databind.ext.Java7SupportImpl',
    ]
    
    1. To fix jackson-datatype-jsr310.

    2.1 It uses some JDK8 interfaces that can be safety included in your project.

    java.util.function.ToIntFunction
    java.util.function.ToLongFunction
    

    2.2 It uses some JDK8 methods that can be safety substituted by JDK6-7 implementations, simply include in your project the java files and look up the pre-JDK8 back ports of the Time API.

    JavaTimeModule.java
    SerializerToPach.java
    

    3.3 Point your own JavaTimeModule to your own serializer. 3.4 Register in your ObjectMapper your own JavaTimeModule.

    Voila, now you can use the lattest Jackson to create immutable objects and use JDK8 Time classes in gluon jfxmobile-plugin 1.x