SOAP Response Schema Validation - soap

Short version:
I'm trying to write an XSD that will validate my SOAP service's responses. I feel compelled to just import http:// schemas.xmlsoap.org/soap/envelope/ instead of redefining the SOAP elements like Envelope, Head, and Body, but that xmlsoap.org schema definition of Body is too broad for my use--as soon as I import the SOAP Schema, suddenly my XSD (that I've carefully tailored to my service) validates all SOAP messages.
How should I handle the definition of the SOAP envelope, head, body in my XSD?
I suspect the problem is that I'm trying to re-use other schemas that I shouldn't be trying to re-use. Certainly, those Schemas for SOAP are intended to define what (all) SOAP messages should look like. And maybe I just need to define in my schema what I want my particular soap body to look like.
I might have just answered my own question. Maybe someone has a different solution?
Long version:
I'm having a little trouble authoring an XSD to describe the response message from one of my SOAP services.
Here's an example response from my service that I'm trying to validate:
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<helloResponse xmlns="http://justinfaulkner/wsdl/1.0">
<Message>Hello, Justin!</Message>
<Message>Your lucky numbers are: 329, 9</Message>
</helloResponse>
</soap:Body>
</soap:Envelope>
My goal is to validate responses from my service with an XSD.
So, I hand-authored an XSD that describes all the types that belong in my service's soap:Body
<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://justinfaulkner/wsdl/1.0" xmlns:tns="http://justinfaulkner/wsdl/1.0">
<xsd:complexType name="helloResponseType">
<xsd:sequence>
<xsd:element name="Message" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="helloResponse" type="tns:helloResponseType"/>
</xsd:schema>
When I tried to validate the example response (first XML snippet) with the Schema (2nd snippet) using PHP's DOMDocument::schemaValidateSource() functionality, the validator pointed out my first obvious mistake:
Element 'soap:Envelope': No matching global declaration available
"Oops, duh," I thought, "Those elements are defined in SOAP's namespace, so I need to import SOAP's XSD."
So I edited my XSD and added an import:
<xsd:import namespace="http://schemas.xmlsoap.org/soap/envelope/" schemaLocation="http://schemas.xmlsoap.org/soap/envelope/"/>
And it worked! DOMDocument::schemaValidateSource returns true when I validate the soap response with the XSD.
Then, as a sanity check, I took a different soap response XSD I had lying around:
<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://justinfaulkner/wsdl/1.0" xmlns:tns="http://justinfaulkner/wsdl/1.0">
<xsd:import namespace="http://schemas.xmlsoap.org/soap/envelope/" schemaLocation="http://schemas.xmlsoap.org/soap/envelope/"/>
<xsd:complexType name="OtherServiceResponseType">
<xsd:all>
<xsd:element name="CompletionCode" type="xsd:string"/>
<xsd:element name="ResponseMessage" type="xsd:string"/>
</xsd:all>
</xsd:complexType>
<xsd:element name="OtherServiceResponse" type="tns:OtherServiceResponseType"/>
</xsd:schema>
And I tried to validate my soap response with this completely unrelated Schema...
And the schema that, at first glance, doesn't describe this message at all, also validates the soap response.
Then I realize that XSD's Schema must be the reason the response is validating against these two different schemas. The SOAP schema I'm importing from http://schemas.xmlsoap.org/soap/envelope/ defines the Body element to be:
<xs:element name="Body" type="tns:Body" />
<xs:complexType name="Body" >
<xs:sequence>
<xs:any namespace="##any" minOccurs="0" maxOccurs="unbounded" processContents="lax" />
</xs:sequence>
<xs:anyAttribute namespace="##any" processContents="lax" >
<xs:annotation>
<xs:documentation>
Prose in the spec does not specify that attributes are allowed on the Body element
</xs:documentation>
</xs:annotation>
</xs:anyAttribute>
</xs:complexType>
Which allows the contents of the Body tag to be basically anything.
That makes sense, the purpose of XSD's XSD is to define what ALL XSDs should look like, not just mine.
So my question is, how should I build an XSD to validate these SOAP responses, reusing existing SOAP XSDs if possible?
Here's the direction I've been pursuing...
I guess I could throw xmlsoap.org's XSD schema out the window and redefine Envelope and Body myself, specifying exactly what should show up in the Body element. But I feel like I'll end up basically having a copy of all the soap elements inside my own XSD, with a slightly different Head and Body definition, and that feels like a violation of DRY.
Is there a way I can import xmlsoap.org's XSD but then override the definition of soap:Body from inside my XSD?

You should use a SOAP web service framework to do that. There are many for various programming languages listed on the wikipedia page. You write a WSDL to specify your web service API, and in which you import your XSD to define the payload formats (contract-first approach). Use the wsdl2xxx tool provided by the framework to generate the API stub. You write the API implementation code. The framework will take care of the rest (processing the SOAP messages and binding to your implementation code).

