FitNesse: How to correctly configure XmlHttpTest to read web service results - fitnesse

I've been trying to configure XmlHttpTest in FitNesse to create a basic SOAP web service test.
I just can't quite seem to nail down the required syntax/config for the test.
My test page looks like this:
!path fixtures
!path fixtures/*.jar
!define slim.port {0}
!define TEST_SYSTEM {slim}
!define URL {http://localhost:55088/GetEmployee.asmx}
!define POST_BODY_4 { {{{
<s11:Envelope xmlns:s11="http://schemas.xmlsoap.org/soap/envelope/">
<s11:Body>
<ns1:GetEmployees xmlns:ns1="http://someorg.co.uk/">
</ns1:GetEmployees>
</s11:Body>
</s11:Envelope>
}}} }
|Import|
|nl.hsac.fitnesse.fixture|
|nl.hsac.fitnesse.fixture.slim|
|script|xml http test|
|table template |send request |
|post |${POST_BODY_4} |to |${URL} |
|check |response status|200 |
|show |response |
|$Name= |xPath |//Employee[1]/FirstName/text()|
|send request|
|Name? |
|Fred |
The web service method returns the following (visible in the show response):
<?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>
<GetEmployeesResponse xmlns="http://someorg.co.uk/">
<GetEmployeesResult>
<Employee>
<FirstName>Fred</FirstName>
<LastName>Bloggs</LastName>
<id>123</id>
<FacilityName>London</FacilityName>
</Employee>
</GetEmployeesResult>
</GetEmployeesResponse>
</soap:Body>
</soap:Envelope>
My test fails (null is the actual result). I guess I'm getting the xPath part wrong but I'm not sure why. There is no namespace prefix so I guess I don't need to use register prefix.

You do need a namespace for http://someorg.co.uk/ the fact that the response uses it as default for all elements below GetEmployeesResponse does not change the fact that it is present.
Assuming you register an 'a' namespace for 'http://someorg.co.uk/' your xPath becomes: //a:Employee[1]/a:FirstName/text() (and since there is only one Employee, and no other children of FirstName, you could also write //a:Employee/a:FirstName

Related

XML fails on  character

When requesting data from my remote server it responds with a value inside a node with the following token , making the parsing process to fail. I manually removed the guilty string and it started working.
<?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>
...
<sFName>Bradley</sFName>
<sLName>Libbra</sLName>
...
Token: 
The error raised by Savon is:
Savon::InvalidResponseError: Unable to parse response body:
 (aka INFORMATION SEPARATOR TWO) is not an allowed character in XML :
[2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
Therefore your data is not XML, and any conformant XML processor must report an error such as the one you received.
You must repair the data by removing any illegal characters by treating it as text, not XML, manually or automatically before using it with any XML libraries.
See also How to parse invalid (bad / not well-formed) XML?
My original question was around Savon ruby gem. I sorted this out by changing the default response parser to :rexml. It now parses the invalid character and does not raises an exception.
But right answer would be to parse the malformed XML or ask the provider to fix it. Thanks #kjhughes

Trying to build SOAP Request with Savon?

I am trying to hit a SOAP Service from Ruby on Rails - from SOAP UI I can hit it fine and the request XML is as below:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/" xmlns:mun="http://schemas.datacontract.org/2004/07/MyExternalService.Map" xmlns:mun1="http://schemas.datacontract.org/2004/07/MyExternalService.Common.Map">
<soapenv:Header/>
<soapenv:Body>
<tem:GetInformationsForCoordinates>
<!--Optional:-->
<tem:coordReq>
<!--Optional:-->
<mun:Coordinates>
<!--Zero or more repetitions:-->
<mun:Coordinate>
<!--Optional:-->
<mun:Id>1</mun:Id>
<!--Optional:-->
<mun:QualityIndex>90</mun:QualityIndex>
<!--Optional:-->
<mun:X>-110.5322</mun:X>
<!--Optional:-->
<mun:Y>35.2108</mun:Y>
</mun:Coordinate>
</mun:Coordinates>
</tem:coordReq>
<!--Optional:-->
<tem:analysisTypes>
<!--Zero or more repetitions:-->
<mun:AnalysisType>Additional</mun:AnalysisType>
</tem:analysisTypes>
</tem:GetInformationsForCoordinates>
</soapenv:Body>
</soapenv:Envelope>
If I copy that exact XML into a Ruby string with request = %q(XML STRING) into savon and use the method and then in Savon call the following:
response = client.call(:get_info, xml: request)
It works as expected and I get my response - however in reality I want to be just passing the parameters to Savon. So far I have tried the following:
coordinate = { Id: '1', X: -110.5322, Y: 35.2108, QualityIndex: 90 }
coordinates = {Coordinates: [coordinate] }
coordinateReq = {coordReq: {coordinates: coordinates} }
response = client.call(:get_informations_for_coordinates, message: coordinateReq)
This fails and if I look at the XML I am sending it is below:
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tns="http://tempuri.org/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<env:Body>
<tns:GetInformationsForCoordinates>
<coordReq>
<coordinates>
<coordinates>
<Id>1</Id>
<X>-110.5322</X>
<Y>35.2108</Y>
<QualityIndex>90</QualityIndex>
</coordinates>
</coordinates>
</coordReq>
</tns:GetInformationsForCoordinates>
</env:Body>
</env:Envelope>
In comparison to what is sent from SOAP UI I am missing the xmlns:mum namespace - is there anyway I can add it my request so that it is added to each parameter i.e. X, Y QualityIndex - also the tem which is similar to tns in my Savon call is added to the coordReq in SOAPUI but not in my Savon call - is there anyway I can add it?
Also I am having some difficulty in working out how to Build the analysisTypes and AnalysisType part of my request?
From the documentation:
Namespaces
If you don’t pass a namespace to Savon::Client#request, Savon will
register the target namespace (“xmlns:wsdl”) for you. If you did
pass a namespace, Savon will use it instead of the default one. For
example:
client.request :v1, :get_user
<env:Envelope
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:v1="http://v1.example.com">
<env:Body>
<v1:GetUser>
</env:Body>
</env:Envelope>
You can always set namespaces or overwrite namespaces set by Savon.
Namespaces are stored as a simple Hash.
# setting a new namespace
soap.namespaces["xmlns:g2"] = "http://g2.example.com"
# overwriting the "xmlns:wsdl" namespace
soap.namespaces["xmlns:wsdl"] = "http://ns.example.com"
Apparently, for Savon 2, setting multiple namespaces is impossible:
I found that is not possible (for now) to set multiple namespaces on
version 2 of Savon.
For now i migrate my application on Savon version 1 and it worked =)
To use multiple namespaces you put the following type of code in your client definition
...
:namespaces => {
"xmlns:v2" => "http://v2.example.com",
"xmlns:v1" => "http://v1.example.com" },
...

Namespace prefix getting changed from request to response

I developed one service using websphere application server and Rational application developer(RAD) . I am using SOAP UI to unit test my service. The service is well deployed and getting the accurate results but the problem is in the namespace prefixes.prefixes of response i am getting is different from the prefixes of request namespaces. i.e. if request having namespaces defined as common, domain etc..i am getting response having namespaces as a,b,c ..
the request is as goes here...
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tic="http://www.trrt.com/pos/TicketRemark_v1" xmlns:dom="http://www.tport.com/pos//Domain" xmlns:com="http://www.tralport.com/pos//Common">
<soapenv:Header/>
<soapenv:Body>
<tic:RetrrksRequest Version="1" >
<dom:TicketDocument TicketNbr="6000001"/>
</tic:RetrrksRequest>
</soapenv:Body>
</soapenv:Envelope>
the response is...
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<c:RetrrksResponse Version="1" TimeStamp="2012-08-23T14:15:59.000" xmlns:a="http://www.trrt.com/pos/viewtrip/schema/CommonTypes_v1" xmlns:b="http://www.trport.com/pos/viewtrip/schema/DomainTypes_v1" xmlns:c="http://www.travt.com/pos/viewtrip/schema/TicketRemarksServices_v1">
<a:Success/>
<b:TicketDocument TicketDocumentNbr="6000000000001" TotalDocQuantity="7"/>
<b:BookiID CreateDateTime="2012-08-12T12:40:00.000" PurgeDate="2013-06-20" ID="ABCDEF">
</b:BookiID>
<b:FeeRemarks>
<b:Remark Type="3000">remark text</b:Remark>
</b:FeeRemarks>
</c:RetrirksResponse>
</soapenv:Body>
</soapenv:Envelope>
This is not a problem. The namespace prefix may be arbitrary, so long as it references the correct namespace. One should not depend on the particular choice of a namespace prefix. Any code that does rely on a choice of prefix will likely suffer interoperability problems.

Bad Request in SOAPUI

I am attempting to consume a web service using Delphi 2010 and Indy. To establish a usable SOAP stream to compare to the one created by my program, I am testing in SOAPUI. I am using a SOAP stream provided by the web service provider which also matches the SOAP stream specified in the WSDL file. I am getting an HTTP 400 (bad request) error from the service.
From what I can find online, it appears that receiving an HTTP 400 error indicates that your SOAP request is malformed and can not be read by the web service. I have tested my SOAP stream using XMLPad and the XML seems to be well formed. I suppose this may mean that something does not match its schema requirement. I will first check the schema description for the password in case that is expected to not be sent as plain text. What else should I be checking to eliminate an HTTP 400 error?
Here is my request (less username and password) in case it helps:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
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"
xmlns:xop="http://www.w3.org/2004/08/xop/include"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://wwww3.org/2001/XMLSchema-instance">
<soap:Header>
<wsa:Action>http://edd.ca.gov/SendTransmission</wsa:Action>
<wsa:MessageID>urn:uuid:5aa788dc-86e1-448b-b085-2d2743cf9f26</wsa:MessageID>
<wsa:ReplyTo>
<wsa:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:Address>
</wsa:ReplyTo>
<wsa:To>http://fsettestversion.edd.ca.gov/fsetproxy/fsetservice.asmx</wsa:To>
<wsse:Security soap:mustUnderstand="1">
<wsse:UsernameToken wsu:Id="UsernameToken">
<wsse:Username>#USERNAME#</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">#PASSWORD#/wsse:Password>
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">O5QWht1bslLCX6KnlEypAA==</wsse:Nonce>
<wsu:Created>2012-02-29T22:32:38.250Z</wsu:Created>
</wsse:UsernameToken>
<wsu:Timestamp wsu:Id="Timestamp-805a7373-335c-43b6-ba21-6596c4848dbf">
<wsu:Created>2012-02-22T15:41:42Z</wsu:Created>
<wsu:Expires>2012-02-22T15:46:42Z</wsu:Expires>
</wsu:Timestamp>
</wsse:Security>
</soap:Header>
<soap:Body>
<SendTransmission xmlns="http://edd.ca.gov/">
<SendTransmissionRequest xmlns="http://www.irs.gov/a2a/mef/MeFTransmitterServiceWse.xsd">
<TransmissionDataList>
<Count>1</Count>
<TransmissionData>
<TransmissionId>123456789</TransmissionId>
<ElectronicPostmark>2012-02-22T07:41:42.2502206-08:00</ElectronicPostmark>
</TransmissionData>
</TransmissionDataList>
</SendTransmissionRequest>
<fileBytes>
<xop:Include href="cid:1.634654933022658454#example.org"/>
</fileBytes>
</SendTransmission>
</soap:Body>
</soap:Envelope>
There may be something else, but at the moment, I am suspicious of the wsse:UsernameToken. I downloaded the document at http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0.pdf and read it last night. It's written in fairly plain language and I feel like I understand what it is saying but it leaves me with a smaller question than the one I asked originally. This document proposes that you can use a plain text password in this format:
<S11:Envelope xmlns:S11="..." xmlns:wsse="...">
<S11:Header>
...
<wsse:Security>
<wsse:UsernameToken>
<wsse:Username>Zoe</wsse:Username>
<wsse:Password>IloveDogs</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
...
</S11:Header>
...
</S11:Envelope>
Or you can use a password digest. It defines a password digest like this:
Password_Digest = Base64 ( SHA-1 ( nonce + created + password ) )
According to the reference, the format for a password digest would look like this:
<S11:Envelope xmlns:S11="..." xmlns:wsse="..." xmlns:wsu= "...">
<S11:Header>
...
<wsse:Security>
<wsse:UsernameToken>
<wsse:Username>NNK</wsse:Username>
<wsse:Password Type="...#PasswordDigest">
weYI3nXd8LjMNVksCKFV8t3rgHh3Rw==
</wsse:Password>
<wsse:Nonce>WScqanjCEAC4mQoBE07sAQ==</wsse:Nonce>
<wsu:Created>2003-07-16T01:24:32Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
...
</S11:Header>
...
</S11:Envelope>
This is not the format used in the example provided by the web service publisher. The plain text version in the reference does not use a nonce. The example message uses a nonce but calls for a plain text password. It appears to me that the use of a nonce without a password digest does not add any security to the message. It could be any random string of characters if there is no agreement for how it is to be created. Am I missing the point?
I know this must seem like a tedious undertaking, but I am hoping that by providing this here, maybe we can provide a little help to the next person coming along.
I too have come across this issue. The web service publisher (edd.ca.gov) responded by stating that the " value is required by the SOAP 1.2 standards" yet I find no valid support for that. It looks like we both are heading down the same path (FSET) and maybe we should team up and work together, two heads are better than one. I have found many mistakes within the example code and I too have yet get it to work.

Cannot call web service methods via SOAP Connection (SAVON) in Ruby on Rails. Where am i going wrong?

I seem to be getting this error message:
(a:ActionNotSupported) The message with Action 'GetServices' cannot be
processed at the receiver, due to a ContractFilter mismatch at the
EndpointDispatcher. This may be because of either a contract mismatch
(mismatched Actions between sender and receiver) or a binding/security
mismatch between the sender and the receiver. Check that sender and
receiver have the same contract and the same binding (including
security requirements, e.g. Message, Transport, None).
I assume it is something to do with the security/binding setup.
My connection uses HTTP, with basichttpbinding. I've done a lot of searching for the answer, as I always do, but am unable to fix it, and no one here has expertise on Ruby on Rails.
Help would be appreciated.
Below is my code, in Ruby on Rails, which initialises the service and then calls it. Note: I can connect to it fine. It has successfully reported the available methods. Just calling the methods seems to be the problem. I have successfully connected to online test services using the same code. And I use Savon.
def test
puts "web_service: IN"
client = Savon::Client.new do
wsdl.document = "http://hidden.co.uk/myService.svc?wsdl"
end
#response = client.request "GetServices", :xmlns => "http://tempuri.org/" do
soap.header = {}
soap.body = {
"CostCentreNo" => 1,
"filter" => 0
}
end
puts '##########################'
puts #response.to_hash;
end
Below is what my Ruby on Rails sends:
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:wsdl="http://tempuri.org/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Body>
<GetServices xmlns="http://tempuri.org/">
<CostCentreNo>1</CostCentreNo>
<filter>0</filter>
</GetServices>
</env:Body>
</env:Envelope>
This is what WCF test client sends, (which works)
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://tempuri.org/IIBCSServices/GetServices</Action>
</s:Header>
<s:Body>
<GetServices xmlns="http://tempuri.org/">
<CostCentreNo>0</CostCentreNo>
<filter>0</filter>
</GetServices>
</s:Body>
</s:Envelope>
It seems to be the way it was being called... Something so simple.
The override Stated on the SAVON Tutorial, recommended if you have an uppercase starting camelcase doesnt work. Maybe the tutorial is outdated. (Note, :wsdl IS required in my case)
So this was not working:
response = client.request :wsdl, "GetCustomerCentreDetails"
Changing it to:
response = client.request :wsdl, :get_customer_centre_details
Then obviously I need a body added to it, and header etc.
The assumption that caused me confusion : Being able to get the WSDL does not mean you are connected to the webservice.
it seems you're missing this part
<Action s:mustUnderstand="1" ...>
you should insert something like the following into your request
soap.header = {"Action" =>
{'env:mustUnderstand' =>
'http://tempuri.org/IIBCSServices/GetServices',
attributes! => { 'mustUnderstand' => "1", 'xmlns' => "..." }
}

Resources