3

I am using JAXB to marshal/unmarshal an xml document based on defined schemas. What I am noticing is that JAXB is producing incorrect namespaces in the marshalled xml.

Here are the details -

soap.xsd -->

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope" 
    xmlns:svc="http://abc.com/ServiceSetupV001"
    targetNamespace="http://schemas.xmlsoap.org/soap/envelope"
    elementFormDefault="qualified" attributeFormDefault="unqualified">

    <xsd:import namespace="http://abc.com/ServiceSetupV001" schemaLocation="schema1.xsd" />

    <xsd:complexType name="Envelope">
        <xsd:sequence minOccurs="0" maxOccurs="1">
            <xsd:element name="Body" type="soapenv:Body" minOccurs="0" maxOccurs="1" />
        </xsd:sequence>
    </xsd:complexType>

    <xsd:complexType name="Body">
        <xsd:sequence minOccurs="0" maxOccurs="1">
            <xsd:element name="detailsRequest" type="svc:DetailsRequest" minOccurs="0" maxOccurs="1"/>
            <xsd:element name="detailsResponse" type="svc:DetailsResponse" minOccurs="0" maxOccurs="1" />
        </xsd:sequence>
    </xsd:complexType>

</xsd:schema>

schema1.xsd -->

<xsd:schema 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    targetNamespace="http://abc.com/ServiceSetupV001" 
    xmlns:svc="http://abc.com/ServiceSetupV001" 
    xmlns:osa="http://abc.com/xmlschema/osa" 
    elementFormDefault="qualified" attributeFormDefault="unqualified">

    <xsd:import namespace="http://abc.com/xmlschema/osa" schemaLocation="schema2.xsd"/>

    <xsd:complexType name="DetailsRequest">
        <xsd:sequence minOccurs="0" maxOccurs="1">
            <xsd:element name="requestHeader" type="osa:RequestHeader" />
        </xsd:sequence>
    </xsd:complexType>

    <xsd:element name="detailsRequest" type="svc:DetailsRequest" />

    <xsd:complexType name="DetailsResponse">
        <xsd:sequence minOccurs="0" maxOccurs="1">
            <xsd:element name="responseHeader" type="osa:ResponseHeader" />
        </xsd:sequence>
    </xsd:complexType>

    <xsd:element name="detailsResponse" type="svc:DetailsResponse" />

</xsd:schema>

schema2.xsd -->

 <xsd:schema xmlns="http://www.w3.org/2001/XMLSchema" 
        xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
        xmlns:osa="http://abc.com/xmlschema/osa" 
        targetNamespace="http://abc.com/xmlschema/osa" 
        elementFormDefault="qualified" attributeFormDefault="unqualified">

        <xsd:complexType name="RequestHeader">
            <xsd:sequence>
                <xsd:element name="component" type="string" />
                <xsd:element name="channel" type="string" />
                <xsd:element name="serverInstance" type="string" minOccurs="0" />
                <xsd:element name="traceId" type="string" />
                <xsd:element name="applicationId" type="string" />
                <xsd:element name="userId" type="string" minOccurs="0" />
                <xsd:element name="userIdType" type="string" minOccurs="0" />
                <xsd:element name="role" type="string" minOccurs="0" />
                <xsd:element name="timestamp" type="dateTime" minOccurs="0" />
                <xsd:element name="isReplyExpected" type="boolean" minOccurs="0" />
            </xsd:sequence>
        </xsd:complexType>

        <xsd:complexType name="ResponseHeader">
            <xsd:sequence>
                <xsd:element name="component" type="string" />
                <xsd:element ref="osa:service" />
                <xsd:element name="traceId" type="string" />
                <xsd:element name="serverInstance" type="string" />
                <xsd:element name="timestamp" type="dateTime" />
            </xsd:sequence>
        </xsd:complexType>

        <xsd:element name="service" type="osa:Service" />
        <xsd:complexType name="Service">
            <xsd:sequence>
                <xsd:element name="name" type="string" />
                <xsd:element name="operation" type="string" />
                <xsd:element name="version" type="string" />
            </xsd:sequence>
        </xsd:complexType>  

    </xsd:schema>

I have defined a namespacePrefixMapperImpl for the jaxbMarshaller (in my spring config), that maps URIs to my defined prefix names.

The marshalled response xml looks like this. Notice that JAXB has goofed up on the namespace prefixes. JAXB is using soapenv namespace for detailsResponse complex type, instead of the svc prefix. Then it is using svc prefix for responseHeader complex type instead of osa prefix. Some elements are of type string, and as such should have no prefixes (ie the default namespace). And so on...

Where did I go wrong? Or is this an issue with jaxb-impl.

Generated XML -->

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope"
xmlns:osa="http://abc.com/xmlschema/osa"
xmlns:svc="http://abc.com/ServiceSetupV001">
    <soapenv:Body>
        <soapenv:detailsResponse>
            <svc:responseHeader>
                <osa:component/>
                <osa:service/>
                <osa:traceId>sadasdas</osa:traceId>
                <osa:serverInstance>40d501</osa:serverInstance>
                <osa:timestamp>2012-07-01T02:18:00.693Z</osa:timestamp>
            </svc:responseHeader>
        </soapenv:detailsResponse>
    </soapenv:Body>
