Spring Web-Service unmarshalling无法正常工作

时间:2011-10-17 07:22:29

标签: web-services spring spring-ws

我已经像这样配置了我的WebService:

的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>

注意:拦截器在启动时加载,但如果有请求,则不会写任何内容。

我有一个类PersonServiceImpl,方法是addPersonRequest()。如果我使用org.dom4j.Element作为方法参数,一切正常;

@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;
     }
}

但是如果我改变我的方法参数,如下所示(因此应该使用spring-ws的自动编组),request.getFirstName()打印为null。 (JAXB2在类路径上)。

Person-class使用@XMLType和@XMLRootElement注释。

注意:编组工作正常。

@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;
    }
}

通过soapUI发送的测试请求(从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>

3 个答案:

答案 0 :(得分:2)

我不确定你是否还需要答案,阅读你的最新评论。我对你的请求和响应有效负载有点困惑。他们似乎被转换了。无论如何,没有Person课程就很难说。

之前我已经处理过类似的问题,并且通过添加JAXBElement&lt;&gt;来解决这些问题。在实际的课程周围。喜欢这个片段:

@PayloadRoot(
    localPart = "PutOrganisationUnitRequest", 
    namespace = DEFAULT_NAMESPACE
)
@ResponsePayload public JAXBElement<Response> putOrganisationUnits (
    @RequestPayload JAXBElement<PutOrganisationUnitRequest> organisations,
    MessageContext messageContext) {

您可以检查的另一件事是jaxb类和端点定义中的命名空间。

答案 1 :(得分:2)

你提到编组正在工作我没有看到为什么解组不起作用的原因,你是否测试了马歇尔和unmarshall in isloation?

只是为了确保soap请求是好的,你可以添加日志记录拦截器并打印来自客户端访问Web服务的实际请求,将此片段添加到您的上下文文件

  <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>

您应该看到这样的日志消息,其中包含整个soap请求,我正在从saop UI添加日志消息请求

   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>

答复更新

可能是你的肥皂要求不确定

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

        <sch:firstName>firstname</sch:firstName>

另一次更新

例外是由于您定义终点的方式,在您的soap请求( sch:AddPersonRequest )中,您发送的是addPersonRequest而非Person作为有效负载,因此更改结束点以反映该结果, @RequestPayload应该是AddPersonRequest而不是Person

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

答案 2 :(得分:1)

这个Spring Web服务实现完全是垃圾。一个脑死的白痴可以比那些“职业”更好地工作。

遵循JSON原则并按照提供的根类型恢复对象树有多难。

NO-ONE需要这些命名空间。永远不会发生相同的请求具有两个具有相同名称但来自不同名称空间的元素。但这些命名空间是无穷无尽的痛苦。

只需将XML元素与对象字段匹配即可。这只是需要的。在生成响应时从WSDL分配名称空间,如果有人在检索结束时关心它们,但在解组请求时完全忽略它们。

当我看到所有这些时,我真的想花一个月的时间做一个带有XML序列化/反序列化的NORMAL SOAP Web服务框架,它只关心元素名称和自动实例化请求/响应对象,只要XML树匹配对象树。