Calling Webservice method - ruby-on-rails

I have this method on a web service I'm consuming, using SAVON 3 on Rails 3 web app
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/" xmlns:gpa="http://schemas.datacontract.org/2004/07/Gpa.Comercio.Servicos.Contracts.DTO">
<soapenv:Header/>
<soapenv:Body>
<tem:CalcularCarrinho>
<!--Optional:-->
<tem:carrinho>
<!--Optional:-->
<gpa:CEP>parameter here</gpa:CEP>
<!--Optional:-->
<gpa:CNPJ>parameter here</gpa:CNPJ>
<!--Optional:-->
<gpa:IdCampanha> parameter here </gpa:IdCampanha>
<!--Optional:-->
<gpa:Produtos>
<!--Zero or more repetitions:-->
<gpa:DadosListaProdutoCarrinhoDTO>
<!--Optional:-->
<gpa:Codigo> parameter here </gpa:Codigo>
<!--Optional:-->
<gpa:Quantidade>parameter here</gpa:Quantidade>
</gpa:DadosListaProdutoCarrinhoDTO>
</gpa:Produtos>
</tem:carrinho>
</tem:CalcularCarrinho>
</soapenv:Body>
</soapenv:Envelope>
How should I make a call to this method, considering that the "Produtos" parameter is an array?
I tried:
client.call(:calcular_carrinho){message(id_campanha: 2543, cnpj: '93.528.261/0001-60', cep: '04080013', produtos: ['379457', 1])}
P.S: I made tests with soapUI and the service is working...

I solve this question!
The call to this method:
client = Savon.client(wsdl: "webserviceadress?wsdl")
message = { :carrinho => {cep: '04080013',cnpj: '93.528.261/0001-60', id_campanha: 2543, :produtos => {:dados_lista_produto_carrinho_dto => {codigo: '379457', quantidade: 1}}}}
calc_carrinho = client.call(:method_name, message: message)

According to your question statement I assume you want to use version 3 of gem Savon. The syntax interface for Savon 3 is different from that used in 2.x.
You need to create a Savon-Object first and then create an operation with the corresponding Service/Port data.
client = Savon.new('http://link_to_your_wsdl_here')
operation = client.operation('ServiceName', 'Port', 'custom_action_here')
operation.body = { message: {} }
You can fire up the request by operation.call then.
Since the documentation for Savon 3 is sparse due to its development state I don't know how reliable the above code is. I would be happy seeing someone correcting me if it is not the right way.

Related

savon (SOAP:Server) No handlers could be found for unmarshalling the SOAP body payload

Objective
Build Soap call via savon v2
What I tried :
my soap call RQ , this is what given in the documentation
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="http://www.opentravel.org/OTA/2003/05">
<soapenv:Header/>
<soapenv:Body>
<OTA_AirLowFareSearchRQ TimeStamp="2012-04-18T07:30:42.663Z" Target="Production" Version="1.0" PrimaryLangID="en" AltLangID="en" RetransmissionIndicator="false" xmlns="http://www.opentravel.org/OTA/2003/05">
<POS>
<Source ISOCountry="ZA" ISOCurrency="ZAR" DisplayCurrency="ZAR" DisplayRate="1.0" FirstDepartPoint="CPT" FinalDestinationPoint="JNB">
<RequestorID Type="Company" ID="website" ID_Context="ts" TSAffiliateID="<AFFILIATE_ID>" MessagePassword="<AFFILIATE_PASSWORD>">
<CompanyName><AFFILIATE_ID></CompanyName>
</RequestorID>
</Source>
</POS>
<OriginDestinationInformation RefNumber="0">
<DepartureDateTime>2012-07-26T00:00:00CAT</DepartureDateTime>
<OriginLocation LocationCode="CPT" CodeContext="iata"/>
<DestinationLocation LocationCode="JNB" CodeContext="iata"/>
</OriginDestinationInformation>
<OriginDestinationInformation RefNumber="1">
<DepartureDateTime>2012-07-29T00:00:00CAT</DepartureDateTime>
<OriginLocation LocationCode="JNB" CodeContext="iata"/>
<DestinationLocation LocationCode="CPT" CodeContext="iata"/>
</OriginDestinationInformation>
<TravelPreferences>
<FlightTypePref FlightType="Nonstop" DirectAndNonStopOnlyInd="true"/> <!-- This line is optional – include to filter direct flights only -->
<CabinPref Cabin="Economy"/>
</TravelPreferences>
<TravelerInfoSummary>
<AirTravelerAvail>
<PassengerTypeQuantity Code="7" Quantity="0"/>
<PassengerTypeQuantity Code="8" Quantity="0"/>
<PassengerTypeQuantity Code="9" Quantity="0"/>
<PassengerTypeQuantity Code="10" Quantity="1"/>
</AirTravelerAvail>
</TravelerInfoSummary>
</OTA_AirLowFareSearchRQ>
</soapenv:Body>
</soapenv:Envelope>
my Target Url : eg: http://www.example.com?wsdl
operation name : search
#client = Savon.client(wsdl: ' http://www.example.com?wsdl')
#client.call(:search, message: { 'RefNumber' => '1','DepartureDateTime'=>'2014-09-26T00:00:00CAT','ArrivalDateTime'=>'2012-10-26T00:00:00CAT','OriginLocation'=>'CPT','DestinationLocation'=>'JNB' })
what i am getting :
(SOAP:Server) No handlers could be found for unmarshalling the SOAP body payload
The Soap call i built is correct or i have to build the entire xml of Soap body ?
Any help is appreciated !!
My standard answer:
download SoapUI
build a valid SOAP request.
make sure it works
then replicate the request with Ruby/Savon
if it still doesn't work, ask again

using wslite in grails returning client - Internal Error

I have an xml that I am trying to send via wslite to my service. My service endpoint, lets call it https://development.net/InquiryService
Now when I send the following call through soapUI, I get the correct response
<soapenv:Envelope //my header information>
<soapenv:Header>
<wsec:Security>
<wsec:PartnerToken>
<wsec:PartnerId>xxxx</wsec:PartnerId>
<wsec:Password>yyyy</wsec:Password>
</wsec:PartnerToken>
</wsec:Security>
</soapenv:Header>
<soapenv:Body>
<acc:retrieveUserAccount>
<acc:SystemInfo>
<sys:ServiceContext>
<sys:transactionId>123</sys:transactionId>
<sys:sourceLogicalId>zzzz</sys:sourceLogicalId>
</sys:ServiceContext>
</acc:SystemInfo>
<acc:accessRegistration>
<acc1:userId>xxxx</acc1:userId>
</acc:accessRegistration>
</acc:retrieveUserAccount>
</soapenv:Body>
</soapenv:Envelope>
When I send the service request through grails, using
withSoap(serviceURL:"https://development.net/InquiryService"){
def response = send {
serviceRequest
}
}
I get wslite.soap.SOAPFaultException: env:Client - Internal Error
I have validated the xml is EXACTLY the same, so I'm not sure why this isn't working.
I think the issue is I need to add my wsdl somewhere, but where?
If the serviceRequest variable is a String, the following should work:
def response = send(serviceRequest)
The braces are causing it to pass a closure to send which if serviceRequest is a String you don't want to happen.

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.

Number format exception in JIRA

I am getting number format exception while trying to get the issue details by using id.
RemoteIssue ri = jira.getIssueById(JIRAtoken, string.Format(IssueKey));
here jiratoken is string. But giving exception. Any one have any idea?
I had the same problem, using the SOAP Web Service API of JIRA (4).
I solved it by using getIssue instead of getIssueById. With getIssue, JIRA expects the key like MYPROJECT-3.
Now I send a request like this, and it works :
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soap="http://soap.rpc.jira.atlassian.com">
<soapenv:Header/>
<soapenv:Body>
<soap:getIssue soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<in0 xsi:type="xsd:string">MyAuthToken</in0>
<in1 xsi:type="xsd:string">MYPROJECT-1</in1>
</soap:getIssue>
</soapenv:Body>
</soapenv:Envelope>

Resources