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!
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>
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With