Skip to main content

Problem Using JAXB with an Extension XML and It's Base

1 reply [Last post]
etherealstill
Offline
Joined: 2008-10-06
Points: 0

I am using JAXB to generate a class structure based on two XML schemas---say, Base.xsd and Extension.xsd. Both of these schemas declare their own namespace for their respective types. Base.xsd contains a complexType of some type, let's say "Person," as well as some more types that are put inside of person such as "Eyes" and "Hair," and there is also an "any" tag in Person. Extension.xsd defines some other complexTypes such as "Shirt" and "Shoes." There already exists an application which emits XML that is validated on Base.xsd and Extension.xsd, and uses "Person" such that "Person" contains "Eyes," "Hair," "Shirt," and "Shoes."

I cannot change the form of the XML being emitted by the application, which must be validated against Base.xsd and Extension.xsd, but I can change Extension.xsd (as long as the emitted XML in its present form can still be validated against it).

Now, because I've had to generate these class models in two separate calls to xjc (one for each schema), JAXB will generate a Person class such that Person only contains Eyes and Hair. Of course, this is problematic in any application that subscribes to the JAXB generated model, because we would like to have type-safe access to Shirt and Shoes from Person.

My first naive attempt to resolve this issue was to redefine Person in Extension.xsd such that it contains a Shirt element and a Shoes element. However, I've since realized that this is impossible because a redefined type must exist in the same namespace as it's original form.

I've also been working on sort of a hybrid schema so that Base.xsd and Extension.xsd can be combined by cutting and pasting to declare a Person with all the desired elements--including the type definitions. This hybrid can be used to generate the right class structure and then ignored. This is somewhat tedious however, as the actual schemas in question are quite a bit more lengthy and more complicated. I'm also experiencing some namespace issues that--again, due to my naivety regarding XML schemas--might doom the hybrid effort.

The hybrid schema method seems a kludge in itself, but it's certainly preferable to having the subscriber to the JAXB model extract the types through Person's "getAny()" method.

Any ideas?

EDIT: Originally posted here: http://forums.java.net/jive/thread.jspa?messageID=483345&#483345

Message was edited by: etherealstill

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
etherealstill
Offline
Joined: 2008-10-06
Points: 0

I have resolved this, although the solution currently requires me to "hack" the XJC generated classes.

First of all, I realized that I needed to create a new schema which (to continue with the Person analogy) redefines the complexType "Person" from "Base.xsd". Adding the types from Extension.xsd can be accomplished by using the xsd:import tag to import the Extension, and adding the desired extension elements to the redefinition of Person.

Run xjc against this new schema.

The correct references to the added fields will be created in the generated class model, but--due to an apparent error in jaxb namespace resolution--these fields will not map properly. To get JAXB to recognize them when unmarshalling from an instance document, add the attribute "namespace" and assign to it the proper namespace to the XmlType annotation on the appropriate field.

I am still unsure why JAXB is unable to make the correct namespace assignments itself. I feel that this is a bug, since in the class documentation, it will indicate that a particular Element is of the desired namespace--but this namespace is NOT the one JAXB actually maps it to.

This experience has been incredibly frustrating, and many times I convinced myself to look for another solution when the desire to "make it right" pulled me back to resolve my issues with JAXB. I think the framework could be better.

** Also, in some cases with particular schemas I had to edit the package-info.java file to include the redefined schema's target namespace instead of the imported namespace.