Betlista
Betlista

Reputation: 10549

Is it possible to remove wrapper element in WS result?

I have CXF project working fine.

My WS interface is

package net.betlista.ws;

import javax.jws.WebMethod;
import javax.jws.WebService;

import org.apache.cxf.annotations.EndpointProperty;

@WebService
public interface TestWs {

    @WebMethod
    Result foo(String child);

}

implementation is

package net.betlista.ws;

import org.springframework.stereotype.Component;

@Component("testWsEndpoint")
public class TestWsImpl implements TestWs {

    @Override
    public Result foo(final String child) {
        Result res = new Result();
        res.status = "ok";
        res.data = "bar";
        return res;
    }

}

Result type class:

package net.betlista.ws;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;

//@XmlTransient - NOT working
@XmlType
//@SOAPBinding(parameterStyle=SOAPBinding.ParameterStyle.BARE) - NOT working
public class Result {

    @XmlElement
    String status;

    @XmlElement
    String data;

}

When I call the WS with request:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ws="http://ws.betlista.net/">
   <soapenv:Header/>
   <soapenv:Body>
      <ws:foo>
         <arg0>a</arg0>
      </ws:foo>
   </soapenv:Body>
</soapenv:Envelope>

the result is:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
   <soap:Body>
      <ns2:fooResponse xmlns:ns2="http://ws.betlista.net/">
         <return>
            <status>ok</status>
            <data>bar</data>
         </return>
      </ns2:fooResponse>
   </soap:Body>
</soap:Envelope>

And I'd like to skip this return element.

I'd like to have:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
   <soap:Body>
      <ns2:fooResponse xmlns:ns2="http://ws.betlista.net/">
        <status>ok</status>
        <data>bar</data>
      </ns2:fooResponse>
   </soap:Body>
</soap:Envelope>

I found this question, but if I use this, element arg is also missing from request what is something I do not want.

I tried to use this @SOAPBinding annotation for method (works as described above) and also for type Result (not working).

Requested WSDL:

<?xml version='1.0' encoding='UTF-8'?><wsdl:definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://ws.betlista.net/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:ns1="http://schemas.xmlsoap.org/soap/http" name="TestWsImplService" targetNamespace="http://ws.betlista.net/">
  <wsdl:types>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://ws.betlista.net/" elementFormDefault="unqualified" targetNamespace="http://ws.betlista.net/" version="1.0">
<xs:element name="foo" type="tns:foo"/>
<xs:element name="fooResponse" type="tns:fooResponse"/>
<xs:complexType name="foo">
    <xs:sequence>
      <xs:element minOccurs="0" name="arg0" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>
<xs:complexType name="fooResponse">
    <xs:sequence>
      <xs:element minOccurs="0" name="return" type="tns:result"/>
    </xs:sequence>
  </xs:complexType>
<xs:complexType name="result">
    <xs:sequence>
      <xs:element minOccurs="0" name="status" type="xs:string"/>
      <xs:element minOccurs="0" name="data" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>
</xs:schema>
  </wsdl:types>
  <wsdl:message name="foo">
    <wsdl:part element="tns:foo" name="parameters">
    </wsdl:part>
  </wsdl:message>
  <wsdl:message name="fooResponse">
    <wsdl:part element="tns:fooResponse" name="parameters">
    </wsdl:part>
  </wsdl:message>
  <wsdl:portType name="TestWs">
    <wsdl:operation name="foo">
      <wsdl:input message="tns:foo" name="foo">
    </wsdl:input>
      <wsdl:output message="tns:fooResponse" name="fooResponse">
    </wsdl:output>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="TestWsImplServiceSoapBinding" type="tns:TestWs">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="foo">
      <soap:operation soapAction="" style="document"/>
      <wsdl:input name="foo">
        <soap:body use="literal"/>
      </wsdl:input>
      <wsdl:output name="fooResponse">
        <soap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="TestWsImplService">
    <wsdl:port binding="tns:TestWsImplServiceSoapBinding" name="TestWsImplPort">
      <soap:address location="http://localhost:8080/tests-wicket-cxf/ws/TestWs"/>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

Upvotes: 4

Views: 7367

Answers (2)

Asiri Dias
Asiri Dias

Reputation: 29

Instead of <return>tag you can use your own tag like <result> by adding @javax.jws.WebResult(name = "result") both in your interface and implementation.

@Override
@javax.jws.WebResult(name = "result")
public Result foo(final String child) {
    Result res = new Result();
    res.status = "ok";
    res.data = "bar";
    return res;
}

Upvotes: 2

Roman Vottner
Roman Vottner

Reputation: 12829

If you want to replace arg0 with child within the SOAP request, you should add a @WebParam(name="child") annotation to your method parameter.

You can furthermore take influence on the produced style by annotating the service (the class) with @SOAPBinding(...) - which style to use depends on your needs/whises - here please refer to the link of my first comment to see the differences.

Further, please have a look at the CXF docs to see the default values for each @SOAPBinding parameter.

As you want to get rid of the return element in the response, please note that this is not WS-I complient, as only one soap::body child is allowed - but as this is your intention you should change the ParameterStyle.WRAPPED default SOAPBinding parameter to ParameterStyle.BARE. This however might change the request type too. Maybe have a look at @ResponseWrapper here. I haven't used it yet so I can't give detailed information therefore.

Upvotes: 6

Related Questions