I have to do some support on a single-function SOAP webservice, and I am failing to understand a specific aspect of the WSDL file & the resulting SOAP request as generated by SoapUI.
The WSDL for this service specifies a targetNamespace in the definitions part (targetNamespace="tetra-river-common-types/trafficinfo").
If I load the WSDL file into SoapUI, it reads everything perfectly fine; no issues at all with any of the definitions. The types for this service are defined in a single external schema file with the following definition in the WSDL file:
<wsdl:types>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:import namespace="tetra-river-common-types" schemaLocation="tetra-river-interface.xsd" />
</xsd:schema>
</wsdl:types>
However, after loading the WSDL file into SoapUI, and opening the auto generated request, it shows the following:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tet="tetra-river-common-types">
<soapenv:Header/>
<soapenv:Body>
<tet:TrafficInformation>
<tet:Item1>?</tet:Item1>
<!-- several other items with the tet: namespace prefixed -->
</tet:TrafficInformation>
</soapenv:Body>
</soapenv:Envelope>
My question is: how is the tet: namespace determined by SoapUI? I see no mention of it in either the WSDL file or the XSD file. I assume it takes the first 3 characters from the targetNamespace, but I am unsure.
The problem I am facing is that the webservice itself expects this exact message, but with tetra: as the namespace.
If you see the wsdl, there is an import of namespace as below:
namespace="tetra-river-common-types"
And if you see the request in the soapUI, in the very first line has the same namespace with prefix tet i.e.,
xmlns:tet="tetra-river-common-types"
Hence, the respective request elements are prefixed with tet.
It does not really matter what the prefix is as along the referring to the same namespace.
For more information on namespaces, see here
Related
I'm trying to use JMeter to invoke a RPC/SOAP Web service and when I invoke the service my namespaces are mangled from the actual values to NS1.
<?xml version="1.0" encoding="UTF-8"?>
<wpc:invoke xmlns:wpc="http://wpc.ibm.com">
<wpc:envelope communicationVersion="5.3">
<wpc:WPCResponseType>asynchronous</wpc:WPCResponseType>
<wpc:wpcHeader>
<wpc:companyName>mycompany</wpc:companyName>
<wpc:wpsUserID>me</wpc:wpsUserID>
<wpc:wpcUserID>wpcUsername</wpc:wpcUserID>
<wpc:password />
<wpc:messageIdentifier>9E2FA100-BE54-11E5-8A91-BF48E24665E0</wpc:messageIdentifier>
<wpc:timestamp>2016-01-18</wpc:timestamp>
<wpc:supplierId><![CDATA[0Z188]]></wpc:supplierId>
<wpc:localeForDisplay>en_US</wpc:localeForDisplay>
<wpc:localeRestriction>en_US</wpc:localeRestriction>
</wpc:wpcHeader>
<wpc:wpcBody>
<wpc:wpcCommand mode="ASYNC" type="UPLOAD">
<wpc:wpcCatalogName>Item Transaction Catalog</wpc:wpcCatalogName>
<wpc:wpcFileDocStorePath>test_data/upload/0003_items.csv</wpc:wpcFileDocStorePath>
<wpc:wpcUpdateOnly>false</wpc:wpcUpdateOnly>
</wpc:wpcCommand>
</wpc:wpcBody>
</wpc:envelope>
</wpc:invoke>
Changes to:
<?xml version="1.0" encoding="UTF-8"?>
<ns1:invoke xmlns:ns1="http://wpc.ibm.com">
<ns1:envelope communicationVersion="5.3">
<ns1:WPCResponseType>asynchronous</ns1:WPCResponseType>
<ns1:wpcHeader>
<ns1:companyName>mycompany</ns1:companyName>
<ns1:wpsUserID>me</ns1:wpsUserID>
<ns1:wpcUserID>wpcUsername</ns1:wpcUserID>
<ns1:password/>
<ns1:messageIdentifier>9E2FA100-BE54-11E5-8A91-BF48E24665E0</ns1:messageIdentifier>
<ns1:timestamp>2016-01-18</ns1:timestamp>
<ns1:supplierId><![CDATA[0Z188]]></ns1:supplierId>
<ns1:localeForDisplay>en_US</ns1:localeForDisplay>
<ns1:localeRestriction>en_US</ns1:localeRestriction>
</ns1:wpcHeader>
<ns1:wpcBody>
<ns1:wpcCommand mode="ASYNC" type="UPLOAD">
<ns1:wpcCatalogName>Item Transaction Catalog</ns1:wpcCatalogName>
<ns1:wpcFileDocStorePath>test_data/upload/0003_items.csv</ns1:wpcFileDocStorePath>
<ns1:wpcUpdateOnly>false</ns1:wpcUpdateOnly>
</ns1:wpcCommand>
</ns1:wpcBody>
</ns1:envelope>
</ns1:invoke>
There must be a setting in JMeter to keep the message from being transformed from my original meaningful namespace to this arbitrary namespace called NS1? When the message is received at the target endpoint it cannot parse the request because of this semantic error.
Any/all replies are appreciated!
MG
JMeter should not change anything in the request body, maybe it is an issues with your web service? Double check the request which is being sent by JMeter using a sniffer tool like Wireshark
In any case try switching to HTTP Request sampler, this is recommended way of sending web service requests (just don't forget to add HTTP Header Manager to send Content-Type and SOAPAction headers).
References:
JMeter User's Manual: Building a SOAP WebService Test Plan
Testing SOAP/REST Web Services Using JMeter
Is it required that each schema must have a unique namespace in a wsdl?
For an example consider the below WSDL snippet which does not have a namespace for the schemas.
<wsdl:types>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:import namespace="http://example.com/WSDL/service/1.0.0/" schemaLocation="GetFilterValuesRequest.xsd"/>
</xsd:schema>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:import namespace="http://example.com/WSDL/service/1.0.0/" schemaLocation="GetFilterValuesReply.xsd"/>
</xsd:schema>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:import namespace="http://example.com/WSDL/service/1.0.0/" schemaLocation="IRequest.xsd"/>
</xsd:schema>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:import namespace="http://example.com/WSDL/service/1.0.0/" schemaLocation="IReply.xsd"/>
</xsd:schema>
</wsdl:types>
The reason I am asking is because, I am using node-soap library for writing a WSDL service, and the library service does not work when there are either conflicting namespaces in schema or no namespaces at all.
It gives an error saying Cannot read property 'input' of undefined, when the SOAP request is sent, as it builds a map of schemas by their namespace and then later fails to find unique schema for a given request.
I do not want to go in much details of error or its fix, but, wanted to understand that is it something required for a WSDL to be a valid one?
Yes namespaces are required for a SOAP server to function properly with most clients.
Your schemas are all in the same namespace, so if you have data structures defined with the same name, this will be a problem.
Namespaces in XML are just like namespaces in programming languages. They prevent datatypes of the same name from colliding with each other.
Note that the namespace does not have to be a URL. That is just a convention. It can be anything, it just needs to be unique.
I apologize in advance if this post feels too long. But 1) this is my first post ever and 2) I have really been over the river and through the woods trying to figure this out.
The Add Service Reference feature in Visual Studio 2012 produces a proxy that (apparently) generates invalid SOAP messages. I suspect it has to do with serialization or how the proxy types are decorated but I cannot seem to figure it out. Help is much appreciated.
Detail 1. My environment is Visual Studio 2012 and I have created a .NET 4.5 class library with a service reference to https://sandbox-api.bancbox.com/v1/BBXPort?wsdl. I'm attempting to call the getClient() function; which is defined here. (http://www.bancbox.com/api/view/45)
The code looks like this:
public void GetClient()
{
// create an instance of the service reference proxy class
var bbx=newBBXClient();
bbx.ChannelFactory.Endpoint.Behaviors.Remove<System.ServiceModel.Description.ClientCredentials>();
bbx.ChannelFactory.Endpoint.Behaviors.Add(new CustomCredentials());
bbx.ClientCredentials.UserName.UserName="MY_USERNAME";
bbx.ClientCredentials.UserName.Password="MY_PASSWORD";
var customerId=newid {
subscriberReferenceId="44XX33YY"
};
var request=newgetClientRequest {
subscriberId=MY_SUBSCRIBER_ID,
clientId=customerId
};
var response=bbx.getClient(request);
}
Detail 2. I have made many successful calls into the web service via SoapUI. The successful SoapUI-produced SOAP messages look like this
<soapenv:Envelope xmlns:sch="schema.bancbox.com" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<wsse:Security soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:UsernameToken wsu:Id="UsernameToken-11">
<wsse:Username>MY_USERNAME</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">MY_PASSWORD</wsse:Password>
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">tRLo6AlRKl+/rULiKq6A6g==</wsse:Nonce>
<wsu:Created>2013-02-22T18:32:02.204Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<sch:getClient>
<getClientRequest>
<subscriberId>MY_SUBSCRIBER_ID</subscriberId>
<clientId>
<!--Optional:-->
<subscriberReferenceId>44XX33YY</subscriberReferenceId>
</clientId>
</getClientRequest>
</sch:getClient>
</soapenv:Body>
</soapenv:Envelope>
Detail 3. Per Fiddler, my failed SOAP messages look like this
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<s:Header>
<VsDebuggerCausalityData xmlns="http://schemas.microsoft.com/vstudio/diagnostics/servicemodelsink">uIDPozcAgEH0QhJHloqMBWUf3mAAAAAA5wy3enJkDUGU8IaMUCFyEjzfL+1Uez1HhAvEeFpJ+30ACQAA</VsDebuggerCausalityData>
<o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<o:UsernameToken u:Id="uuid-6e1c9f81-0651-41f7-b659-26b191bf7e13-1" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<o:Username>MY_USERNAME</o:Username>
<o:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">MY_PASSWORD</o:Password>
<o:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">hGggJkxurSkHQ3MKoeBK6AmEHNs=</o:Nonce>
<u:Created>2013-02-23T11:24:47.663Z</u:Created>
</o:UsernameToken>
</o:Security>
</s:Header>
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<getClient xmlns="schema.bancbox.com">
<getClientRequest xmlns="">
<subscriberId>MY_SUBSCRIBER_ID</subscriberId>
<clientId>
<subscriberReferenceId>XX55YY22</subscriberReferenceId>
</clientId>
</getClientRequest>
</getClient>
</s:Body>
</s:Envelope>
The SOAP message above is produced when running the GetClient() method. GetClient throws the following Exception.
System.ServiceModel.FaultException
Unmarshalling Error: cvc-elt.4.2: Cannot resolve 'getClientRequest' to a type definition for element 'getClientRequest'.
When I replay the same failing message using SoapUI, I get the following response:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<soap:Fault>
<faultcode>soap:Client</faultcode>
<faultstring>Unmarshalling Error: cvc-elt.4.2: Cannot resolve 'getClientRequest' to a type definition for element 'getClientRequest'. </faultstring>
</soap:Fault>
</soap:Body>
</soap:Envelope>
Detail 4. Based on my research, this indicates that the server on the other end is Apache CXS. It's choking on my SOAP request. So I started playing around with my SOAP message and submitting it via SoapUI.
The first glaring distance in the successful message and my fail message are these lines
SUCCESS
<sch:getClient>
<getClientRequest>
FAIL
<getClient xmlns="schema.bancbox.com">
<getClientRequest xmlns="">
So the first thing that I did was make my getClientRequest tag identical to the successful one.
<getClient xmlns="schema.bancbox.com">
<getClientRequest>
This produced the following response.
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<soap:Fault>
<faultcode>soap:Server</faultcode>
<faultstring>Found element {schema.bancbox.com}getClientRequest but could not find matching RPC/Literal part</faultstring>
</soap:Fault>
</soap:Body>
</soap:Envelope>
The next thing that I did is change the way the getClient tag is assigned a schema.
BEFORE
<getClient xmlns="schema.bancbox.com">
AFTER
<s:Envelope xmlns:bb="schema.bancbox.com" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
. . .
<bb:getClient>
<getClientRequest>
. . .
</bb:getClient>
The resultant SOAP message looks like this and it is successful.
<s:Envelope xmlns:bb="schema.bancbox.com" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<s:Header>
<VsDebuggerCausalityData xmlns="http://schemas.microsoft.com/vstudio/diagnostics/servicemodelsink">uIDPozcAgEH0QhJHloqMBWUf3mAAAAAA5wy3enJkDUGU8IaMUCFyEjzfL+1Uez1HhAvEeFpJ+30ACQAA</VsDebuggerCausalityData>
<o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<o:UsernameToken u:Id="uuid-6e1c9f81-0651-41f7-b659-26b191bf7e13-1" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<o:Username>MY_USERNAME</o:Username>
<o:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">MY_PASSWORD</o:Password>
<o:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">hGggJkxurSkHQ3MKoeBK6AmEHNs=</o:Nonce>
<u:Created>2013-02-23T11:24:47.663Z</u:Created>
</o:UsernameToken>
</o:Security>
</s:Header>
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<bb:getClient>
<getClientRequest>
<subscriberId>MY_SUBSCRIBER_ID</subscriberId>
<clientId>
<subscriberReferenceId>XX55YY22</subscriberReferenceId>
</clientId>
</getClientRequest>
</bb:getClient>
</s:Body>
</s:Envelope>
So the million dollar questions are WHY and HOW.
*WHY does the .NET proxy class serialize the SOAP message the way it does?
*HOW do I fix it? How can I may my proxy serialize into the SOAP message above? How can I force the serializer to define shorthand for the message namespace in the Envelop and then use the shorthand in the message tag?
FYI, to even get to this point I had to get past a number of WCF WSE issues and ended up implementing the solution so generously provided on Rich Stahls blog. I would post the link but apparently I don't have enough rep.
From I understand, the SOAP message that WCF produces is syntactically correct. However, Java CXF web services are very rigid with regards to the SOAP messages that they will accept.
The solution to specific problem setting aliases for xml namespace definitions in the Operation node of the SOAP messages produced by WCF proxies involves implementing a Custom Message Inspector is detailed here: Force WCF to create an xml namespace alias in client proxy.
This has completely resolved my issue.
I have a web service that follows some of the semantics of a SOAP service, but they don't provide a WSDL for said service. Instead, they provide an XSD, by which I'm reverse-engineering a WSDL out of. Things seemed to be going well, even so far as to be able to
create a WSDL
Import the XSD as part of the WSDL using the xsd:import tag
Create Java wrappers with CXF
Call the service.
Now, what I get when I call the service is an exception:
INFO: Creating Service {http://service.something.net/xml}QueryService from WSDL: file:/C:/mydocs/Work/project/my-service.wsdl
Aug 09, 2011 1:22:34 PM org.apache.cxf.phase.PhaseInterceptorChain doDefaultLogging
WARNING: Interceptor for {http://service.something.net/xml}QueryService#{http://servicesomething..../xml}QueryRequest has thrown exception, unwinding now
org.apache.cxf.binding.soap.SoapFault: "http://service.something.net/xml", the namespace on the "QueryResponse" element, is not a valid SOAP version.
The WSDL can be found in this gist, and the XSD is something I got from the vendor.
What does the error mean? What might I have done wrong in my .wsdl file generation?
Edit 1
I have manually tested the service from the vendor service, and the response seems okay to me:
<?xml version="1.0" encoding="UTF-8"?>
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
<Body>
<QueryResponse xmlns="http://service.something.net/xml">
....
</QueryResponse>
</Body>
</Envelope>
Unless I'm missing something, there should not be any reason why CXF even wants the QueryResponse to be a SOAP element, since it's namespace isn't SOAP but http://service.something.net/xml.
Where you are importing your XSD:
<wsdl:types>
<xsd:schema targetNamespace="http://service.something.net/xml">
<xsd:include schemaLocation="My-XSD.xsd" />
</xsd:schema>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:import namespace="http://service.something.net/xml"
schemaLocation="My-XSD.xsd">
</xsd:import>
</xsd:schema>
</wsdl:types>
try this instead:
<wsdl:types>
<xs:schema targetNamespace="http://service.something.net/xml"
elementFormDefault="qualified">
<xs:import schemaLocation="My-XSD.xsd"/>
</xs:schema>
</wsdl:types>
Basically you shouldn't need the include, just the import. Also you want to specify fully qualified element form.
Hope this works.
I am trying connecting PHP soap server with client written in C#.
WSDL is created in that way:
$autodiscover = new Zend_Soap_AutoDiscover('Zend_Soap_Wsdl_Strategy_ArrayOfTypeComplex');
$autodiscover->setClass('Soap_Service1');
$autodiscover->handle();
then I receive:
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://www.xx.de/soap/version/1"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap-enc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
targetNamespace="http://www.xx.de/soap/version/1"
name="Soap_Services1"
>
this 'name="Soap_Services1"' attribute parsed in C# looks ugly (Services.Soap_Services1Service). Of course name is connected with ServiceBinding and PortType. Is there any way to change it without manually hacking zend library?
Yes. Just rename your service class ;)
$autodiscover->setClass('CoolServiceName');
will give you
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://www.xx.de/soap/version/1"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap-enc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
targetNamespace="http://www.xx.de/soap/version/1"
name="CoolServiceName"
>
Since you're using the autodiscover / magical soap service creator, you can't override the names it creates as-is.
If you want to do this you can extend Zend_Soap_AutoDiscover and implement your own setClass method that uses your own name choice while generating the wsdl.
All you need to do is rename your service class (the one set by the setClass() call) and you're good.