I am using Coldfusion9 to interact with a 3rd party SOAP service with which I need to both send and receive SOAP with attachments. I am having no issue in receiving the SOAP which may or may not have binary attachments by using ToString() around the HTTP content to convert the SOAP Body into a usable string, however the service requires that I send my response back using attachments as well which is where I am coming undone. I've just never done this in ColdFusion and i'm not exactly sure how I should be presenting this to the originating service so that the SOAP body is referenced via an ID.
Below is the parsing of the incoming SOAP data with attachments:
<cfset soapData = GetHttpRequestData()>
<!--- Loop over the HTTP headers and dump the SOAP content into a variable --->
<cfsavecontent variable="soapContent">
<cfoutput>
<cfloop collection = #soapData.headers# item = "http_item">
#http_item#: #StructFind(soapData.headers, http_item)# #chr(10)##chr(13)#
</cfloop>
request_method: #soapData.method# #chr(10)##chr(13)#
server_protocol: #soapData.protocol# #chr(10)##chr(13)#
http_content --- #chr(10)##chr(13)#
#toString(soapData.content)#
</cfoutput>
</cfsavecontent>
<!--- Save file to flat file --->
<cffile action = "write"
file = "#expandPath('../')#logs/#dateFormat(now(),'dd-mm-yyyy')#_#timeFormat(now(),'HHmmss')#.txt"
output = "#soapContent#">
Now I am currently presenting the response as a full SOAP XML response containing the body as inline XML with the required STATUSCODE (see below).
<cfsavecontent variable="strResponse">
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAPENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/1999/XMLSchema" xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance">
<SOAPENV:Body>
<ns1:processResponse xmlns:ns1="urn:TripFlow" SOAPENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<STATUSLVL>00</STATUSLVL>
</ns1:processResponse>
</SOAP-ENV:Body>
</SOAPENV:Envelope>
</cfsavecontent>
<!--- Strip all whitespace between tags --->
<cfset strResponse = trim(ReReplaceNoCase(strResponse,'(>[\s]*<)','><','ALL'))>
<!--- Output the XML response to the soap service --->
<cfoutput>#strResponse#</cfoutput>
The above response is throwing an error because the SOAP service requires the response to be sent referencing the body message as an attachment exactly like follows from the documentation:
HTTP/1.1 200 OK
Date: Thu, 01 Apr 2010 09:30:25 GMT
Server: Jetty/5.1.4 (Windows XP/5.1 x86 java/1.5.0_15
Content-Type: multipart/related; boundary=soaptestserver; type="text/xml"; start="<theenvelope>"
SOAPAction: ""
Content-Length: 796
Connection: close
--soaptestserver
Content-ID: <theenvelope>
Content-Transfer-Encoding: 8bit
Content-Type: text/xml; charset=utf-8
Content-Length: 442
<?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope xmlns:SOAPENV="
http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/1999/XMLSchema"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"><SOAPENV:
Body><ns1:processResponse xmlns:ns1="urn:TripFlow" SOAPENV:
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><message
href="cid:thecontentmessage"/></ns1:processResponse></SOAP-ENV:Body></SOAPENV:
Envelope>
--soaptestserver
SOAP Interface
www.travelsolutions.com 123
travel solutions online V14.0 External System Integration
Content-ID: <thecontentmessage>
Content-Transfer-Encoding: 8bit
Content-Type: text/xml; charset=utf-8
Content-Length: 65
<?xml version="1.0" encoding="UTF-8"?><STATUSLVL>00</STATUSLVL>
--soaptestserver--
Any help would be greatly appreciate as i'm really hitting my head up against a wall on this one. Thanks!
It has been a while since I worked with ColdFusion. The last I remember, it did not provide a harness to send a SOAP attachment. I solved this issue by writing a custom CFX tag with Java that did it for me. The entire SOAP call will need to go through the tag.
The Java library you want to look at if you choose to do this is javax-ws. You also need to find out if the service call has to use MTOM.
Sorry that is not a direct solution, but it is what I had to do with CF a few versions back.
Whenever I interact with SOAP services I usually end up using something similar to this. It generally works. Notice that I have some place-holder text in there that you would need to replace with the appropriate values for your 3rd party provider.
<cfsavecontent variable="soap">
<?xml version="1.0" encoding="UTF-8" ?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/1999/XMLSchema" xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance">
<soapenv:Header/>
<soapenv:Body>
<ns1:processResponse xmlns:ns1="urn:TripFlow" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<statuslvl>00</statuslvl>
</ns1:processResponse>
</soapenv:Body>
</soapenv:Envelope>
</cfsavecontent>
<!--- Invoke web service to send message--->
<cfhttp url="http://3rd-party-url-here" method="post" timeout="10">
<cfhttpparam type="header" name="content-type" value="text/xml" />
<cfhttpparam type="header" name="SOAPAction" value="""3rd-party-method-name-here""" />
<!---<cfhttpparam type="header" name="accept-encoding" value="no-compression" /> sometimes this is needed --->
<cfhttpparam type="header" name="content-length" value="#len(soap)#" />
<cfhttpparam type="header" name="charset" value="utf-8" />
<cfhttpparam type="xml" name="message" value="#trim(soap)#" />
</cfhttp>
Related
I have created an application developped by Embarcadero XE5 C++. I use THTTPRio to consume a web service.
I have a problem with the request message generated by our application. It seems that namespaces are missing in the soap message for NS1, NS2 and NS3.
I think there's a bug in the Embarcadero.
Here the SOAP request message generated by Embarcadero:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Body>
<G110Request xmlns="urn:wsdltypes.nmvs.eu:v1.0">
<Header xmlns="urn:types.nmvs.eu:v1.0">
<Auth>
<ClientLoginId>xxx</ClientLoginId>
<UserId>xxx</UserId>
<Password>xxx</Password>
</Auth>
<UserSoftware NS1:name="xxxxx" NS2:supplier="xxxx"/>
</Header>
<Body xmlns="urn:types.nmvs.eu:v1.0">
<Product>
<ProductCode NS3:scheme="GTIN">1234567891234</ProductCode>
</Product>
</Body>
</G110Request>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Thanks for your help
I want to invoke a BPS process from CEP through SOAP method, but got an exception in BPS side.
the event output formatter such as:
<?xml version="1.0" encoding="UTF-8"?>
<eventFormatter name="output_formatter" statistics="disable"
trace="enable" xmlns="http://wso2.org/carbon/eventformatter">
<from streamName="output" version="1.0.0"/>
<mapping customMapping="enable" type="xml">
<inline>
<TestEchoRequest>
<input>{{meta_output}}</input>
</TestEchoRequest>
</inline>
</mapping>
<to eventAdaptorName="outputadapter" eventAdaptorType="soap">
<property name="headers">SOAPAction:"http://wso2.org/bps/sample/process" </property>
<property name="username">admin#carbon.super</property>
<property name="password">admin</property>
<property name="url">http://192.168.20.213:9767/services/TestEcho/</property>
</to>
</eventFormatter>
but from the view of Enter Event Formatter Details, the headers property was mismatch to the XML version, lost the bottom half of "SOAPAction".
if fire the event from Event Stream Simulator, the BPS got an exception:
TID[-1234] [BPS] [2015-08-27 09:51:08,064] ERROR {org.apache.axis2.engine.AxisEngine} - The endpoint reference (EPR) for the Operation not found is http://192.168.11.250:9767/services/TestEcho/ and the WSA Action = . If this EPR was previously reachable, please contact the server administrator.
the message sent by CEP is just like this, it seems that the SOAPAction header is lost:
POST / HTTP/1.1
Content-Type: text/xml; charset=UTF-8
SOAPAction: ""
User-Agent: Axis2
Host: 192.168.20.213:9767
Transfer-Encoding: chunked
400
<?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Header><wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" soapenv:mustUnderstand="1"><wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="Timestamp-71"><wsu:Created>2015-08-28T05:14:09.554Z</wsu:Created><wsu:Expires>2015-08-28T05:19:09.554Z</wsu:Expires></wsu:Timestamp><wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="UsernameToken-72"><wsse:Username>admin</wsse:Username><wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">admin</wsse:Password></wsse:UsernameToken></wsse:Security></soapenv:Header><soapenv:Body><event xmlns="http://wso2.org/carbon/event"><metaData><im>AAAAAAA</im></metaData></event></soapenv:Body></soapenv:Envelope>
0
Is it a bug or any suggestion ?
Above is a known issue in WSO2 CEP 3.1.0, see [1].. As a workaround can you call the soap12 endpoint of TestEcho service because SOAPAction property is optional in soap12 (Add complete url with soap12 endpoint for url property)..
example,
http://192.168.20.213:9767/services/TestEcho.TestEchoHttpsSoap12Endpoint/
[1] https://wso2.org/jira/browse/CEP-1108
I am following RegOnline's developer pages to set up an API call to our server. They offer various examples of how to handshake (PHP, C#, JS, SOAP), the last one has the poorest example of how to include an API token as part of a method call.
http://developer.regonline.com/authentication-basics/
I am trying to call their GetEvent method, and this call has to include an API token that I have generated. However, based on their SOAP example, I am left guessing as to how to include the value of token. The following is their example:
<s:complexType name="TokenHeader">
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="APIToken" type="s:string"/>
</s:sequence>
<s:anyAttribute/>
</s:complexType>
The other examples on the page have full versions that show explicitly where you could hard code the token if you had to. I will admit my knowledge of SOAP is minimal currently so perhaps I'm missing something in this example.
Here is my attempt to call the method. It only spits out a page of their documentation and a 200 OK status, which is not right.
<cfset apiToken = "xxxxx" />
<cfset eventID = "xxxxxx" />
<cfsavecontent variable="soapBody">
<cfoutput>
<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<GetEvent xmlns="http://www.regonline.com/api">
<eventID>#eventID#</eventID>
</GetEvent>
</s:Body>
</s:Envelope>
<s:complexType name="TokenHeader">
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="APIToken" type="s:string">
#apiToken#
</s:element>
</s:sequence>
<s:anyAttribute/>
</s:complexType>
</cfoutput>
</cfsavecontent>
<cfhttp url="https://www.regonline.com/api" method="get" result="theCFHTTP" redirect="true">
<cfhttpparam type="HEADER" name="Content-Type" value="text/xml; charset=utf-8">
<cfhttpparam type="HEADER" name="Accept" value="application/soap+xml, multipart/related, text/*">
<cfhttpparam type="HEADER" name="User-Agent" value="Axis/1.1">
<cfhttpparam type="HEADER" name="Cache-Control" value="no-cache">
<cfhttpparam type="HEADER" name="Pragma" value="no-cache">
<cfhttpparam type="HEADER" name="SOAPAction" value="https://www.regonline.com/api/default.asmx/GetEvent">
<cfhttpparam type="HEADER" name="Content-Length" value="#len(soapBody)#">
<cfhttpparam type="xml" name="body" value="#soapBody#">
</cfhttp>
<cfdump var="#theCFHTTP#">
Your SOAP request is in a wrong format. All of the SOAP request should be within the SOAP envelope. Here is the template created in SoapUI for the getEvent request.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:api="http://www.regonline.com/api">
<soapenv:Header>
<api:TokenHeader>
<!--Optional:-->
<api:APIToken>?</api:APIToken>
</api:TokenHeader>
</soapenv:Header>
<soapenv:Body>
<api:GetEvent>
<api:eventID>?</api:eventID>
</api:GetEvent>
</soapenv:Body>
</soapenv:Envelope>
For the call itself, you may need to try post over get, but I'm unsure about this. The one thing I think you might need to update is the SOAPAction. In my test call in SoapUI, the action in the header was http://www.regonline.com/api/GetEvent. Though it may work both ways.
That's sort of not what you want to do. With SOAP calls, you just follow the XML they provided in the documentation (https://www.regonline.com/api/default.asmx?op=GetEvent).
So in the particular case, you want to replace the CSSAVECONTENT variable soapBody to below:
<cfsavecontent variable="soapBody">
<cfoutput>
<?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:Header>
<TokenHeader xmlns="http://www.regonline.com/api">
<APIToken>#apiToken#</APIToken>
</TokenHeader>
</soap:Header>
<soap:Body>
<GetEvent xmlns="http://www.regonline.com/api">
<eventID>#eventID#</eventID>
</GetEvent>
</soap:Body>
</soap:Envelope>
</cfoutput>
</cfsavecontent>
See what that returns for you.
I have written a web service using asp.net 2.0 and a simple method "HelloWorld" to test it. Here is the soap envelope which the server receives:
<?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:Header>
<SoapAuthHeader xmlns="http://myservice.anywhere.net/">
<UserName>MyUser</UserName>
<Password>MyPassword</Password>
</SoapAuthHeader>
</soap:Header>
<soap:Body>
<HelloWorld xmlns="http://myservice.anywhere.net/">
<request>
<?xml version="1.0" encoding="utf-16"?>
<HelloWorld />
</request>
</HelloWorld>
</soap:Body>
</soap:Envelope>
My Problem is: If I send the request from a Windows Client with embedded wsdl it succeeds. If I send the request from php (or SoapUI) the request fails - the server gets no "request" string, means no content for the body.
The server receives in both cases the same soap envelope above (logged it with a trace extension).
Thanks for any help.
Harald
P.S. No matter if I use embedded XML or embedded string for the request.
Using the asmx trace I have found the problem at least with SoapUI. The requested requirement category was "text/xml" and it got "application/soap+xml". I have disabled "Soap action" and the call succeeds.
I am trying to create a web service that can be consumed with SOAP. I were exercising with normal webservices that returns any values, but know i want to check which elements in the SOAP:BODY are needed and return them with a response. I found the methods
GetSoapRequest()
and
AddSoapResponse()
in the livedoc from adobe, but don't understand how to use them.
I saw the explenation of a request and response on w3school.com
i tried to solve the Problem with the tags "cfsavecontent"
<cffunction
name="soap"
access="remote"
returntype="any"
output="false">
<cfsavecontent variable="soapMessage">
<?xml version="1.0">
<soap:Envelope
xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
<soap:Header>
</soap:Header>
<soap:Body>
<m:GetPriveResponse xmlns:m="namespace">
<m:Price>1.90</m:Price>
</m:GetPriceResponse>
</soap:Body>
</soap:Envelope>
</cfsavecontent>
but it only works, if the cffunction has returntype="any". The type "xml" occurs an error.
thx for helf
The easiest way to create a web service in CF, see
Creating components for web services http://help.adobe.com/en_US/ColdFusion/9.0/Developing/WSc3ff6d0ea77859461172e0811cbec13a13-7fe2.html
Publishing web services
http://help.adobe.com/en_US/ColdFusion/9.0/Developing/WSc3ff6d0ea77859461172e0811cbec22c24-78b7.html
I just installed the soapUI eclipse addon and called the WSDL that includes an argument of a complexe type. After testing the methods of my web service with the addon, I got the SOAP-Message I was searching all the time. Maybe it will help anybody, i just where searching long time for this solution.
<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:com="http://components.conner.somebody">
<soapenv:Header/>
<soapenv:Body>
<com:echoAddress soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<input xsi:type="com:Address">
<City xsi:type="xsd:string">?</City>
<Country xsi:type="xsd:string">?</Country>
<State xsi:type="xsd:string">?</State>
<Street xsi:type="xsd:string">?</Street>
</input>
</com:echoAddress>
</soapenv:Body>
</soapenv:Envelope>
Here is the method of the coldfusion component that will be called
<cffunction
name="echoAddress"
returnType="address"
output="false"
access="remote">
<cfargument
name="input"
type="address">
<cfreturn #arguments.input#>
</cffunction>