Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I'm strugling with using jackson-dataformat-xml on android

I have some very basic code that works fine on oracle jre

JacksonXmlModule module = new JacksonXmlModule();
module.setDefaultUseWrapper(false);
XmlMapper xmlMapper = new XmlMapper(module);

First I tried official documentation adapted for gradle (by me, not sure if done correctly):

compile 'com.fasterxml.jackson.core:jackson-core:2.5.4'
compile 'com.fasterxml.jackson.core:jackson-annotations:2.5.4'
compile 'com.fasterxml.jackson.core:jackson-databind:2.5.4'
compile 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.5.4'

compile 'org.codehaus.woodstox:woodstox-core-asl:4.4.1'
compile 'javax.xml.stream:stax-api:1.0-2'

Result: gradle fails build time about bundling corelibraries into an application

...
:app:preDexDebug
trouble processing "javax/xml/stream/EventFilter.class":
Ill-advised or mistaken usage of a core class (java.* or javax.*)
when not building a core library.
...

2nd attempt trying to follow Sean's answer (Basicly he repackages corelibs with prefix names and rebuilds jackson-dataformat-xml to use the prefixed names)

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'

And build time failed on duplicates

Duplicate files copied in APK META-INF/services/com.fasterxml.jackson.core.ObjectCodec

so added:

packagingOptions {
    ...
    exclude 'META-INF/services/com.fasterxml.jackson.core.JsonFactory'
    exclude 'META-INF/services/com.fasterxml.jackson.core.ObjectCodec'
}

When adding the exclusions it builds and deploys, but fails runtime on below stackdump (AFAIK it cant find the SAX provider, even tho it is added to the classpath to my understanding)

edu.usf.cutr.javax.xml.stream.FactoryConfigurationError: Provider com.bea.xml.stream.MXParserFactory not found
            at edu.usf.cutr.javax.xml.stream.FactoryFinder.newInstance(FactoryFinder.java:72)
            at edu.usf.cutr.javax.xml.stream.FactoryFinder.find(FactoryFinder.java:176)
            at edu.usf.cutr.javax.xml.stream.FactoryFinder.find(FactoryFinder.java:92)
            at edu.usf.cutr.javax.xml.stream.XMLInputFactory.newInstance(XMLInputFactory.java:136)
            at com.fasterxml.jackson.dataformat.xml.XmlFactory.<init>(XmlFactory.java:97)
            at com.fasterxml.jackson.dataformat.xml.XmlFactory.<init>(XmlFactory.java:85)
            at com.fasterxml.jackson.dataformat.xml.XmlFactory.<init>(XmlFactory.java:82)
            at com.fasterxml.jackson.dataformat.xml.XmlMapper.<init>(XmlMapper.java:46)

What is the proper way to move forward on either #1 or #2?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
189 views
Welcome To Ask or Share your Answers For Others

1 Answer

Number 2 is the correct approach (Android doesn't like it when you include classes in the official Java package namespace - but then again, I wrote the original answer so I'm biased ;) ).

I believe the FactoryConfigurationError: Provider com.bea.xml.stream.MXParserFactory not found error is due to a bug in the Android build tools. In previous versions of ADT for Eclipse and Gradle plugin < 0.7.0 the /META-INF/* files are stripped from the JARs during the build process. It seems like >= v0.7.0 shouldn't have the problem according to Google, but from others' reports it sounds like it still may be problematic, and could potentially remove the META-INF/services/javax.xml.stream.XMLInputFactory file, which is required for the platform to register Aalto.

Try the workaround mentioned in AOSP issue 59658 comment 22:

  1. right click on /src/main (where you have /java and /res folders),
  2. select New > Folder > Java Resources Folder,
  3. click Finish (do not change Folder Location),
  4. right click on new /resources folder,
  5. select New > Directory
  6. enter "META-INF" (without quotes),
  7. right click on /resources/META-INF folder,
  8. select New > Directory
  9. enter "services" (without quotes)
  10. copy any file you need into /resources/META-INF/services

For you, in step 10 above you'd need to copy this file into /resources/META-INF/services. In case the file link is broken in the future, the name of the file is javax.xml.stream.XMLInputFactory and it consists of a single line:

com.fasterxml.aalto.stax.InputFactoryImpl

EDIT

If you get a "Error:duplicate files during packaging of APK... Path in archive: META-INF/services/javax.xml.stream.XMLInputFactory", you can try telling Gradle to keep the first occurrence with:

android {
  packagingOptions {
    pickFirst 'META-INF/services/javax.xml.stream.XMLInputFactory'
  }
}

EDIT 2

This bug may be affecting "pickFirst". Please make sure you're running the latest version of Android Studio, and update your local tools and Android Gradle plugin to make sure you're running the most recent version of the tools. This may be fixed in Android Studio 1.3 RC1.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...