</soapenv:Envelope>

The plugin I am using to generate the JAXB classes from the schema is defined in my pom.xml as follows:

<!-- Plugin to generate jaxb classes from xsd -->
<plugin>
    <groupId>org.jvnet.jaxb2.maven2</groupId>
    <artifactId>maven-jaxb2-plugin</artifactId>
    <version>0.8.2</version>
    <executions>
        <execution>
            <id>process-xsd</id>
            <goals>
                <goal>generate</goal>
            </goals>
            <phase>generate-sources</phase>
            <configuration>
                <schemaIncludes>
                    <include>**/*.xsd</include>
                </schemaIncludes>
                <bindingIncludes>
                    <include>**/*.xjb</include>
                </bindingIncludes>
                <generateDirectory>${src.dir}</generateDirectory>
                    <verbose>true</verbose>
                <extension>true</extension>
                <args>
                    <arg>-Xannotate</arg>
                </args>
                <plugins>
                    <plugin>
                        <groupId>org.jvnet.jaxb2_commons</groupId>
                        <artifactId>jaxb2-basics-annotate</artifactId>
                        <version>0.6.4</version>
                    </plugin>
                </plugins>
            </configuration>
        </execution>
    </executions>
    <dependencies>
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.2.6</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-impl</artifactId>
            <version>2.2.6</version>
        </dependency>       
        <dependency>
            <groupId>javax.activation</groupId>
            <artifactId>activation</artifactId>
            <version>1.1.1</version>
        </dependency>
        <dependency>
            <groupId>stax</groupId>
            <artifactId>stax-api</artifactId>
            <version>1.0.1</version>
        </dependency>
        <dependency>
            <groupId>activesoap</groupId>
            <artifactId>jaxb-xercesImpl</artifactId>
            <version>1.5</version>
        </dependency>                   
    </dependencies>             
</plugin>
pfl
  • 51
  • 1
  • 4

1 Answers1

2

Well, looks like Jaxb is retaining the target namespace of the containing xsd for the imported child elments, even though those imported child elements have their own namespace. One way to fix this is to change the definintion of the imported element in the schema from "type" to "ref".

But, in this case, I dont want to modify the schemas as they are from the client and as such we dont want to modify them to make it work.

Hence, I added the below annotations in my bindings.xjb file. I can now see that the elements in the generated schema classes have the correct namespace declaration. But, now the issue, is that the generated xml does not produce the child elements, even though the namespace is now correct.

So, I am kind of stuck again. I didnt imagine this would be so hard.

Changes to my bindings.xjb:

<jaxb:bindings node="//xsd:complexType[@name='Body']//xsd:element[@name='detailsRequest']">
    <annox:annotate target="field">
    <annox:annotate annox:class="javax.xml.bind.annotation.XmlElement" 
        name="detailsRequest" 
        namespace="http://abc.com/ServiceSetupV001"/>
    </annox:annotate>            
<jaxb:bindings node="//xsd:complexType[@name='Body']//xsd:element[@name='detailsResponse']">
    <annox:annotate target="field">
    <annox:annotate annox:class="javax.xml.bind.annotation.XmlElement" 
        name="detailsResponse" 
        namespace="http://abc.com/ServiceSetupV001"/>
    </annox:annotate>            
</jaxb:bindings>        

<jaxb:bindings node="//xsd:complexType[@name='DetailsRequest']//xsd:element[@name='requestHeader']">
    <annox:annotate target="field">
    <annox:annotate annox:class="javax.xml.bind.annotation.XmlElement" 
        name="requestHeader" 
        namespace="http://abc.com/xmlschema/osa"/>
    </annox:annotate>            
<jaxb:bindings node="//xsd:complexType[@name='DetailsResponse']//xsd:element[@name='responseHeader']">
    <annox:annotate target="field">
    <annox:annotate annox:class="javax.xml.bind.annotation.XmlElement" 
        name="responseHeader" 
        namespace="http://abc.com/xmlschema/osa"/>
    </annox:annotate>            
</jaxb:bindings>

Generated classes have proper namespaces annotations

@XmlElement(name = "detailsRequest", namespace = "http://abc.com/ServiceSetupV001")
protected DetailsRequest detailsRequest;

@XmlElement(name = "detailsResponse", namespace = "http://abc.com/ServiceSetupV001")
protected DetailsResponse detailsResponse;

But now, the marshalled XML does not have values

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope"
xmlns:osa="http://abc.com/xmlschema/osa"
xmlns:svc="http://abc.com/ServiceSetupV001">
    <soapenv:Body>
        <svc:detailsResponse/>
    </soapenv:Body>
</soapenv:Envelope>
pfl
  • 51
  • 1
  • 4