How #WebResult annotation works in JAX-WS - web-services

I'm trying to create Jax-ws WebServices. But stuck with this behaviour of JAX-WS 2.2.
I wrote the SEI class in the following way
#WebService
#SOAPBinding(parameterStyle=ParameterStyle.WRAPPED,use=Use.LITERAL,style=Style.DOCUMENT)
public class WebServicesServlet{
#WebMethod
public GetServerTimeProperty getServerTimeProperties(){
return new GetServerTimeProperty();
}
}
The generated wsdl for the above SEI is as follows:
<types>
<xsd:schema>
<xsd:import namespace="http://soapCl.test/" schemaLocation="WebServicesService_schema1.xsd"/>
</xsd:schema>
</types>
<message name="getServerTimeProperties">
<part name="parameters" element="tns:getServerTimeProperties"> </part>
</message>
<message name="getServerTimePropertiesResponse">
<part name="parameters" element="tns:getServerTimePropertiesResponse"> </part>
</message>
And the XSD
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://soapCl.test/" version="1.0" targetNamespace="http://soapCl.test/">
<xs:element name="getTimeProperties" type="tns:getServerTimeProperties"/>
<xs:element name="getTimePropertiesResponse" type="tns:getServerTimePropertiesResponse"/>
<xs:complexType name="getServerTimeProperties">
<xs:sequence/>
</xs:complexType>
**<xs:complexType name="getServerTimePropertiesResponse">**
<xs:sequence>
**<xs:element name="return" type="tns:getServerTimeProperty" minOccurs="0"/>**
</xs:sequence>
</xs:complexType>
<xs:complexType name="getServerTimeProperty">
<xs:sequence>
<xs:element name="dayLightSavingHours" type="xs:int"/>
<xs:element name="observesDayLightSavings" type="xs:boolean"/>
<xs:element name="timeZoneDisplayName" type="xs:string"/>
<xs:element name="timeZoneId" type="xs:string"/>
<xs:element name="timeZoneValue" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
SOAP Response :
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<dlwmin:getServerTimePropertiesResponse xmlns:dlwmin="http://soapCl.test/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<GetServerTimeProperty>
<dayLightSavingHours>0</dayLightSavingHours>
<observesDayLightSavings>false</observesDayLightSavings>
</GetServerTimeProperty>
</dlwmin:getServerTimePropertiesResponse>
</soapenv:Body>
</soapenv:Envelope>
I've tried to generate stubs using wsimport and this is what I could observe in the generated port class
#WebMethod
**#WebResult(targetNamespace = "")**
#RequestWrapper(localName = "getServerTimeProperties", targetNamespace = "http://soapCl.test/", className = "soapCl.test.GetServerTimeProperties")
#ResponseWrapper(localName = "getServerTimePropertiesResponse", targetNamespace = "http://soapCl.test/", className = "soapCl.test.GetServerTimePropertiesResponse")
#Action(input = "http://soapCl.test/WsSessionEJBEndPoint/getServerTimePropertiesRequest", output = "http://soapCl.test/WsSessionEJBEndPoint/getServerTimePropertiesResponse")
public GetServerTimeProperty getServerTimeProperties();
I'm curious to Know why is the WebResult name different in wsdl as "return" and in soap Response as "GetServerTimeProperty" and in generated stub as "".
Also If I dont annotate the Webmethod with #WebResult(name="GetServerTimeProperty"), my stub-generated client response is null.
If I annotate my webmethod with #WebResult(name="GetServerTimeProperty"), my soapResponse is looking as follows:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<ns2:getServerTimePropertiesResponse xmlns:ns2="http://soapCl.test/">
<return>
<dayLightSavingHours>0</dayLightSavingHours>
<observesDayLightSavings>false</observesDayLightSavings>
</return>
</ns2:getServerTimePropertiesResponse>
</soapenv:Body>
</soapenv:Envelope>
Is #WebResult(name) is mandatory in jax-ws? I'm curios to Know how this webresult annotation is making a difference in soap response and client response.
Is is that the name should be unique for every "operationName"+"Respone" element ? My wsdl has many elements with same name as
Please Suggest on this why the WebResult name returning soap response as null if we dont annotate

I Further ruled out this
1.When two webmethods methods have same #WebResult(name="A"), the soapResponse result name differs for two methods when I mention
<wsdl-file>web-inf/wsdl/WebService.wsdl</wsdl-file>
explicitly in webservices.xml.
2.The SoapResponse return name is same when I remove the <wsdl-file> entry in webservices.xml. Not sure how wsdl-file tag is making the difference.

Related

Generate wsdl from xsd using common property from common xsd file

