Skip to main content

JAXB NameSpaceContext access and DOM binding

1 reply [Last post]
aaronanderson
Offline
Joined: 2004-01-23

I am attempting to create a JAXB binding customization for the WS-HumanTask schema which requires access to the NamespaceContext for a specific element. Some WS-HumanTask elements contain functions that reference namespace prefixes defined in the document.

<htd:humanInteractions xmlns:htd="http://www.example.org/WS-HT"
...
xmlns:cla="http://www.insurance.example.com/claims">

<htd:tasks>

<htd:task name="Task1" xmlns:cla2="http://www.insurance.example.com/claims2" >
...
<htd:priority xmlns:cla3="http://www.insurance.example.com/claims3"> xs:integer(htd:getInput("ClaimApprovalRequest")/cla:prio*(cla2:t2+cla3:t3)) </htd:priority>

Unfortunately due to JAXB issue 670 the NamespaceContext cannot be passed into a custom XMLAdapter so in the default Object binding the NamespaceContext is unavailable. This meant that the only way to obtain access to the namespace/prefix mapping is to bind the namespace sensitive types as DOM elements.

Here is an excerpt from the WS-HumanTask schema:

<xsd:complexType name="tExtensibleElements">
<xsd:sequence>
<xsd:element name="documentation" type="tDocumentation"
minOccurs="0" maxOccurs="unbounded" />
<xsd:any namespace="##other" processContents="lax" minOccurs="0"
maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:anyAttribute namespace="##other" processContents="lax" />
</xsd:complexType>
<xsd:complexType name="tTask">
<xsd:complexContent>
<xsd:extension base="tExtensibleElements">
<xsd:sequence>
...
<xsd:element
ref="priority"
minOccurs="0"
/>
...

<xsd:complexType name="tExpression" mixed="true">
<xsd:sequence>
<xsd:any namespace="##other" processContents="lax" minOccurs="0"
maxOccurs="unbounded" />
</xsd:sequence>
<xsd:attribute name="expressionLanguage" type="xsd:anyURI" />
<xsd:anyAttribute namespace="##other" processContents="lax" />
</xsd:complexType>
<xsd:complexType name="tPriority" mixed="true">
<xsd:complexContent mixed="true">
<xsd:extension base="tExpression" />
</xsd:complexContent>
</xsd:complexType>

By attaching the JAXB:DOM binding customization to the XMLSchema any declarations and also to the tPriority complex type I was able to coerce the priority element to be unmarshalled as a DOM and then I was able to use the apache commons XMLSchema NodeNamespaceContext class to rebuild a NamespaceContext and retrieve all the prefix mappings.

I did have a few questions about some of the results I observed during my testing.

  1. Even when I bind the jaxb:dom customization to the tPriority complextype JAXB still generates a TPriority class. Is there any way to disable the generation of class for a specify XMLSchema type?
  2. If I only attached the jaxb:dom customization to the tPriority complextype and not to anything else the containing TTask was generated with the priority field of type Element but during unmarshalling the priority field would be null and the TTask's any field would contain an instance of the TPriority class instead of a DOM element as desired
  3. Similar to the anomaly above, if I bound the jaxb:dom binding to the tExtensibleElements's any declaration and to the tPriority complex type then during unmarshalling a DOM node would be created for the priority element but it would still end up in the TTask's any field instead of the desired priority field. It appears that if an any declaration is present JAXB dumps all jaxb:dom declared content into it even if there is a designated field bound for it
  4. Since the priorty DOM element ends up in the TTask's any field I will probably need to further customize the JAXB code buy disabling the getter/setter for the TTask priority property and then inject new getter/setters using the JAXB code injection plugin that perhaps remarshalls the DOM as a class that extends from TPriority that can hold the generated NamespaceContext. Does this sound like a valid approach?
  5. Is there an alternative solution for this type of element NamespaceContext awareness issue?
  6. I am using JAXB 2.1.13

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
aaronanderson
Offline
Joined: 2004-01-23

After reading the JAXB spec at least for #3 it was the expected behavior. I also came across the JAXB Binder class which seems to address all my JAXB/DOM issues.



DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

dbf.setNamespaceAware(true);

DocumentBuilder db = dbf.newDocumentBuilder();

Document document = db.parse(new File("htd_doc.xml"));

JAXBContext jaxbContext = JAXBContext.newInstance("com.example.htd");

Binder binder = jaxbContext.createBinder();

htdDoc = ((JAXBElement)
binder.unmarshal(document)).getValue();

for (TTask t : hiDoc.getTasks().getTask()) {

Node e = binder.getXMLNode(t.getPriority());

if (e != null) {

NodeNamespaceContext namespaceContext = NodeNamespaceContext.getNamespaceContext(e);

....


This even makes it easy to use XPath with JAXB by operating on the DOM and then switching over to JAXB when needed. Pretty nifty!