Copy link to clipboard
Copied
Hi
if api getting soap request using cfhttp like below:
<cfxml variable="mydata">
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Header />
<soapenv:Body>
<ns:service_soap_call soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<login>test</login>
<password>test</password>
</ns:service_soap_call>
</soapenv:Body>
</soapenv:Envelope>
</cfxml>
<cfhttp url="http://sm.iclp-dubai.ae/research/wsdl/MyPointsBank.cfc?wsdl" method="post" charset="utf-8" result="myresult">
type" value="text/xml">
<cfhttpparam type="header" name="SOAPAction" value="">
<cfhttpparam name="soapInput" type="xml" value="#trim(mydata)#"/>
</cfhttp>
then how to get Soap Request in application cfc.
like :
<cfif IsSOAPRequest() >
<cfset soapreq = GetSOAPRequest() />
</cfif>
I want to validate the soap xml Request before calling targeted CFC.
Any suggestion!.
Copy link to clipboard
Copied
Why would you want to do that in Application.cfc? The whole idea behind the design of IsSOAPRequest() is that it is to be used within a CFC to indicate when the CFC is called as a web service. In your case, it would be appropriate to put it in MyPointsBank.cfc instead.
Copy link to clipboard
Copied
Thanks BKBK,
I want to validate soap request before calling the targeted CFC method.
Consider this example if the soap request without the method body like below:
<cfxml variable="mydata">
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Header />
<soapenv:Body>
</soapenv:Body>
</soapenv:Envelope>
</cfxml>
then how to validate this and display proper fault code. In this case coldfusion generating a below exception:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<soapenv:Fault>
<faultcode>soapenv:Server.userException</faultcode>
<faultstring>java.lang.Exception: Body not found.</faultstring>
<detail>
<ns1:stackTrace xmlns:ns1="http://xml.apache.org/axis/">java.lang.Exception: Body not found.
at org.apache.axis.providers.java.RPCProvider.processMessage(RPCProvider.java....
but I wan to display proper fault code.
Any Idea!
Copy link to clipboard
Copied
What you show (mydata) is just an XML variable. It is not a SOAP request. A SOAP request is, for example, a CFC method whose access is 'remote'.
Copy link to clipboard
Copied
BKBK Thanks,
Please consider that CFC component is ready like below:
<cfcomponent output="no">
<cffunction name="service_soap_call" access="remote" output="no" returntype="any" >
<cfargument name="argument1">
................................
</cfcomponent>
Now I am accessing this CFC via CFHTTP or vai SoapUI like below:
<cfxml variable="mydata">
<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:wor="https://www.worldmilesafrica.com">
<soapenv:Header/>
<soapenv:Body>
</soapenv:Body>
</soapenv:Envelope>
</cfxml>
<cfhttp url="#WSDL_URL#" method="post" charset="utf-8" result="myresult">
<cfhttpparam type="header" name="content-type" value="text/xml">
<cfhttpparam type="header" name="SOAPAction" value="">
<cfhttpparam name="soapInput" type="xml" value="#trim(mydata)#"/>
</cfhttp>
<cfdump var="#myresult.FileContent#">
It will generate below exception:
<?xml version="1.0" encoding="utf-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <soapenv:Body> <soapenv:Fault> <faultcode>soapenv:Server.userException</faultcode> <faultstring>java.lang.Exception: Body not found.</faultstring>................
How can I handle this type of exception and display my customize fault code. Any idea will be very helpful..
Copy link to clipboard
Copied
You could just test whether the SOAP body is blank. If so, do a throw, returning the error message. Something like this,
<cfset var inputXML = xmlParse(arguments.soapInput)>
<cfset var soapBodyText="">
<cfset var noBodyTextError="">
<cfset soapBodyText = xmlSearch(inputXML,"//soapenv:Body/text()")[1].xmlValue>
<cfsavecontent variable="noBodyTextError"><?xml version="1.0" encoding="utf-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <soapenv:Body> <soapenv:Fault> <faultcode>soapenv:Server.userException</faultcode> <faultstring>java.lang.Exception: Body not found.</faultstring></cfsavecontent>
<cftry>
<cfif trim(soapBodyText) is "">
<cfthrow>
</cfif>
<cfcatch type="any">
<cfreturn noBodyTextError>
</cfcatch>
</cftry>
Copy link to clipboard
Copied
BKBK, You know very well all soap request directly calling CFC Component, right
If this is my CFC component then could you explain me please where I will check the soap body and how
<cfcomponent output="no">
<cffunction name="service_soap_call" access="remote" output="no" returntype="any" >
<cfargument name="argument1">
................................
</cfcomponent>
Copy link to clipboard
Copied
In the function, of course. You can tell from the use of 'var', 'arguments' and 'cfreturn'.
Copy link to clipboard
Copied
My Dear BKBK if you check request xml above, then there is no function name(cfc component function: service_soap_call) and function body. So flow will not come inside a function and code will not execute.
Please could you make simple component like below:
Webservice.cfc
<cffunction name="service_soap_call" access="remote" output="no" returntype="any" >
<cfargument name="str">
<cfreturn arguments.str>
</cffunction>
</cfcomponent>
if CFC component on your localhost then you can access web service url: http://localhost/Webservice.cfc?wsdl
then call this web service via this localhost url in your cfm with below below code:
CFhttp.cfm
<cfxml variable="mydata">
<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:wor="https://www.worldmilesafrica.com">
<soapenv:Header/>
<soapenv:Body>
</soapenv:Body>
</soapenv:Envelope>
</cfxml>
<cfhttp url="http://localhost/Webservice.cfc?wsdl" result="myresult">
<cfhttpparam type="header" name="content-type" value="text/xml">
<cfhttpparam type="header" name="SOAPAction" value="">
<cfhttpparam name="soapInput" type="xml" value="#trim(mydata)#"/>
</cfhttp>
<cfdump var="#myresult.fileContent#">
Please can try this example so you will have clear picture and understand correctly.
I am using ColdFusion 8 but I have checked in ColdFusion 11 same error.
thanks
Copy link to clipboard
Copied
HaroonTyagi wrote:
if you check request xml above, then there is no function name(cfc component function: service_soap_call) and function body.
No function name and body? This is confusing. You did define the following named function:
<cffunction name="service_soap_call" access="remote" output="no" returntype="any" >
</cffunction>
Copy link to clipboard
Copied
BKBK This function defined in cfc component not in xml file inside cfm. if request doesn't have the function value then how the cfc component will identify which function need to call, finally will return the error that function is not defined.
Copy link to clipboard
Copied
Let me see whether I understand. Are you attempting to achieve something like this:
test.cfc
<cfcomponent output="no">
<cffunction name="testFunction" returntype="any" access="remote">
<cfargument name="soapInput">
<cfset var inputXML = arguments.soapInput>
<cfset var soapBodyText="">
<cfset var noBodyTextError="">
<cftry>
<cfset soapBodyText = xmlSearch(inputXML,"//soapenv:Body/text()")[1].xmlValue>
<cfsavecontent variable="noBodyTextError"><?xml version="1.0" encoding="utf-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <soapenv:Body> <soapenv:Fault> <faultcode>soapenv:Server.userException</faultcode> <faultstring>java.lang.Exception: Body not found.</faultstring></cfsavecontent>
<cfif trim(soapBodyText) is "">
<cfthrow>
</cfif>
<cfreturn inputXML>
<cfcatch type="any">
<cfreturn noBodyTextError>
</cfcatch>
</cftry>
</cffunction>
</cfcomponent>
tester.cfm
<cfxml variable="mydata">
<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:wor="https://www.worldmilesafrica.com">
<soapenv:Header/>
<soapenv:Body>
</soapenv:Body>
</soapenv:Envelope>
</cfxml>
<cfinvoke webservice = "http://127.0.0.1:8500/workspace/wsTest/test.cfc?wsdl"
method = "testFunction"
returnVariable = "result">
<cfinvokeargument name="soapInput" value="#trim(mydata)#" >
</cfinvoke>
<cfdump var="#result#">
Copy link to clipboard
Copied
Hi BKBK yes but as you know web service can call from any language so please use the
standard method via http like below
<cfxml variable="xmldata">
<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:wor="https://www.worldmilesafrica.com">
<soapenv:Header/>
<soapenv:Body>
</soapenv:Body>
</soapenv:Envelope>
</cfxml>
<cfhttp url="http://127.0.0.1:8500/workspace/wsTest/test.cfc?wsdl" method="post" result="myresult">
<cfhttpparam type="header" name="content-type" value="text/xml">
<cfhttpparam type="header" name="SOAPAction" value="">
<cfhttpparam name="soapInput" type="xml" value="#trim(xmldata)#"/>
</cfhttp>
<br />
<cfset mydata = xmlParse(#myresult.fileContent#) >
<cfdump var="#mydata#">
Copy link to clipboard
Copied
Yes, you may call a SOAP web service like that, using cfhttp. I would expand the call to:
<cfxml variable="mydata">
<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/" der/>
<soapenv:Body>
</soapenv:Body>
</soapenv:Envelope>
</cfxml>
<cfhttp url="http://127.0.0.1:8500/workspace/wsTest/test.cfc?wsdl" method="post" result="myresult" >
<cfhttpparam type="header" name="content-type" value="text/xml" />
<cfhttpparam type="header" name="content-length" value="#Len(Trim(mydata))#" />
<cfhttpparam type="header" name="charset" value="utf-8" />
<cfhttpparam type="header" name="SOAPAction" value="">
<cfhttpparam type="xml" name="message" value="#trim(mydata)#">
</cfhttp>
<cfdump var="#myresult.FileContent#">
I should add that it is unnecessary to manually code the error-handling in the CFC. If there are any errors, ColdFusion will generate and return them automatically.
Copy link to clipboard
Copied
Yes BKBK, but we can not show ColdFusion generated errors to user because that error is not user friendly and user will never identify what is the problem exactly.
Please look below errors which is generated by ColdFusion automatically
<soapenv:Fault>
<faultcode>soapenv:Server.userException</faultcode>
<faultstring>java.lang.Exception: Body not found.</faultstring>
<detail>
<ns1:stackTrace xmlns:ns1="http://xml.apache.org/axis/">java.lang.Exception: Body not found.
at org.apache.axis.providers.java.RPCProvider.processMessage(RPCProvider.java:121)...................
I want to show proper erros like this
<soapenv:Fault>
<faultcode>11001</faultcode>
<faultstring>method definition does not exist</faultstring>
-------------
All technology have separate fault class and method through that can generate easily original fault code..
Copy link to clipboard
Copied
@HaroonTyagi
I am now able to make time so that we can explore this question in full. First of all, let us get some assumptions and misconceptions out of the way.
For example, you insisted that one should be able to throw and handle a custom exception when invoking a web service using cfhttp. This expectation may have a basis in the client-server model, where methods are explicitly invoked, but it has no basis here.
In fact, Adobe ColdFusion owes you no explanation about the use of cfhttp to invoke SOAP web services. Neither can it guarantee anything about this usage. The reason is that, using the post method of cfhttp to invoke web services is an undocumented method. By this, I mean that, although creative developers have discovered that it can be so used, it was not designed for that purpose.
The officially documented native Coldfusion ways to consume a web service are by means of <cfobject>, <cfinvoke> and createobject(), or their various script/tag equivalents. There is one big difference between these functionalities and <cfhttp method="post">. If the web service has a compulsory method, then they must call it. Neither <cfobject>, <cfinvoke> nor createobject() can intereact with a web service without explicitly calling its methods.
That is in keeping with the principles of the client-server model of computing. In this case, the web service is the server and the calling application the client. The client makes a request to the service by invoking its method; the server responds by means of a method return.
In contrast, a client using <cfhttp method="post"> may interact with a web service without calling its methods. For example, by posting a SOAP message containing a blank body to the service, as you have done. In that case, you should not expect to be able to apply client-server validation methods, as these necessarily require that methods be explicitly called. In fact, in the client-server model, the method or function is the web service proper.
Therefore, you should perform custom validation in your CFC with the assumption that the service will be consumed by means of <cfobject>, <cfinvoke> or createobject(). There is a further advantage of assuming these will be used, instead of <cfhttp method="post">. The calls based on <cfobject>, <cfinvoke> and createobject() are the Coldfusion equivalents of calls that will be made from other languages, like PHP, .NET, and so on.