I have created a very basic Web Service "operation" with an operation called "hello". It works perfectly from SoapUI, but when I use Matlab 2014a to call it, the input parameters are never obtained. So hello() always returns "Hello null!" and other operations, such as addition(), always returns 0. I have followed Matlab help and I am unable to see what is going on.
What I have done is:
>> createClassFromWsdl('http://ip/WebServiceTest/operation?wsdl')
ans = operation
>> obj = operation
endpoint: 'http://ip/WebServiceTest/operation'
wsdl: 'http://ip/WebServiceTest/operation?wsdl'
>> methods(obj)
addition display hello operation
>> hello(obj, 'John')
ans =
Hello null!
This demonstrates that the Web Service is called correctly and it returns an answer, but the input parameter is not obtained.
The generated code hello.m seems fine to me:
function xReturn = hello(obj,name)
%hello(obj,name)
%
% Input:
% name = (string)
%
% Output:
% return = (string)
% Build up the argument lists.
values = { ...
name, ...
};
names = { ...
'name', ...
};
types = { ...
'{http://www.w3.org/2001/XMLSchema}string', ...
};
% Create the message, make the call, and convert the response into a variable.
soapMessage = createSoapMessage( ...
'http://webservices/', ...
'hello', ...
values,names,types,'document');
response = callSoapService( ...
obj.endpoint, ...
'', ...
soapMessage);
xReturn = parseSoapResponse(response);
I have captured network traffic to see the SOAP message and Matlab sends indeed the parameter, and the message looks fine:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<hello xmlns="http://webservices/">
<name xsi:type="xs:string">John</name>
</hello>
</soap:Body>
</soap:Envelope>
The same message from SoapUI, which returns a correct Hello John! value would look like:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://webservices/">
<soapenv:Header/>
<soapenv:Body>
<web:hello>
<!--Optional:-->
<name>John</name>
</web:hello>
</soapenv:Body>
</soapenv:Envelope>
What is it happening?
EDIT
I have also found this in the logs:
Received WS-I BP non-conformant Unquoted SoapAction HTTP header
After a lot of testing, I believe this is due to an error on old Matlab Web Service implementation, especially related to the lack of explicit namespace here <hello xmlns="http://webservices/">
From version 2014b there is a new way to call Web Services based on JDK and Apache CXF, and using the Web Services are called correctly. According to the documentation, the steps are:
Install and/or locate the Java JDK and Apache CXF programs.
Set the
paths to the JDK and CXF programs using the
matlab.wsdl.setWSDLToolPath function. Values for the paths are saved
across sessions in your user preferences, so you only need to
specify them once.
Change the MATLAB current folder to the location
where you want to use the files generated from the WSDL document.
You must have write-permission for this folder.
Run
matlab.wsdl.createWSDLClient, supplying the WSDL document location,
which can be a URL or a path to a file. The function converts the
server's APIs to a MATLAB class, and creates a class folder in the
current folder. The class folder contains methods for using the
server's APIs. The function always creates a constructor method that
has the same name as the class. You only need to run the
matlab.wsdl.createWSDLClient function once. You can access the class
anytime after that.
Create an object of the class whenever you want
to use the operations of the service.
View information about the
class to see what methods (operations) are available for you to use.
Use the methods of the object to run applications on and exchange
data with the server. MATLAB automatically converts XML data types
to MATLAB types, and vice versa.
Note: Depending on the version of Matlab used you might be required to provide a minimum or specific version of JDK
An example can be:
jdk = 'C:\Program Files\Java\jdk1.7.0_79'
cxf = 'C:\Program Files\apache\apache-cxf-2.7.18'
matlab.wsdl.setWSDLToolPath('JDK',jdk,'CXF',cxf)
matlab.wsdl.createWSDLClient('http://ip/WebServiceTest/operation?wsdl')
javaaddpath('.\+wsdl\operation.jar')
obj = operation
methods(obj)
hello(obj, 'John')
The newer version produces the following SOAP message:
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:hello xmlns:ns2="http://webservices/">
<name>John</name>
</ns2:hello>
</S:Body>
</S:Envelope>
Related
I am trying to use Postman to test an old outdated SOAP Service. The service is expecting some identities to be placed in a Handler Chain to obtain from the request. In the request it obtains the values in the following manner (with some exclusions):
import javax.annotation.Resource;
#Resource
private WebServiceContext webServiceContext;
public MyResponse methodEvent(...) {
...
String var1 = (String) context.getMessageContext().get("VAR1");
...
}
My question is when trying to use Postman how can I set this value in the request. It is not part of the normal headers or other standard entries.
It is possible before SOAP API call.
You can using the response of output to assign result variable
It can use other call output
From three different inputs
#1 Pre-request Script
#2 Global variable
#3 From other request output - I think you looking for this solution.
Demo - I will show ADD operation in Calculator SOAP
SOAP service URL
http://www.dneonline.com/calculator.asmx
Using variables input_a, input_b for adding
#1 Pre-request Script
value defined at Pre-request Script
postman.setEnvironmentVariable("input_a", 3);
postman.setEnvironmentVariable("input_b", 4);
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<Add xmlns="http://tempuri.org/">
<intA>{{input_a}}</intA>
<intB>{{input_b}}</intB>
</Add>
</soap:Body>
</soap:Envelope>
Result
#2 Global variable
Result
#3 From other request output - XML parsing and assign variable
You can using this output variable for other SOAP call's input
var xmlTree = xml2Json(responseBody);
var text = xmlTree["soap:Envelope"]["soap:Body"]["AddResponse"]["AddResult"];
console.log(text)
postman.setEnvironmentVariable("output_result", Number(text));
console.log(postman.getEnvironmentVariable("output_result"));
Print the parsing variable
Karate - How to write to the same CSV file that is being used as an input to the feature file
I have created a java function which accepts key and value pair as arguments and then writes those values to the CSV file. But I am unable to understand how to call that method in the feature file.
I am writing the javascript function as shown below wherein "Utilities" is the package and "getdataexcel" is the java class.
Background:
* def doWork = function(arg1,arg2) {
var JavaDemo = Java.type(Utilities.getdataexcel);
JavaDemo.writesingleData(arg1,arg2);
}
Below is the feature file being used:
I am not quite sure how to write back the status/Result to the same CSV file.
There is definitely something wrong with the code that i have written in the Background and Feature file section.
Scenario: soapAdd 1.1 <Scenario with passing input Parameters in Request>
Given request
"""
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<Add xmlns="http://tempuri.org/">
<intA>4</intA>
<intB>3</intB>
</Add>
</soap:Body>
</soap:Envelope>
"""
When soap action 'http://tempuri.org/Add'
Then status 200
And def resp = /Envelope/Body/AddResponse/AddResult
And match /Envelope/Body/AddResponse/AddResult == 7
* eval if (resp == 7) karate.call doWork("Result","Pass")
* print 'the value of resp is' + resp
I need to write the Results back to the same input file and i have integrated Karate with QTEST(Test management Tool) and the test cases will the executed(Passed/Failed) in QTEST based on the test results of the API.
Please read this part of the documentation (actually read all of it, it is worth it :) https://github.com/intuit/karate#js-function-argument-rules-for-call
So you can't use call if you have 2 arguments. So just do this:
* if (resp == 7) doWork("Result","Pass")
This question is very specific. If CUCM, AXL and SOAP doesn't tell you anything, there's no need to read further. Except you're interested.
Has anyone been successful at wsimporting the current WSDL file for Cisco AXL and supporting the AddTransPattern-Request? I'm talking about version 8.5 or "current" (as in Cisco UCM 8.6.2).
The import was successful, but adding a translation pattern doesn't work anymore.
I tested it by writing my SOAP request by hand, using soapUI in eclipse.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://www.cisco.com/AXL/API/8.5">
<soapenv:Header/>
<soapenv:Body>
<ns:addTransPattern sequence="?">
<transPattern>
<pattern>MYPATTERN</pattern>
<description>MYDESCRIPTION</description>
<routePartitionName>MYPARTITION</routePartitionName>
<calledPartyTransformationMask>MYDESTINATION</calledPartyTransformationMask>
<provideOutsideDialtone>false</provideOutsideDialtone>
<callingSearchSpaceName>MYCALLINGSEARCHSPACE</callingSearchSpaceName>
</transPattern>
</ns:addTransPattern>
</soapenv:Body>
The response is as follows:
<axlcode>-391</axlcode>
<axlmessage>Cannot insert a null into column (numplan.tkpatternusage).</axlmessage>
<request>addTransPattern</request>
soapUI tells me that putting usage is optional. Even if I put a value for usage, e.g. <usage>3</usage>, it tells me the value wouldn't exist even though I know it does.
Any idea is appreciated
Finally, I figured out what was wrong.
The value for <usage> needs to be a string, like in this case Translation. Then it works without any problem.
I am creating a class that will be utilizing the Fedex Web Services. I am attempting to communicate through the nusoap php class's nosoapclient() function, passing it a wsdl file. It seems Fedex requires a namespace attribute in the document root of a request.
I can use nusoap's call() function and pass it an XML string as the PARAMETER agrument which WILL WORK properly. I would rather pass an array through as the PARAMETER argument, and this is where I am running into an issue.
Is it possible to pass an array through nusoap's call() function and also include a namespace attribute in the root?
FEDEX RateRequest PHP exerpt
The following is to give an idea of what I am trying to do and not actual code
$client = new nusoapclient('RateRequest_v9.wsdl',true);
//Thought this would work but to no avail.
//$request_array is a multi-associative array with keys as required XML tag names and values as the tags inner value, did not include as it is irrelevant to this problem
//$root_attr = array('xmlns'=>'http://fedex.com/ws/rate/v9');
//$parameters = array('RateRequest'=>new soapval('RateRequest',false,$request_array,false,false,$root_attr));
$parameters = array('RateRequest'=>$request_array);
//Have tried with and without the third argument - which is the for the namespace
$response = $client->call('getRates',$parameters,'http://fedex.com/ws/rate/v9');
FEDEX RateRequest XML excerpt
The following is not the full XML (look at the RateRequest tag toward the end to see the difference)
INCORRECT FORMAT
<?xml version="1.0" encoding="ISO-8859-1"?><SOAP-ENV:Envelope xmlns:SOAP-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:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns="http://fedex.com/ws/rate/v9"><SOAP-ENV:Body><RateRequest>...</RateRequest></SOAP-ENV:Body></SOAP-ENV:Envelope>
CORRECT FORMAT
<?xml version="1.0" encoding="ISO-8859-1"?><SOAP-ENV:Envelope xmlns:SOAP-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:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns="http://fedex.com/ws/rate/v9"><SOAP-ENV:Body><RateRequest xmlns="http://fedex.com/ws/rate/v9">...</RateRequest></SOAP-ENV:Body></SOAP-ENV:Envelope>
My apologies in advance if I have missed this conversation elsewhere but I have been scouring the net and trying everything I could think of to make it work, if its not possible any suggestions? Thank you in advance for your assistance.
I'm trying to implement a client for National Rail Enquiries' SOAP Service (http://www.livedepartureboards.co.uk/ldbws/).
I stick the WSDL (http://realtime.nationalrail.co.uk/ldbws/wsdl.aspx) into http://soapclient.com/soaptest.html, but I get back the error message "Unable to handle request without a valid action parameter. Please supply a valid soap action."; what on earth should the action be?
Thanks,
Stewart
edit:
I just used soapclient.com as a quick example. In my software, I send the following XML; I still get that I'm missing an action.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://thalesgroup.com/RTTI/2008-02-20/ldb/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:ldbt2="http://thalesgroup.com/RTTI/2008-02-20/ldb/types" xmlns:ldbt="http://thalesgroup.com/RTTI/2007-10-10/ldb/types" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:ct="http://thalesgroup.com/RTTI/2007-10-10/ldb/commontypes" >
<SOAP-ENV:Body>
<ldbt2:GetDepartureBoardRequest xmlns:ldbt2="http://thalesgroup.com/RTTI/2008-02-20/ldb/" >
<ldbt2:numRows>5</ldbt2:numRows>
<ldbt2:crs>WAT</ldbt2:crs>
<ldbt2:filterCrs>GLD</ldbt2:filterCrs>
<ldbt2:filterType>to</ldbt2:filterType>
<ldbt2:timeOffset>0</ldbt2:timeOffset>
</ldbt2:GetDepartureBoardRequest>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
If its a SOAP 1.1 service then you will also need to include a SOAPAction HTTP header field:
http://www.w3.org/TR/2000/NOTE-SOAP-20000508/#_Toc478383528
I have come across exactly the same problem when trying to write a client for the National Rail SOAP service with Perl.
The problem was caused because the Perl module that I'm using 'SOAP::Lite' inserts a '#' in the SOAPAction header ...
SOAPAction: "http://thalesgroup.com/RTTI/2008-02-20/ldb/#GetDepartureBoard"
This is not interpreted correctly by .NET servers. I found this out from Example 3-19 in O'Reilly's Programming Web Services with SOAP . The solution was given below in section 3-20, namely you need to explicitly specify the format of the header with the 'on_action' method.
print SOAP::Lite
-> uri('urn:Example1')
-> on_action(sub{sprintf '%s/%s', #_ })
-> proxy('http://localhost:8080/helloworld/example1.asmx')
-> sayHello($name)
-> result . "\n\n";
My guess is that soapclient.com is using SOAP::Lite behind the scenes and so are hitting the same problem when talking to National Rail.
The solution is to write your own client so that you have control over the format of the SOAPAction header ... but you've probably done that already.
SOAPAction is required in SOAP 1.1 but can be empty ("").
See https://www.w3.org/TR/2000/NOTE-SOAP-20000508/#_Toc478383528
"The header field value of empty string ("") means that the intent of the SOAP message is provided by the HTTP Request-URI."
Try setting SOAPAction=""
When soapAction is missing in the SOAP 1.2 request (and many clients do not set it, even when it is specified in WSDL), some app servers (eg. jboss) infer the "actual" soapAction from {xsd:import namespace}+{wsdl:operation name}.
So, to make the inferred "actual" soapAction match the expected soapAction, you can set the expected soapAction to {xsd:import namespace}+{wsdl:operation name} in your WS definition (#WebMethod(action=...) for Java EE)
Eg. for a typical Java EE case, this helps (not the Stewart's case, National Rail WS has 'soapAction' set):
#WebMethod(action = "http://packagename.of.your.webservice.class.com/methodName")
If you cannot change the server, you will have to force client to fill soapAction.
I've just spent a while trying to get this to work an have a written a Ruby gem that accesses the API. You can read more on it's project page.
This is working code in Ruby:
require 'savon'
client = Savon::Client.new do
wsdl.document = "http://realtime.nationalrail.co.uk/LDBWS/wsdl.aspx"
end
response = client.request 'http://thalesgroup.com/RTTI/2012-01-13/ldb/GetDepartureBoard' do
namespaces = {
"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.xml do |xml|
xml.soap(:Envelope, namespaces) do |xml|
xml.soap(:Header) do |xml|
xml.AccessToken do |xml|
xml.TokenValue('ENTER YOUR TOKEN HERE')
end
end
xml.soap(:Body) do |xml|
xml.GetDepartureBoardRequest(xmlns: "http://thalesgroup.com/RTTI/2012-01-13/ldb/types") do |xml|
xml.numRows(10)
xml.crs("BHM")
xml.filterCrs("BHM")
xml.filterType("to")
end
end
end
end
end
p response.body
Hope that's helpful for someone!
We put together Web Services on Windows Server and were trying to connect with PHP on Apache. We got the same error. The issue ended up being different versions of the Soap client on the different servers. Matching the SOAP versions in the options on both servers solved the issue in our case.
the service have 4 operations:
1. GetServiceDetails
2. GetArrivalBoard
3. GetDepartureBoard
4. GetArrivalDepartureBoard
I have solved this problem, in Java Code, adding:
MimeHeaders headers = message.getMimeHeaders();
headers.addHeader("SOAPAction", endpointURL);