Related

WSDL contract list occuring with numbers

When I define the fields of a contract in XSD I define a list field with maxOccurs= and minOccurs>0.
Can i declare the XSD in such a way that when the request is received the fields with occurs have occurance number?
e.g.
I hope i make my self clear.
<xsd:complexType name="FieldNameType">
<xsd:sequence>
<xsd:element name="FieldName" type="FieldNameType" minOccurs="1" maxOccurs="8"/>
</xsd:sequence>
</xsd:complexType>
and when the request is send i get something like:
<FieldName_1></FieldName_1>
<FieldName_2></FieldName_2>
<FieldName_3></FieldName_3>
Thanks in advance!
I found a work-around! As i saw i can iterate through the same nodes in an XSLT file.

Creating a comment that gets displayed in generated request? WSDL SOAP xml

Im in the process of writing a wsdl file for an existing system. I'd like to add comments to generated requests.
For instance this:
<xsd:simpleType name="coffeetype">
<xsd:restriction base="xsd:integer">
<!--0=likescoffee,1=doesnotlikecoffe-->
<xsd:enumeration value="0" />
<xsd:enumeration value="1" />
</xsd:restriction>
</xsd:simpleType>
<xsd:element name="CoffeeRequestInput" nillable="false" type="tns:coffeetype" />
Should look like this in the generated request: (eg. when loading the WSDL in SoapUI)
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsdl="https://example.com/some.wsdl">
<soapenv:Header/>
<soapenv:Body>
<!--0=likescoffee,1=doesnotlikecoffe-->
<wsdl:CoffeeRequestInput>0</wsdl:CoffeeRequestInput>
</soapenv:Body>
</soapenv:Envelope>
I was able to see these comments when opening the WSDL but not when generating a request from that WSDL.
Already looked into annotations but I wasn't able to use them to create the result I wanted. (Probably an error on my side)
In short you cannot create documentation in requests as you would like to. However you can generate documentation from your WSDL that can be be very useful. By using the "xsd:documentation" tag you can add documentation directly to the elements.
For example
<xsd:simpleType name="coffeetype">
<xsd:restriction base="xsd:integer">
<xsd:enumeration value="0" />
<xsd:enumeration value="1" />
</xsd:restriction>
</xsd:simpleType>
<xsd:element name="CoffeeRequestInput" nillable="false" type="tns:coffeetype">
<xsd:annotation>
<xsd:documentation>
This object is the CoffeeRequestInput object is an Enumeration which can be used to determine is the user sending the request likes coffee or not.
Valid values for the enumeration is as follows:
0 = like coffee
1 = does not like coffee (probably a user not a programmer making a request).
Some other things that you need to document goes here.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
You can then use software such as Altova StyleForce, LiquidXML and OxyGen to generate PDF, Word documents or HTML pages which shows the SOAP services and operations with all your comments included.
If you feel up to it you can write your own XLST to transform your WSDL and XSD's into a neat HTML page which documents you interfaces as well. The best part about this is that when you update the WSDL with new operations and so on that the documentation is updated as well.

Salesforce Apex Error 'Apex type not found for element products'