I have to generate separate wsdl for separate client.
entry.xsd -> entry.wsdl
migration.xsd -> migration.wsdl
I am using spring boot contract frist approach for generating wsdl from xsd definition. Problem is type are same for both xsd fiels like: credential, so I want to create a common xsd file and include/import in both xsd so can reduce redundant code.
like common.xsd -> entry.xsd, migration.xsd
but getting exception or soap client giving invalid error message.
Any help, how to generate wsdl from two xsd where one is base xsd file?
It's giving, failed to update interface. InvalidFormatException from SOAP Client.
entry.sxd
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://www.test.com/idms-ws"
targetNamespace="http://www.test.com/idms-ws"
elementFormDefault="qualified">
<xs:include schemaLocation="common-element.xsd"></xs:include>
<xs:element name="updateMigrationStatusRequest">
<xs:complexType>
<xs:sequence>
<xs:element name="credential" type="tns:credential" minOccurs="0"/>
<xs:element name="referenceNo" type="xs:string" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
common-element.xsd
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="credential">
<xs:sequence>
<xs:element name="loginName" type="xs:string" minOccurs="0"/>
<xs:element name="password" type="xs:string" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:schema>

Parse soap msg with gSOAP

I have following example xml message:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header>
<to>...</to>
<from>...</from>
<id>..</id>
<relatesTo>...</relatesTo>
<action>...</action>
<version>...</version>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<customComplexElement>
<a>a_v</a>
<b>b_v</b>
<c>c_v</c>
<d>d_v</d>
<e>e_v</e>
<f>f_v</f>
</customComplexElement>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
From which I have generated a xsd file with use of one of online tools:
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" attributeFormDefault="unqualified" elementFormDefault="qualified">
<import namespace="http://schemas.xmlsoap.org/soap/envelope/" schemaLocation="http://schemas.xmlsoap.org/soap/envelope/"></import>
<xs:element name="to" type="xs:string"/>
<xs:element name="from" type="xs:string"/>
<xs:element name="id" type="xs:string"/>
<xs:element name="relatesTo" type="xs:string"/>
<xs:element name="action" type="xs:string"/>
<xs:element name="version" type="xs:string"/>
<xs:element name="customComplexElement">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:string" name="a"/>
<xs:element type="xs:string" name="b"/>
<xs:element type="xs:string" name="c"/>
<xs:element type="xs:string" name="d"/>
<xs:element type="xs:string" name="e"/>
<xs:element type="xs:string" name="f"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Then I generate the appropriate header file with wsdl2h.exe and then compile it with soapcpp2.exe compiler.
Then I try to read xml file with a function soap_read_customComplexElement() and all I get is SOAP_TAG_MISMATCH. This method seems to work if I get rid of all the soap stuff the message but I wonder if there are some functions in gSOAP to parse soap envelope, header and body?
I've had same problem. But i've just fixed it.
So, in my case i use this line of code.
struct soap *soap = soap_new1(SOAP_C_UTFSTRING | SOAP_XML_IGNORENS | SOAP_XML_TREE);
The key paramter is SOAP_XML_IGNORENS. This parameter ignore namespaces.
SOAP_XML_IGNORENS in: ignores the use of XML namespaces in input
The root of this problem is that you don't declare namespaces in your body content. That why gSoap don't know how to convert this xml.
This wouldn't be converted, because gSoap don't know what is ns4:
<ns4:ParseKeywords><ns4:Keyword>Hello</ns4:Keyword></ns4:ParseKeywords>
But if i declare namespace it will be converted
<ns4:ParseKeywords xmlns:ns4="com.idurdyev.idcommerce:ParseKeywords:1.0"><ns4:Keyword>Hello</ns4:Keyword></ns4:ParseKeywords>

Body namespace declaration in WSDL

