Search code examples
javaweb-servicessoapwsdljax-ws

JAX-WS null arguments


I've made a WS server from a WSDL definition (Contract first approach). I've generated the Java artifacts with wsimport and tested the service. Now I've got a problem. Some (not all) arguments of an operation requests are unmarshalled as null! The web service is SOAP based. The wsdl follow the document-literal convention. So, this is the schema imported by AbstractFDSInfo.wsdl:

<schema xmlns="http://www.w3.org/2001/XMLSchema" 
        xmlns:tns="http://www.example.com/FDSControl"
        xmlns:com="http://www.example.com/FDSCommon"
        targetNamespace="http://www.example.com/FDSControl" 
        elementFormDefault="qualified">
  <import namespace="http://www.example.com/FDSCommon" schemaLocation="FDSCommon.xsd"/>

  <complexType name="PassengerList">
    <sequence>
      <element ref="com:Passenger" minOccurs="0" maxOccurs="unbounded"/>
    </sequence>
  </complexType>

  <complexType name="FlightInstanceStatusList">
    <sequence>
      <element type="com:flightInstanceStatus" name="Status" minOccurs="0" maxOccurs="unbounded"/>
    </sequence>
  </complexType>

  <!-- other operation types here -->

  <element name="setPassengerBoarded">
    <complexType>
      <sequence>
        <element ref="com:FlightInstanceId"/>
        <element type="string" name="Passenger"/>
      </sequence>
    </complexType>
  </element>
  <element name="setPassengerBoardedResponse">
    <complexType/>
  </element>
  <element name="passengerBoardingException">
    <complexType>
        <sequence>
          <element type="token" name="Reason"/>
          <element type="string" name="Detail"/>
        </sequence>
    </complexType>
  </element>

  <!-- Other operation types here --->

And here is the FDSControlAbstract.wsdl:

<?xml version="1.0" encoding="UTF-8"?>
<definitions name="FDSControlAbstract"  
             xmlns:tns="http://www.example.com/FDSControl.wsdl"
             xmlns:con="http://www.example.com/FDSControl"
             xmlns:com="http://www.example.com/FDSCommon"
             xmlns="http://schemas.xmlsoap.org/wsdl/"  
             targetNamespace="http://www.example.com/FDSControl.wsdl">
  <types>
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <xsd:import namespace="http://www.example.com/FDSCommon" schemaLocation="FDSCommon.xsd"/>
      <xsd:import namespace="http://www.example.com/FDSControl" schemaLocation="FDSControl.xsd"/>
    </xsd:schema>
  </types>

  <message name="setPassengerBoardedRequest">
    <part element="con:setPassengerBoarded" name="Params"/>
  </message>
  <message name="setPassengerBoardedResponse">
    <part element="con:setPassengerBoardedResponse" name="Params"/>
  </message>
  <message name="passengerBoardingException">
    <part element="con:passengerBoardingException" name="Params"/>
  </message>

  <!-- other messages here -->

  <portType name="FDSBoardingPortType">

    <!-- other operations here -->

    <operation name="setPassengerBoarded">
      <documentation>
        Sets a passenger as boarded. If the passenger is already boarded, 
        or the flight instance is not in the boarding status, an exception
        is returned.
      </documentation>
      <input message="tns:setPassengerBoardedRequest"/>
      <output message="tns:setPassengerBoardedResponse"/>
      <fault message="tns:flightInstanceNotFoundException"
             name="flightInstanceNotFoundException"/>
      <fault message="tns:passengerBoardingException"
             name="passengerBoardingException"/>
      <fault message="tns:flightStatusException"
             name="flightStatusException"/>
    </operation>
  </portType>

 <!-- other port types here -->

</definitions>

Here is the FDSControl.wsdl:

<?xml version="1.0" encoding="UTF-8"?>
<definitions name="FDSControl"  
             xmlns:tns="http://www.example.com/FDSControl.wsdl"
             xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
             xmlns="http://schemas.xmlsoap.org/wsdl/"  
             targetNamespace="http://www.example.com/FDSControl.wsdl"
             elementFormDefault="qualified">
  <import namespace="http://www.example.com/FDSControl.wsdl" location="FDSControlAbstract.wsdl"/>

  <!-- other bindings here-->

  <binding name="FDSBoardingSOAP" type="tns:FDSBoardingPortType">

    <!-- other operations here -->

    <operation name="setPassengerBoarded">
      <soap:operation soapAction="http://www.example.com/FDSControl/setPassengerBoarded"/>
      <input> <soap:body use="literal"/> </input>
      <output> <soap:body use="literal"/> </output>
      <fault name="flightInstanceNotFoundException">
        <soap:fault name="flightInstanceNotFoundException" use="literal"/>
      </fault>
      <fault name="passengerBoardingException">
        <soap:fault name="passengerBoardingException" use="literal"/>
      </fault>
      <fault name="flightStatusException">
        <soap:fault name="flightStatusException" use="literal"/>
      </fault>
    </operation> 
  </binding>

  <service name="FDSBoardingSOAPService">
    <port name="FDSBoardingPortType" binding="tns:FDSBoardingSOAP">
      <soap:address location="http://localhost:7070/fdscontrol"/>
    </port>
  </service>

</definitions>

Now here is the definition of the java class implementing the web service:

@WebService(name="FDSBoarding",
        endpointInterface="it.polito.dp2.FDS.lab4.server.gen.FDSBoardingPortType",
        wsdlLocation="META-INF/FDSControl.wsdl",
        portName="FDSBoardingPortType",
        serviceName="FDSBoardingSOAPService",
        targetNamespace="http://www.example.com/FDSControl.wsdl")
})
public class FDSControlImpl implements FDSBoardingPortType {
    private FlightManager manager;

    public FDSControlImpl(FlightManager manager) {
        this.manager = manager;
    }

    //other methods here

    @Override
    public SetPassengerBoardedResponse setPassengerBoarded(SetPassengerBoarded params)
    throws FlightInstanceNotFoundException_Exception, FlightStatusException_Exception, PassengerBoardingException_Exception {
        return manager.setPassengerBoarded(params);
    }

}

You can see I kept the parameters wrapped in a single class. Now the problem is that, whenever I send a request for setPassengerBoarded(), the server returns null as params.getPassenger() Is there something wrong with my structure/definitions?


Solution

  • I was compiling two different WSDLs to the same package. I split the generated code in two packages and the problem disappeared, even though now I have duplicate classes and thus I need to convert back and forth between the these...