Using JAXB with Google Android

I need to parse the java-objects which are passed through xml. I want to use for these purposes JAXB framework, because I have pre-annotated (using JAXB) java-class.

Is this possible in principle?

InputStream input = entity.getContent();
JAXBContext jc = JAXBContext.newInstance(new Class[] {Response.LoginResponse.class});
Unmarshaller un = jc.createUnmarshaller();
LoginResponse response = (LoginResponse)un.unmarshal(input);

in line 4, I have a warning: "unable to resolve static method 282 JAXBContext ... " and then VM crashes

Any ideas on how to solve this problem?


Solution 1:

I'm not exactly resolving your problem, but JAXB isn't included in android by default and the library will cost you 9(!) MB of your apk. Try SimpleXML instead. It has similiar abilities and much more lightweight.

Solution 2:

I had the same problem of wanting to use a bunch of JAXB classes in the process of parsing XML (and, for me, JSON) web server responses.

I wrote up a wiki page for Parsing XML and JSON on Android, which describes a solution for this problem and guides you through step-by-step.

To be clear - I'd advise using JSON instead of XML on Android whenever possible. There are significant performance advantages for JSON.

To summarize my solution for using JAXB classes for both JSON and XML parsing:

I ended up stripping all annotations and javax.xml.* imports from the JAXB classes (slightly easier than re-annotating classes for SimpleXML - plus, you can also parse JSON responses) to create true POJOs, and then use Jackson with modified versions of the XML libraries that Jackson depends on.

The modification of the XML libraries is necessary because Android doesn't include required XML classes in the platform, and it will complain if you try to include classes in the protected javax.xml namespace as libraries in your project.

I stripped the XML annotations and imports manually initially, but then ended up automating the process via ant scripts.

Luckily, you can automate the XML library modification process. I wrote up a detailed post on Modifying XML libraries for Android (which the full tutorial references) which describes how to move the relevant classes into a new unprotected namespace using the Jar Jar Links utility.

If you want to use Jackson on Android, I've also created a modified version of the jackson-dataformat-android, aalto-xml, stax-api, and stax2-api projects for Android that you can feel free to use.

Here's a sample of what you would include in your pom.xml to include the dependencies via Maven:

<dependencies>              
    <!-- Using Jackson for parsing -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>2.1.2</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.1.2</version>
    </dependency>

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-annotations</artifactId>
        <version>2.1.2</version>
    </dependency>   
    <!-- XML parsing  -->
    <!-- So many problems with XML and Android...
         Below XML libraries have been modified using JarJar
         and are NOT the same as their J2SE counterparts,
         hence the added "-android" to the artifactId
         See:
         https://github.com/CUTR-at-USF/SiriRestClient/wiki/Modifying-XML-libraries-for-Android
      -->        
    <dependency>
        <groupId>edu.usf.cutr.android.xml</groupId>
        <artifactId>jackson-dataformat-xml-android</artifactId>
        <version>2.1.2</version>
    </dependency>
    <dependency>
        <groupId>edu.usf.cutr.android.xml</groupId>
        <artifactId>stax2-api-android</artifactId>
        <version>3.1.1</version>
    </dependency>
    <dependency>
        <groupId>edu.usf.cutr.android.xml</groupId>
        <artifactId>stax-api-android</artifactId>
        <version>1.0-2</version>
    </dependency>
    <dependency>
        <groupId>edu.usf.cutr.android.xml</groupId>
        <artifactId>aalto-xml-android</artifactId>
        <version>0.9.8</version>
    </dependency>        
</dependencies>    

<repositories>
    <!-- CUTR Android XML libraries Releases -->
    <repository>
      <id>cutr-releases</id>
      <url>https://github.com/CUTR-at-USF/cutr-mvn-repo/raw/master/releases</url>
    </repository>      
</repositories>

See this page for more details using these libraries.

You can download the JAR files from their respective directories here, if you want to include them directly in your project.

You can also check out the open-source "SIRI REST Client" app that uses these libraries for a working example.

EDIT

If you're using Gradle, your build.gradle would look like this:

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:0.9.+'
    }
}
apply plugin: 'android'

repositories {
    mavenCentral()
    maven {
        // CUTR SNAPSHOTs
        url "https://github.com/CUTR-at-USF/cutr-mvn-repo/raw/master/snapshots"
    }
    maven {
        // CUTR Releases
        url "https://github.com/CUTR-at-USF/cutr-mvn-repo/raw/master/releases"
    }
}

android {
    compileSdkVersion 19
    buildToolsVersion "19.0.1"
    ...
}

dependencies {
    ...
    // Normal Jackson libraries
    compile 'com.fasterxml.jackson.core:jackson-core:2.1.2'
    compile 'com.fasterxml.jackson.core:jackson-annotations:2.1.2'
    compile 'com.fasterxml.jackson.core:jackson-databind:2.1.2'
    // Repackaged XML-specific libraries
    compile 'edu.usf.cutr.android.xml:jackson-dataformat-xml-android:2.1.2'
    compile 'edu.usf.cutr.android.xml:stax2-api-android:3.1.1'
    compile 'edu.usf.cutr.android.xml:stax-api-android:1.0-2'
    compile 'edu.usf.cutr.android.xml:aalto-xml-android:0.9.8'
    ...       
}