I've generated Apex from a WSDL, but when invoking a callout I get the error 'Unable to parse callout response. Apex type not found for element products'. I know it has something to do when I generated the WSDL, but not sure how to fix it or why. Here are the pieces that I believe is causing the problem. I know there are other solutions and I have looked at those, but this seems different because of the type="impl:..."
<complexType name="myVData">
<sequence>
<element name="products" nillable="true" type="impl:ArrayOf_tns1_VTP"/>
</sequence>
...
<complexType name="ArrayOf_tns1_VTP">
<sequence>
<element maxOccurs="unbounded" minOccurs="0" name="item" type="tns1:VTP"/>
</sequence>
</complexType>
Anyone got a clue? Thanks!
Found the error if anyone else runs into the same problem. First I found that SOAPUI is a very helpful tool for figuring out what the response should be like.
Second, the generated Apex class from the wsdl was wrong (or wsdl, however you want to look at it) and the apex was looking for products and not item (as shown in the ArrayOf_tns1_VTP complex. I changed the name="item" to name="products" in the wsdl, regenerated the Apex and works now!

Soap does not cast response fields to into typed objects

I am a SOAP newb assigned to resurrecting an old soap interface. I've ported the soap service onto a new tomcat at a new path (and left the client unchanged). I send the request:
http://myserver:8181/soap/SoapTest?wsdl
and I get back:
<wsdl:definitions xmlns:ns1="http://webservices.mycompany.com"
xmlns:ns3="http://schemas.xmlsoap.org/wsdl/soap/http"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://www.mycompany.com/SoapTest"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
name="SoapTestService"
targetNamespace="http://www.mycompany.com/SoapTest">
<wsdl:import location="http://myserver:8181/soap/SoapTest?wsdl=SoapTest.wsdl"
namespace="http://webservices.mycompany.com"></wsdl:import>
<wsdl:binding name="SoapTestServiceSoapBinding" type="ns1:SoapTest">...</wsdl:binding>
<wsdl:service name="SoapTestService">...</wsdl:service>
</wsdl:definitions>
Seems promising. A request to the import location SoapTest?wsdl=SoapTest.wsdl returns:
<wsdl:definitions xmlns:ns1="http://webservices.mycompany.com"
xmlns:ns2="http://jaxb.dev.java.net/array" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
name="SoapTest"
targetNamespace="http://webservices.mycompany.com">
<wsdl:types>
<xs:schema xmlns:tns="http://webservices.mycompany.com"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://webservices.mycompany.com" version="1.0">
<xs:complexType name="sessionObj">
<xs:sequence>
<xs:element name="code" type="xs:int"/>
<xs:element name="id" type="xs:long"/>
<xs:element minOccurs="0" name="role" type="xs:string"/>
<xs:element minOccurs="0" name="username" type="xs:string"/>
</xs:sequence>
</xs:complexType>
... (and so on)
So the client can receive member xs name:type associations but seems not to be - or not to be applying them. That is ...
HUH.. upon review, I see xs being used as a namespace but xmlns:xsd defined?? How might this happen?
ZSI client queries (from Windows, if that makes any difference) to this interface (Linux) receive responses containing the expected data payload but then map each data item into an individual "property" - resulting in a list of generic properties.
I was expecting a list of typed members, with each property cast to its xs type (e.g. int, long, string, string for the above), right?
Thanks in advance for any clues.
Given that you've not provided enough information for the real issue at hand, I will base this on the basis of you been a newb, and therefore wrap my answer around portions I find relevant to your question.
Your main web service is described in the WSDL http://myserver:8181/soap/SoapTest?wsdl, which holds an import to a parent WSDL. This parent WSDL holds service definitions which can be bind by your main service.
Seems promising. A request to the import location
SoapTest?wsdl=SoapTest.wsdl returns:
..
From the document definition provided above, the import:
<wsdl:import location="http://myserver:8181/soap/SoapTest?wsdl=SoapTest.wsdl"
namespace="http://webservices.mycompany.com">
</wsdl:import>
injects the parent WSDL file which holds the schema defintion for all elements and attributes relevant for your service. Meaning a standalone call to it, will reveal the xs namespace definition. See here for more on schema and datatypes.
HUH.. upon review, I see xs being used as a namespace but xmlns:xsd
defined?? How might this happen?
Yes, the schema is defined not as a separate file, but as part of the WSDL. It is defined between <wsdl:types> tags:
<wsdl:types>
<xs:schema xmlns:tns="http://webservices.mycompany.com"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://webservices.mycompany.com" version="1.0">
[..]
</wsdl:types>
See here also for more on ZSI binding and stub generation.
From ZSI documentation:
If the operation invoked returns a ComplexType, typecode information must be provided in order to tell ZSI how to deserialize the response.
In order for ZSI to transparently deserialize the returned complex type into a Person instance, a module defining the class and its typecode must be appended to the ZSI.Path list. It is also possible to explicitly tell ZSI what class and typecode to use by passing the class as a parameter to the Binding.Receive() method. The first method is often preferred, particularly for publically-distributed libraries.
Code Generation from WSDL and XML Schema is the second way ZSI provides to access WSDL services. Given the path to a WSDL service, two files are generated, a 'service' file and a 'types' file, that one can then use to access the service.

Is this a standard or common encoding for a SOAP request?

I'm using a web service where the WSDL describes a single string element in each request and response.
<s:element name="SERVICE">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="SERVICERequest" type="s:string" />
</s:sequence>
</s:complexType>
</s:element>
Embedded in that string are a number of plain XML elements that have escaped tags.
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<SERVICE xmlns="https://services.transcard.com/">
<SERVICERequest>
<SERVICE_REQ>
<PARAM_1>
Value1
</PARAM_1>
<PARAM_2>
Value2
</PARAM_2>
<PARAM_3>
Value3
</PARAM_3>
</SERVICE_REQ>
</SERVICERequest>
</SERVICE>
</soap:Body>
</soap:Envelope>
This is the format of responses from the service, and is the format expected for incoming requests.
Is this common in SOAP interfaces? In practice, it causes the inner parameters to be inaccessible to the SOAP library I'm using. (soap4r) Any feedback from SOAP veterans is appreciated.
No. That's not common.
That completely disregards using an actual schema (which defines the data type being returend) and replaces it with a giant string that you're going to have to parse once you get the response.
...Terrible.