Search code examples
jax-wswsimport

JAX-WS SOAP request doesn't match WSDL file


I have been given a WSDL file of a SOAP web service that was written in .NET. I am building a Java client using JAX-WS (the implementation that comes with JBoss.)

I ran wsimport to generate the classes, and I am able to call the service using them. The problem is that JAX-WS appears to be interpreting the WSDL file differently than .NET does.

Here is an excerpt from the WSDL file. The element of interest is named minorgroups:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
    <xs:complexType name="traffichistoryrequest">
        <xs:sequence>
            <xs:element name="startmonth" type="xs:string" nillable="true"/>
            <xs:element name="endmonth" type="xs:string" nillable="true" minOccurs="0"/>
            <xs:element name="minorgroups" type="minorgrouplist" nillable="true" minOccurs="0"/>
        </xs:sequence>
    </xs:complexType>
    <xs:element name="traffichistoryrequest" type="traffichistoryrequest" nillable="true"/>
    <xs:complexType name="minorgrouplist">
        <xs:sequence>
            <xs:element name="minorgroupcode" type="xs:string" nillable="true" minOccurs="0" maxOccurs="unbounded"/>
        </xs:sequence>
    </xs:complexType>
    <xs:element name="minorgrouplist" type="minorgrouplist" nillable="true"/>

The JAX-WS-generated request looks like this. Note the <minorgrouplist></minorgrouplist>:

<ns2:request>
    <startmonth>2017-01</startmonth>
    <endmonth>2017-12</endmonth>
    <minorgrouplist>
        <minorgroupcode>group1</minorgroupcode>
        <minorgroupcode>group2</minorgroupcode>
    </minorgrouplist>
</ns2:request>

The .NET service is expecting <minorgroups></minorgroups> instead. That's also what I get if I generate a client from this WSDL using Visual Studio.

I can fix the JAX-WS client request by editing the last line of the WSDL snippet, renaming that global element to minorgroups. But not being that familiar with XML Schema, I don't know what function that global element is serving, let alone whether JAX-WS is correct to use its name instead of the name of the element inside of traffichistoryrequest.

So is JAX-WS behaving correctly or not?


Solution

  • Sometimes the fact that no one responds to your question is itself a hint. :-)

    JAX-WS is generating the correct classes. I was building the request incorrectly.

    The schema lists two different elements of type minorgrouplist. One is nested in traffichistoryrequest and the other is a global element.

    The generated ObjectFactory class therefore has two similar methods for creating elements of type minorgrouplist:

    @XmlElementDecl(namespace = "", name = "minorgrouplist")
    public JAXBElement<Minorgrouplist> createMinorgrouplist(Minorgrouplist value) {
        return new JAXBElement<Minorgrouplist>(_Minorgrouplist_QNAME, Minorgrouplist.class, null, value);
    }
    
    @XmlElementDecl(namespace = "", name = "minorgroups", scope = Traffichistoryrequest.class)
    public JAXBElement<Minorgrouplist> createTraffichistoryrequestMinorgroups(Minorgrouplist value) {
        return new JAXBElement<Minorgrouplist>(_Minorgroups_QNAME, Minorgrouplist.class, Traffichistoryrequest.class, value);
    }
    

    Note the differing names and scopes.

    When building the request I was calling the wrong method, creating an object with the correct Java type but in the wrong XML scope. That itself isn't an error apparently, but this particular schema also gives them different names.

    (I'm a little surprised that JAX-WS has no runtime sanity check on element scopes, instead of generating the bad request. But maybe there's a good reason for it.)