FamilySearch/gedcomx-java

to/from qname uri relies on jaxb, even when using jackson

Closed this issue · 9 comments

he following is a common pattern:

public static GenderType fromQNameURI(URI qname) {
  return org.codehaus.enunciate.XmlQNameEnumUtil.fromURIValue(qname.toString(), GenderType.class);
}

The problem with this on Android is that jaxb is not part of Android (it is pretty much based on Java 5). The above throws an exception:

11-21 19:27:09.206 20353-20353/com.diamondedge.related E/AndroidRuntime: java.lang.NoClassDefFoundError: Failed resolution of: Ljavax/xml/bind/annotation/XmlSchema;
11-21 19:27:09.206 20353-20353/com.diamondedge.related E/AndroidRuntime:     at org.codehaus.enunciate.XmlQNameEnumUtil.fromURIValue(XmlQNameEnumUtil.java:253)
11-21 19:27:09.206 20353-20353/com.diamondedge.related E/AndroidRuntime:     at org.codehaus.enunciate.XmlQNameEnumUtil.fromURIValue(XmlQNameEnumUtil.java:219)
11-21 19:27:09.206 20353-20353/com.diamondedge.related E/AndroidRuntime:     at org.gedcomx.types.GenderType.fromQNameURI(GenderType.java:70)
11-21 19:27:09.206 20353-20353/com.diamondedge.related E/AndroidRuntime:     at org.gedcomx.conclusion.Gender.getKnownType(Gender.java:190)

So far it seems that people have not been successful in getting jaxb alternatives to work in Android and even if it did work it would be overkill just so these kinds of methods would work.

It would be really nice if the gedcomx-model classes could be used with jackson and not require jaxb library in order to work.

Finally got around to looking at this.

If you're using JSON, the gedcomx-java runtime only needs the JAXB annotations; it doesn't need the JAXB runtime. So if you just include the jaxb-api jar on your classpath, these methods should work on Android.

The jaxb-api jar is just 100K with no dependencies (it's basically just some annotations), and it's much smaller than the simple-xml jar that would be required by your proposed solution above.

What do you think? Can you confirm that works?

It had been a while since I did the original android version and did not remember using simplexml annotations in a similar fashion to the jaxb annotations. Using simplexml will not work anyway with the gedcomx-java since it would require adding those annotations as well which probably not desirable.

So far I have not been able to convince android build system to allow including code from java/javax packages (that is a violation). I will try to find some workarounds to force it to include libraries that are in the JDK but so far this is not an option.

On Jan 15, 2016, at 4:28 PM, Ryan Heaton notifications@github.com wrote:

Finally got around to looking at this.

If you're using JSON, the gedcomx-java runtime only needs the JAXB annotations; it doesn't need the JAXB runtime. So if you just include the jaxb-api jar http://search.maven.org/#artifactdetails%7Cjavax.xml.bind%7Cjaxb-api%7C2.2.12%7Cjar on your classpath, these methods should work on Android.

The jaxb-api jar is just 100K with no dependencies (it's basically just some annotations), and it's much smaller than the simple-xml jar that would be required by your proposed solution above.

What do you think? Can you confirm that works?


Reply to this email directly or view it on GitHub #38 (comment).

Okay, thanks for trying. We might just need to hard-code the logic...

I worked on a variation of my version of EnumUtil to remove the dependence on SimpleXml. The following I think is all I changed. You will notice 2 different ways to figure out which package the class is in and can choose the one you like the best. This approach seems as/more flexible than the one using JAXB. This approach does not constrain all classes in the same java package to have the same namespace should that need ever make sense. As compared to maintenance to me seem very similar effort. For JAXB you need to create a package-info.java and maintain the namespace inside their. With the following the package-info.java would probably not be needed anymore.

private static String getNamespaceString(Class clazz) {
    // check for packages that are different from default (alternative 1)
    if (clazz.getPackage().getName().equals("org.gedcomx.types"))
        return GedcomxConstants.GEDCOMX_TYPES_NAMESPACE;

    // check for packages that are different from default (alternative 2)
    if (clazz.getPackage() == GenderType.class.getPackage())
        return GedcomxConstants.GEDCOMX_TYPES_NAMESPACE;

    // override any classes within a package that may be different

// if (clazz == GenderType.class)
// return GedcomxConstants.GEDCOMX_TYPES_NAMESPACE;

    // default to gedcomx namespace
    return GedcomxConstants.GEDCOMX_NAMESPACE;
}

Looks good. I'll try to work on it in the next few days.

Finally fixed this at 8096f33, bundled with 1.0.58.M1.

We should make those dependencies scope-provided so that you don't have to exclude anything to use the JSON.