How to create a ColdFusion REST end-point which accepts query parameters - rest

Here is the code snippet I have tried to create a REST end point with query parameters,
<cfcomponent rest="true" restpath="api">
<cffunction name="getUsersQuery" restpath="Users?filter={query}" access="remote" returntype="struct" httpmethod="GET" produces="application/json">
<cfargument name="query" type="any" required="yes" restargsource="query" />
<cfset var response = {} />
<cfset response["message"] = "Test" />
<cfreturn response>
</cffunction>
</cfcomponent>
But when I tried to call the end point like below it gives "Method Not Allowed"
http://localhost:8010/rest/v1/api/Users?filter=userName eq "test"
Any help would be greatly appreciated.

You don't need to provide ?filter={query} in the rest path since you have mentioned restargsource="query" in the argument. Also the argument name should be the URL key value.
<cffunction name="getUsersQuery" restpath="Users" access="remote" returntype="struct" httpmethod="GET" produces="application/json">
<cfargument name="filter" type="any" required="yes" restargsource="query" />
<cfset var response = {} />
<cfset response["message"] = "Test" />
<cfreturn response>
</cffunction>

Related

Why is a SOAP call working from CFM page but not from a CFC page?

I am working with a SOAP request in coldfusion. When the code I have is run from a .CFM file, it works. If it is run from a .CFC file, it doesn't work. The code is the same as far as possible (the .CFC needs the cfcomponent and cffunction tags for example).
Why would it work from one and not the other? When I call it from the CFC page I get the error
Does anyone have any idea why this might be happening? The SOAP request is identical on both pages. The call with the CFHTTP as well as all the CFHTTPPARAMs are the same as well.
Here is the code for the CFC file:
<cfcomponent>
<cffunction name="updateAgParcel" returntype="string" returnformat="plain" access="remote">
<cfargument name="ag_pres_nr" required="true" type="string">
<cfargument name="emp_nr" required="true" type="string">
<cfargument name="dt_rcvd" required="true" type="string">
<cfset dt_rcvd = DateFormat(#dt_rcvd#,"MMDDYYYY")>
<cfsavecontent variable="soapBody">
<cfoutput>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ass="http://XXXXXX">
<soapenv:Header/>
<soapenv:Body>
<ass:LogAgPreserveFiling>
<ass:AG.PRES.NR>#ag_pres_nr#</ass:AG.PRES.NR>
<ass:TC>04</ass:TC>
<ass:EMP.NR>#emp_nr#</ass:EMP.NR>
<ass:LCAQ.DT.RCVD>#dt_rcvd#</ass:LCAQ.DT.RCVD>
</ass:LogAgPreserveFiling>
</soapenv:Body>
</soapenv:Envelope>
</cfoutput>
</cfsavecontent>
<cfhttp url="XXXXXXXXXXXXXXX" method="post" result="httpResponse">
<cfhttpparam type="header" name="SOAPAction" value="XXXXXXXXXXXX" />
<cfhttpparam type="header" name="Authorization" value="Basic XXXXXXXXXXXXXX" />
<cfhttpparam type="header" name="accept-encoding" value="no-compression" />
<cfhttpparam type="header" name="Content-Type" value="text/xml" />
<cfhttpparam type="xml" value="#trim( soapBody )#" />
</cfhttp>
<cfif find( "200", httpResponse.statusCode )>
<cfset soapResponse = xmlParse( httpResponse.fileContent ) />
<cfset responseNodes = xmlSearch(soapResponse, "//*[ local-name() = 'VCfaultdetails'] ") />
<cfif arrayLen(responseNodes) NEQ 0>
<cfset error = #responseNodes[ 1 ].message.xmlText#>
<cfreturn error>
<cfelse>
<cfreturn "">
</cfif>
</cfif>
</cffunction>
</cfcomponent>
Code for the CFM version:
<cfsavecontent variable="soapBody">
<cfoutput>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ass="http://XXXXX">
<soapenv:Header/>
<soapenv:Body>
<ass:LogAgPreserveFiling>
<ass:AG.PRES.NR>#ag_pres_nr#</ass:AG.PRES.NR>
<ass:TC>04</ass:TC>
<ass:EMP.NR>#emp_nr#</ass:EMP.NR>
<ass:LCAQ.DT.RCVD>#dt_rcvd#</ass:LCAQ.DT.RCVD>
</ass:LogAgPreserveFiling>
</soapenv:Body>
</soapenv:Envelope>
</cfoutput>
</cfsavecontent>
<cfhttp url="XXXXXXXXXXXXX" method="post" result="httpResponse">
<cfhttpparam type="header" name="SOAPAction" value="XXXXXXXXXXXXXXX"/>
<cfhttpparam type="header" name="content-type" value="text/xml">
<cfhttpparam type="header" name="Authorization" value="Basic XXXXXXXXXXXXXXXXX" />
<cfhttpparam type="header" name="accept-encoding" value="no-compression" />
<cfhttpparam type="xml" value="#trim( soapBody )#" />
</cfhttp>
<cfif find( "200", httpResponse.statusCode )>
<cfset soapResponse = xmlParse( httpResponse.fileContent ) />
<cfset responseNodes = xmlSearch( soapResponse, "//*[ local-name() = 'VCfaultdetails'] " ) />
<cfif arrayLen(responseNodes) NEQ 0>
<cfoutput>
Code: #responseNodes[ 1 ].errorcode#
<br />
Message: #responseNodes[ 1 ].message#
</cfoutput>
<cfelse>
Success!!!!!!!!
</cfif>
</cfif>
I XXXXXX out some of the URL's and such for security. Also, sorry for the namespace the developers choose (ass:). It was the abbreviation for Assessor. Somebody was being funny...

How to pass parameter in Form Scope for REST services in ColdFusion?

Today while working with ColdFusion 10 REST, I got an issues. I am not sure how to pass data to a REST service in FORM scope.
Here is my REST enabled CFC,
<cfcomponent rest="true" restpath="/crudService" >
<cfset variable.myQuery = queryNew("Id,Name","Integer,Varchar",[[1,"Test1"],[2,"Test2"],[3,"Test3"]] )>
<cffunction name="getHandlerJSONForm" access="remote" httpmethod="GET" restpath="/formtest" returntype="query" produces="application/xml">
<cfargument name="customerID" required="true" restargsource="Form" type="numeric" >
<cfquery dbtype="query" name="local.qryGetUserName">
SELECT Name
FROM variable.myQuery
WHERE Id = <cfqueryparam cfsqltype="cf_sql_integer" value="#customerID#">
</cfquery>
<cfreturn local.qryGetUserName>
</cffunction>
</cfcomponent>
Here is the CFM code, calling the REST service,
<cfset restInitApplication("E:\Local Workspace\cfcs\rest","myfirstrest")>
<cfhttp url="http://cflocal.com/rest/myfirstrest/crudService/formtest" method="get" >
<cfhttpparam type="header" name="Content-Type" value="application/x-www-form-urlencoded" >
<cfhttpparam type="formfield" name="customerID" value="1" >
</cfhttp>
<cfdump var="#cfhttp#">
In StatusCode I am getting 500 Exception obtaining parameters ?
Please suggest whats going wrong here.

Coldfusion 9 Parse Soap results

I am trying to parse:
<?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:Body><LoginResponse xmlns="http://services.marketernet.com/application"><LoginResult><results><response value="UY+/9dD+Lz7DT3Oq/WG3CVJ/pFW7o6LEFNA4xOSIWr88Dh2RVAgy9qHP1BwpdiYA"/><exceptions></exceptions></results></LoginResult></LoginResponse></soap:Body></soap:Envelope>
So far I have:
<cfset soapResponse = xmlParse(httpResponse.fileContent) />
<cfset results = xmlSearch(soapResponse,"//*[local-name()='LoginResult' and namespace-uri()='http://services.marketernet.com/application']") />
I need the value of <response value="UY+/9dD+Lz7DT3Oq/WG3CVJ/pFW7o6LEFNA4xOSIWr88Dh2RVAgy9qHP1BwpdiYA"/>
I try looping, even try to do a deep xml path, nothing.
Please help me, if you have questions please let me know.
Update 1: "ScreenShot"
Update 2: "Screenshot long version"
I normally just use xmlSearch(soapResponse,"//*[local-name()='whatever']") and it works fine for me. It can return different types depending on how deep you search in the XML. Because of that, when developing the code I always use <cfdump> to view the results of the xmlSearch() function to know what I am dealing with.
I took the SOAP response that you shared and tested the following code successfully on ColdFusion 9.0.1. Notice that I have three different searches here each delving deeper into the XML tree. I left the <cfdump> in there so you can see what each returns.
<cftry>
<cfsavecontent variable="content">
<?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:Body>
<LoginResponse xmlns="http://services.marketernet.com/application">
<LoginResult>
<results>
<response value="UY+/9dD+Lz7DT3Oq/WG3CVJ/pFW7o6LEFNA4xOSIWr88Dh2RVAgy9qHP1BwpdiYA"/>
<exceptions></exceptions>
</results>
</LoginResult>
</LoginResponse>
</soap:Body>
</soap:Envelope>
</cfsavecontent>
<cfset soapResponse = xmlParse(Trim(content)) />
<html>
<head><title>Test xmlParse</title></head>
<body>
<h3>xmlParse option 1</h3>
<div>
<cfset results = xmlSearch(soapResponse,"//*[local-name()='LoginResult']") />
<cfdump var="#results#" />
<cfset value = results[1].results.response.XmlAttributes.value />
<cfdump var="#value#" />
</div>
<h3>xmlParse option 2</h3>
<div>
<cfset results = xmlSearch(soapResponse,"//*[local-name()='results']") />
<cfdump var="#results#" />
<cfset value = results[1].response.XmlAttributes.value />
<cfdump var="#value#" />
</div>
<h3>xmlParse option 3</h3>
<div>
<cfset results = xmlSearch(soapResponse,"//*[local-name()='response']") />
<cfdump var="#results#" />
<cfset value = results[1].XmlAttributes.value />
<cfdump var="#value#" />
</div>
</body>
</html>
<cfcatch type="any">
<cfdump var="#cfcatch#" />
</cfcatch>
</cftry>
All of the options result in setting the value variable to UY+/9dD+Lz7DT3Oq/WG3CVJ/pFW7o6LEFNA4xOSIWr88Dh2RVAgy9qHP1BwpdiYA from the XML.

Coldfusion REST - Serialize Array of CFC

Hi I'm trying to serialize an array of CFCs from one of my REST endpoints. I found this Example: Array of CFC Serialization in the Adobe Help, which pretty much is exactly what I want to do (I can post some code if necessary) Yet when I try to use returnType="myCFC[]" it fails with:
"Message":"array element type mismatch"
The strange thing is, if I instantiate the same object and call the method from a .cfm file, the cfdump shows the array of objects with data as expected. But from my AJAX call, the object's property values are all null. However, if I use return serializeJSON(myArrayOfCFCs) the properties have data. But I don't want to have to do that because it will negate the use of content negotiation.
Just curious if anyone has gotten this to work.
update:
<cffunction name="getPatient" access="remote" httpmethod="GET" returntype="Patient[]" produces="text/json" restpath="/{PatientId}">
<cfargument name="PatientId" type="numeric" required="true" restargsource="Path" />
<cfset local.response = ArrayNew(1) />
<cfset local.patient = getPatientGatewayObject().getPatient(PatientId)>
<cfset local.patientObject = createObject("component", "Patient").init(argumentCollection=queryRowToStruct(local.patient)) />
<cfset arrayAppend(local.response, local.patientObject) />
<cfreturn local.response />
</cffunction>
This works, but not what I want in the end:
<cffunction name="getPatient" access="remote" httpmethod="GET" returntype="Patient" produces="text/json" restpath="/{PatientId}">
<cfargument name="PatientId" type="numeric" required="true" restargsource="Path" />
<cfset local.response = ArrayNew(1) />
<cfset local.patient = getPatientGatewayObject().getPatient(PatientId)>
<cfset local.patientObject = createObject("component", "Patient").init(argumentCollection=queryRowToStruct(local.patient)) />
<cfset arrayAppend(local.response, local.patientObject) />
<cfreturn serializeJSON(local.response) />
</cffunction>

ColdFusion Illudium PU-36 Code Generator

When generating models from postgresql with ColdFusion Illudium Code generator the boolean values get converted to varchar in the cfqueryparam and varchar gets converted to char. Does anyone have a fix for this issue?
http://cfcgenerator.riaforge.org/
1.open the file cfcgenerator/com/cf/model/datasource/postgresql.cfc
2.around line 63 replace bit/bool with this
<!--- bit / bool --->
<cfcase value="bit,boolean">
<cfreturn "cf_sql_bit" />
</cfcase>
<cfcase value="bool">
<cfreturn "cf_sql_varchar" />
</cfcase>
3.around line 101 replace strings with this
<!--- strings --->
<cfcase value="char">
<cfreturn "cf_sql_char" />
</cfcase>
<cfcase value="varchar,character varying,character">
<cfreturn "cf_sql_varchar" />
</cfcase>
<cfcase value="text">
<cfreturn "cf_sql_longvarchar" />
</cfcase>