I have a soap request declared like so:
<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2003/05/soap-envelope/"
soap:encodingStyle="http://www.w3.org/2003/05/soap-encoding"
>
<soap:Body xmlns:myResource="example.org/api/soap/myResource">
<myResource:create_resource>
<myResource:myResourcesList>
<myResource:myResource>
<myResource:title>FIRST TITLE</myResource:title>
</myResource:myResource>
<myResource:myResource>
<myResource:title>SECOND TITLE</myResource:title>
</myResource:myResource>
</myResource:myResourceList>
</myResource:create_resource>
</soap:Body>
</soap:Envelope>
I want to write a WSDL file that would handle such requests. Let's say I have declared basic definitions and models:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<wsdl:definitions
name="mySoapApi"
targetNamespace="http://example.org/api/soap/?wsdl"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsdlsoap12="http://schemas.xmlsoap.org/wsdl/soap12/"
xmlns:soap12enc="http://www.w3.org/2003/05/soap-encoding"
xmlns:soap12env="http://www.w3.org/2003/05/soap-envelope"
xmlns:tns="http://example.org/api/soap/?wsdl"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
>
<wsdl:types>
<xs:schema targetNamespace="http://example.org/api/soap/?wsdl">
<xs:complexType name="myResource">
<xs:sequence>
<xs:element name="title" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:element name="myResource" type="tns:myResource"/>
<xs:complexType name="myResourceList">
<xs:sequence>
<xs:element name="myResource" type="tns:myResource" minOccurs="0" maxOccurs="unbounded" nillable="true"/>
</xs:sequence>
</xs:complexType>
<xs:element name="myResourceList" type="tns:myResourceList"/>
<xs:complexType name="createMyResourceListResponse">
<xs:sequence>
<xs:element name="myResourceList" type="tns:myResourceList"/>
</xs:sequence>
</xs:complexType>
<xs:element name="createMyResourceListResponse" type="tns:myResourceList"/>
</xs:schema>
</wsdl:types>
I have a few problems with this.
I don't know how to handle the namespace declared in request body tag:
<soap:Body xmlns:myResource="example.org/api/soap/myResource">
<myResource:create_resource>
<myResource:myResourcesList>
<myResource:myResource>
<myResource:title>FIRST TITLE</myResource:title>
</myResource:myResource>
<myResource:myResource>
<myResource:title>SECOND TITLE</myResource:title>
</myResource:myResource>
</myResource:myResourceList>
</myResource:create_resource>
</soap:Body>
I understand, that each Type and operation should be declared in proper namespace in WSDL file. How to do that? How to write WSDL file so in response for this request I would get something like:
<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2003/05/soap-envelope/"
soap:encodingStyle="http://www.w3.org/2003/05/soap-encoding"
>
<soap:Body xmlns:myResource="example.org/api/soap/myResource">
<myResource:created_resource>
<myResource:myResourcesList>
<myResource:myResource>
<myResource:title>FIRST TITLE</myResource:title>
</myResource:myResource>
<myResource:myResource>
<myResource:title>SECOND TITLE</myResource:title>
</myResource:myResource>
</myResource:myResourceList>
</myResource:created_resource>
</soap:Body>
</soap:Envelope>
Where the main thing is that myResource:create_resource is changed to myResource:created_resource? (let's say that the logic behind creating resources is executed correctly)

SOAP server reads web method parameters as null

I have a client that connects to a SOAP server endpoint:
Endpoint.publish("http://localhost:8081/todo", new ToDoWebService());
The server offers the next simple method:
#WebService
public class ToDoWebService {
#WebMethod()
public String addToDo(String task, String context, String project, int priority) {
return "ToDo: \n "
+ "\t Task : "+task+"\n"
+ "\t Context : "+context+"\n"
+ "\t Project : "+project+"\n"
+ "\t Priority: "+priority;
}
}
This is the client:
public class Client {
public static void main(String[] args) {
ToDoWebServiceService tdwss = new ToDoWebServiceService();
ToDoWebService tdws = tdwss.getToDoWebServicePort();
System.out.println(tdws.addToDo("Task 1","My Context","My Project",9));
}
}
The thing is that the connection between client and server is succesful, but not entirely: the pass of the arguments from the client to the service is not made as expected, been this the result on the client once executed:
The server doesn't receive correctly the arguments that the client has passed with the method "addToDo()" call. It returns the string format expected but with nulls instead the arguments passed by the client. And that's what I can't figure out...
Of course, I'm pretty confident the WSDL file is well written:
<?xml version='1.0' encoding='UTF-8'?><!-- Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.2.8 svn-revision#13980. --><!-- Generated by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.2.8 svn-revision#13980. -->
<definitions xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:wsp1_2="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://todows.bigws/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://todows.bigws/" name="ToDoWebServiceService">
<types>
<xsd:schema>
<xsd:import namespace="http://todows.bigws/" schemaLocation="toDo.xsd"/>
</xsd:schema>
</types>
<message name="addToDo">
<part name="parameters" element="tns:addToDo"/>
</message>
<message name="addToDoResponse">
<part name="parameters" element="tns:addToDoResponse"/>
</message>
<portType name="ToDoWebService">
<operation name="addToDo">
<input wsam:Action="http://todows.bigws/ToDoWebService/addToDo" message="tns:addToDo"/>
<output wsam:Action="http://todows.bigws/ToDoWebService/addToDoResponse" message="tns:addToDoResponse"/>
</operation>
</portType>
<binding name="ToDoWebServicePortBinding" type="tns:ToDoWebService">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
<operation name="addToDo">
<soap:operation soapAction=""/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="ToDoWebServiceService">
<port name="ToDoWebServicePort" binding="tns:ToDoWebServicePortBinding">
<soap:address location="http://localhost:8081/todo"/>
</port>
</service>
</definitions>
As well as the schema "toDo.xsd":
<?xml version='1.0' encoding='UTF-8'?><!-- Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.2.8 svn-revision#13980. -->
<xs:schema xmlns:tns="http://todows.bigws/" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0" targetNamespace="http://todows.bigws/">
<xs:element name="addToDo" type="tns:addToDo"/>
<xs:element name="addToDoResponse" type="tns:addToDoResponse"/>
<xs:complexType name="addToDo">
<xs:sequence>
<xs:element name="task" type="xs:string" minOccurs="0"/>
<xs:element name="context" type="xs:string" minOccurs="0"/>
<xs:element name="project" type="xs:string" minOccurs="0"/>
<xs:element name="priority" type="xs:int" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="addToDoResponse">
<xs:sequence>
<xs:element name="return" type="xs:string" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
I've tried different actions in the server method, as writing the string with the parameter in a file, but the result is the same, an error cause the parameters are null. That's what I think proves that the failure is located in the way the server receive the parameters passed to the "addToDo()" method.
I've review the WSDL & schema files over and over....but I've not been able to find what make this code run wrongly. I've also tested this code with the SoapUI software and the outcome is the same.
¿Any ideas?
P.D.: Sorry about all the posted code.
In case you need the whole project: my SOAP project at GitHub
I reviewed your WSDL and XSD in your project todows-cli-ws and the problem is the WSDL and XSD files in your client project are outdated!
For example, this is the current content of the XSD file of your server.
<xs:schema xmlns:tns="http://todows.bigws/" xmlns:xs="http://www.w3.org/2001/XMLSchema"
version="1.0" targetNamespace="http://todows.bigws/">
<xs:element name="addToDo" type="tns:addToDo"/>
<xs:element name="addToDoResponse" type="tns:addToDoResponse"/>
<xs:element name="listToDo" type="tns:listToDo"/>
<xs:element name="listToDoResponse" type="tns:listToDoResponse"/>
<xs:element name="removeToDo" type="tns:removeToDo"/>
<xs:element name="removeToDoResponse" type="tns:removeToDoResponse"/>
<xs:complexType name="addToDo">
<xs:sequence>
<xs:element name="arg0" type="xs:string" minOccurs="0"/>
<xs:element name="arg1" type="xs:string" minOccurs="0"/>
<xs:element name="arg2" type="xs:string" minOccurs="0"/>
<xs:element name="arg3" type="xs:int"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="addToDoResponse">
<xs:sequence>
<xs:element name="return" type="xs:string" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="removeToDo">
<xs:sequence/>
</xs:complexType>
<xs:complexType name="removeToDoResponse">
<xs:sequence>
<xs:element name="return" type="xs:string" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="listToDo">
<xs:sequence/>
</xs:complexType>
<xs:complexType name="listToDoResponse">
<xs:sequence>
<xs:element name="return" type="xs:string" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
Note that the current name of the params are arg0, arg1, arg2 and arg3. The server expects as param names task, context, project and priority, and therefore the method is invoked with the default values (null for a String and 0 for an int).

Removing WSDL differences while migrating from Axis2 to CXF

I am migrating my webservice publishing API from AXIS2 to CXF. CXF autogenerated WSDL is not similar to Axis2 WSDL. There are given below differences. As client sits somewhere else I am not able to test if these differences will affect Axis2 generated clients. How can remove these WSDL differences using CXF?
CXF WSDL
<xs:element name="test" type="tns:test"/>
<xs:element name="testResponse" type="tns:testResponse"/>
<xs:complexType name="test">
<xs:sequence> <xs:element name="doc" type="xs:string" minOccurs="0"/> </xs:sequence>
</xs:complexType>
<xs:complexType name="testResponse">
<xs:sequence> <xs:element name="return" type="xs:string" minOccurs="0"/> </xs:sequence>
</xs:complexType>
<wsdl:portType name="TESTService">
Axis2 WSDL
<xsd:element name="test" nillable="true" type="xsd:string" />
<xsd:element name="testResponse" nillable="true" type="xsd:string" />
<wsdl:portType name="TEST">
Most likely, adding an annotation of:
#SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
would do it. You may also need to update "name" attributes of the #WebParam and #WebReturn params.
To get rif of xs:elemntName difference, remove '#WebParams' from web service input as it is accepting just a String not any complex object.
To remove wsdl:portType name difference, just added '#WebService(name) attribute. '#WebService' should be as per the specification order else cxf won't consider them in WSDL.