I need to send a stream of XML from a third party to a SAS stored process (which I deployed as a web service) and return some XML.
I believe I am very close as I have sent XML with parameters to a webservice with a correct response. For example I created addfloats webservice and sent the following data
<addfloats xmlns="http://tempuri.org/addfloats">
<parameters>
<num1>2</num1>
<num2>4</num2>
</parameters>
</addfloats>
with a post request to https://mysite.com:port/SASBIWS/rest/addfloats which results in a prefect response.
I desire to stream in data to a web service named xmlwebout. Here is the underlying stored process
%put &tablename;
libname _WEBOUT xml xmlmeta = &_XMLSCHEMA;
libname instream xml;
proc means data=instream.&tablename;
output out=_WEBOUT.mean;
run;
libname _WEBOUT clear;
libname instream clear;
In the making of the stored process I create an input parameter and input data source (named instream) and post the following data
<xmlwebout xmlns="http://tempuri.org/xmlwebout">
<Parameter name="tablename">InData</Parameter>
<Stream name="instream">
<Table>
<InData>
<Column1>1</Column1>
<Column2>20</Column2>
<Column3>99</Column3>
</InData>
<InData>
<Column1>50</Column1>
<Column2>200</Column2>
<Column3>9999</Column3>
</InData>
<InData>
<Column1>100</Column1>
<Column2>2000</Column2>
<Column3>1000000</Column3>
</InData>
</Table>
</Stream>
</xmlwebout>
When I post this data I get the following error:
HTTP Status 500 - Request processing failed; nested exception is com.sas.web.services.WSException: Expected stream 'instream' was not specified.
This example is laid out in the BI web services developer's guide. The difference between my version and the developer's guide is that I've deployed it as a web service and am using XML and not SOAP.
https://support.sas.com/documentation/cdl/en/wbsvcdg/64883/PDF/default/wbsvcdg.pdf
I found a solution after literally 40 hours of hardship and heartache and no solution from tech support.
Unfortunately the documentation is sorely lacking of concrete examples of sending streams of data through plain XML. I was initially trying to just insert the plain XML part of the lone example SOAP request in the XMLA part of the documentation but my stream 'instream' was unable to be located.
The key to the solution was to look at the wsdl file (just append ?wsdl to the endpoint. ex: https://mycompany.com:port/SASBIWS/services/path/to/process/process_name?wsdl) I had gotten a simple addint stored process to return successfully and noticed that in my new stored process that the wsdl did not match the example in the developers guide. Here is the pertinent part of the wsdl for the stored process that streamed data.
<xsd:complexType name="upload_stream5Streams"> <xsd:sequence> <xsd:element name="instream"> <xsd:complexType> <xsd:sequence> <xsd:element name="Value"> <xsd:complexType> <xsd:sequence>
I needed separate elements for streams, instream, and Value, which is absolutely nowhere across the internet as far as I know.
Here is the complete XML
<upload_stream5> <streams> <instream> <Value> <Table> <InData > <Column1>1</Column1> <Column2>20</Column2> <Column3>99</Column3> </InData> <InData> <Column1>50</Column1> <Column2>200</Column2> <Column3>9999</Column3> </InData> <InData> <Column1>100</Column1> <Column2>2000</Column2> <Column3>1000000</Column3> </InData> </Table> </Value> </instream> </streams> </upload_stream5>
And here is the actual stored process sas code. Its a bit different than the developer's example because there is no _XMLSCHEMA macro variable. (tablename is defaulted to InData but you can pass this with XML as well using <parameters> and <parameter_name> tags)
%put &tablename; libname otstream xml xmlmeta = SchemaData; libname instream xml; proc means data=instream.&tablename; output out=otstream.mean; run; libname otstream clear; libname instream clear;
Stil no luck. If anybody has successfully completed the example from the developers guide (https://support.sas.com/documentation/cdl/en/wbsvcdg/64883/PDF/default/wbsvcdg.pdf) starting on page 19 (sample proc means) could you please post your exact XML here and the post request you used to generate the expected output.
Can I offer a bounty for this? I would pay quite a bit to have this.
I found a solution after literally 40 hours of hardship and heartache and no solution from tech support.
Unfortunately the documentation is sorely lacking of concrete examples of sending streams of data through plain XML. I was initially trying to just insert the plain XML part of the lone example SOAP request in the XMLA part of the documentation but my stream 'instream' was unable to be located.
The key to the solution was to look at the wsdl file (just append ?wsdl to the endpoint. ex: https://mycompany.com:port/SASBIWS/services/path/to/process/process_name?wsdl) I had gotten a simple addint stored process to return successfully and noticed that in my new stored process that the wsdl did not match the example in the developers guide. Here is the pertinent part of the wsdl for the stored process that streamed data.
<xsd:complexType name="upload_stream5Streams"> <xsd:sequence> <xsd:element name="instream"> <xsd:complexType> <xsd:sequence> <xsd:element name="Value"> <xsd:complexType> <xsd:sequence>
I needed separate elements for streams, instream, and Value, which is absolutely nowhere across the internet as far as I know.
Here is the complete XML
<upload_stream5> <streams> <instream> <Value> <Table> <InData > <Column1>1</Column1> <Column2>20</Column2> <Column3>99</Column3> </InData> <InData> <Column1>50</Column1> <Column2>200</Column2> <Column3>9999</Column3> </InData> <InData> <Column1>100</Column1> <Column2>2000</Column2> <Column3>1000000</Column3> </InData> </Table> </Value> </instream> </streams> </upload_stream5>
And here is the actual stored process sas code. Its a bit different than the developer's example because there is no _XMLSCHEMA macro variable. (tablename is defaulted to InData but you can pass this with XML as well using <parameters> and <parameter_name> tags)
%put &tablename; libname otstream xml xmlmeta = SchemaData; libname instream xml; proc means data=instream.&tablename; output out=otstream.mean; run; libname otstream clear; libname instream clear;
Just a quick thanks - The documentation is way off on this one and this was a big help.
This may help someone else -
This was my request file for Proc Soap. This STP has a couple of input parameters and a instream table.
data _null_;
file request;
input;
put _infile_;
datalines4;
<?xml version="1.0"?>
<soapenv:Envelope xmlns:m="http://tempuri.org/stp_import_models"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> >
<soapenv:Header>
</soapenv:Header>
<soapenv:Body>
<m:basicWebService>
<m:parameters>
<m:_envusersk> 49 </m:_envusersk>
<m:_getmodelnamesonly> NO </m:_getmodelnamesonly>
</m:parameters>
<m:streams>
<m:instream>
<m:Value>
<Table>
<InData>
<uuid>a43f9000-0a14-0a6f-70de-c70aca70f6d9 </uuid>
</InData>
<InData>
<uuid>0baecef9-0a14-0a6f-6ff1-c22da43b0bda</uuid>
</InData>
<InData>
<uuid>07a45659-0a14-0a6f-6ff1-c22dc46c4391</uuid>
</InData>
</Table>
</m:Value>
</m:instream>
</m:streams>
</m:basicWebService>
</soapenv:Body>
</soapenv:Envelope>
;;;;
run;
Thank you, thank you, thank you!!!!!
SAS doco is extraordinarity lacking for Web Services. The doco that is there is not clear and certainly incomplete.
I tried the same example, doesn't work for me in SAS 9.4
Build your skills. Make connections. Enjoy creative freedom. Maybe change the world. Registration is now open through August 30th. Visit the SAS Hackathon homepage.
Register today!Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.
Select SAS Training centers are offering in-person courses. View upcoming courses for: