Search code examples
web-servicesspringspring-ws

Spring Web-Service unmarshalling not working


I have configured my WebService like this:

applicationContext:

<sws:annotation-driven />    
 <bean class="org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping" >
<property name="interceptors">
 <list>
    <bean class="org.springframework.ws.server.endpoint.interceptor.PayloadLoggingInterceptor"/>
</list>
</property>

Note: the Interceptor is loaded on startup, but doesn´t write anything, if a request is coming in.

I have a class PersonServiceImpl with the method addPersonRequest(). Everything works , if i am using org.dom4j.Element as method parameter;

@Endpoint
public class PersonServiceImpl {
     @PayloadRoot(namespace = "http://www.example.org/person/schema", localPart = "AddPersonRequest")
     @ResponsePayload
       public AddPersonRequest addPersonRequest(@RequestPayload Element element) {
        System.out.println(element.asXML());
        Person response = new Person();
        response.setId(2);
        response.setFirstName("Mad");
        response.setLastName("Mike");
        return response;
     }
}

But if i change my method parameters like shown below (so auto-marshalling of spring-ws should be used) the request.getFirstName() prints null. (JAXB2 is on classpath).

The Person-class is annotated with @XMLType and @XMLRootElement.

Note: The marshalling works fine.

@Endpoint
public class PersonServiceImpl {
     @PayloadRoot(namespace = "http://www.example.org/person/schema", localPart = "AddPersonRequest")
     @ResponsePayload
       public AddPersonRequest addPersonRequest(@RequestPayload Person request, SoapHeader header) {
        System.out.println(header.getName());
        System.out.println(request.getFirstName());
        Person response = new Person();
        response.setId(2);
        response.setFirstName("Mad");
        response.setLastName("Mike");
        return response;
     }
}

Person.java:

@XmlType
@XmlRootElement(namespace="http://www.example.org/person/schema", name="Person")
public class Person implements Serializable {

    private int id;
    private String firstName;
    private String lastName;

    @XmlElement
    public String getFirstName() {
        return firstName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    @XmlElement
    public String getLastName() {
        return lastName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    @XmlAttribute
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
}

Test-Request sent via soapUI (generated from wsdl):

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sch="http://www.example.org/person/schema"> 
<soapenv:Header/>
<soapenv:Body>

  <sch:AddPersonRequest>

     <sch:Person sch:Id="1">

        <sch:FirstName>firstname</sch:FirstName>

        <sch:LastName>lastname</sch:LastName>

     </sch:Person>

  </sch:AddPersonRequest>

</soapenv:Body>
</soapenv:Envelope>

Solution

  • You mentioned marshalling is working I don't see any reason why unmarshalling won't work, Have you tested marshall and unmarshall in isloation?

    Just to make sure the soap request is good, Can you add logging interceptor and print the actual request that is coming from the client accessing web service, Add this snippet to your context file

      <sws:interceptors>
        <bean class="org.springframework.ws.soap.server.endpoint.interceptor.SoapEnvelopeLoggingInterceptor">
            <property name="logRequest" value="true"></property>
            <property name="logResponse" value="true"></property>
        </bean>
    </sws:interceptors>
    

    You should see a log message like this that contains the entire soap request, I am adding a log message request from a saop UI to

       DEBUG [http-8080-2]:endpoint.interceptor.SoapEnvelopeLoggingInterceptor.logMessage - Request:
        <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sch="http://hoost:port/context/patient/schemas">
          <soapenv:Header/>
             <soapenv:Body>
                <sch:addRequest>
                  <sch:patient>
                      <sch:id>?</sch:id>
                         <sch:lastname>Joe</sch:lastname>
                    </sch:patient>
                 </sch:addRequest>
            </soapenv:Body>
          </soapenv:Envelope>
    

    UPDATE of answer

    It could be your soap request not sure though

            <sch:FirstName>firstname</sch:FirstName> (this should be)
    
            <sch:firstName>firstname</sch:firstName>
    

    Another update

    The exception is due to the way you defined the end point, In your soap request (sch:AddPersonRequest) you are sending a addPersonRequest not Person as payload so change the end point to reflect that, The @RequestPayload should be AddPersonRequest not Person

         @PayloadRoot(namespace = "http://www.example.org/person/schema", localPart = "AddPersonRequest")
         @ResponsePayload
          public AddPersonRequest addPersonRequest(@RequestPayload AddPersonRequest request, SoapHeader header) {