Browse and select the application path or root folder where ColdFusion would search for CFCs.
ColdFusion 10 lets you create and publish REST (Representational State Transfer) services that can be consumed by clients over HTTP/HTTPS request.
The following URL takes you to the Java Tutorial that provides conceptual information on REST:
http://download.oracle.com/javaee/6/tutorial/doc/gijqy.html
You can create REST services by defining certain attributes in the tags cfcomponent , cffuntion , and cfargument and publish as REST resources.
<cfcomponent rest="true" restpath="restService"> <cffunction name="sayHello" access="remote" returntype="String" httpmethod="GET"> <cfset rest = "Hello World"> <cfreturn rest> </cffunction> </cfcomponent>
After you create the CFC you want to REST-enable, specify the folder for registering as web service either using the function restInitAplication or in the ColdFusion Administrator.
Nested REST applications cannot be registered.
When you specify a folder, all CFCs in that folder or subfolders for which you have specified rest or restPath are registered.
Browse and select the application path or root folder where ColdFusion would search for CFCs.
(Optional) In the Service Mapping section, specify virtual mapping in place of application name.If the folder has an Application.cfc and an application name, then the service is identified with the application name. You can override this by specifying the service mapping. In this case, the service is identified with the service mapping that is provided. If there is no Applicaiton.cfc in the folder, then it is mandatory to specify the Service mapping.If you choose to specify REST folder outside of ColdFusion root, then add one of the following mappings to register the folder:Consider that you have added a mapping for c:\restfolder as \map
<cfset restinit("c:\restfolder","myapp")> <cfset restinit("\map","myapp")>
(Optional) Specify an application as default REST service. Only one application can be set as default for a server instance. You can change the default application at any time. Check Set the default application and then click Add Service. To remove the service as default, uncheck it.
After you specify the details, click Add Service to register.The Active ColdFusion REST Services section specifies the details of all registered web services.
After you register, all CFCs are published as RESTful services. On subsequent startups, the registered services automatically get published.
Refresh the application whenever there is a change in REST-related component in the application.
<cfhttp url="http://localhost:8500/rest/RestTest/restService" method="get" port="8500" result="res"> </cfhttp>
The URL provided in the example can be interpreted as follows:
URL component |
Description |
---|---|
http://localhost:8500 |
Base URL which includes the IP address and port of the ColdFusion server.If you deploy ColdFusion as a JEE application, the URL will contain a context root, for example, http://localhost:8500*/cfusion* . |
rest |
Implies that the request sent is a REST request.This default value can be renamed by revising the context path in web.xml available at cfusion/wwroot/WEB-INF and update the same mapping in uriworkermap.properties file found at config\wsconfig\1. |
restTest |
Application name or service mapping that you have used while registering the service in ColdFusion Administrator. If you do not specify a service mapping in the ColdFusion Administrator, then the application name is taken from Application.cfc. |
restService |
Rest path you defined in the service. That is, the value of the attribute restPath in the tag cfcomponent. |
The accept header can be provided in the REST URL. The following examples illustrate this:
<cfhttpparam type="header" name="Accept" value="application/json; charset=utf-8">
The content-type that is returned by a RESTful web service depends on the Accept HTTP header.
Client can set an Accept request header in the following order:
n the following example, client can use both XML and JSON format as no value is specified to indicate a priority in the Accept header:
GET http://adobe.com/stuff |
The request in the following example specifies a priority for returning the content-type:
GET http://adobe.com/stuff |
The order of precedence for content type is as follows:
audio/ mpeg (as no priority is specified)
text/* (0.9 is the highest value)
application/xml
*/
In the following example, though you have specified same priority for both text/* and audio/mpeg, text/* gets precedence because of the sequence.
GET http://adobe.com/stuff |
Functions in a REST service can either be a resource function, subresource function, or subresource locator.
The functions for which you have not specified the RestPath at function level but specified {{httpMethod.}}In this case, the resource function is invoked when URL of the CFC is accessed.
The functions for which you have specified both resptPath and httpMethod.
Subresource functions are used to create subresources for the resource created by CFC. If the subresource has httpMethod attribute in cffunction , the function can directly handle HTTP requests as shown in the following example.
Employee.cfc
<cfcomponent rest="true" restPath="/hello"> <cffunction name="sayHello" access="remote" returnType="String" httpMethod="GET" restPath="name"> --------- </cffunction> </cfcomponent>
In this example, httpMethod and restPath are defined. The baseurl /hello/name is a subresource to the URL baseurl /hello.
If you have not specified the httpMethod attribute, but have specified restPath, you can dynamically resolve the component that handles the request. Any returned object is treated as a resource class instance and used to either handle the request or to further resolve the object that handles the request.
In this example, StudentService.cfc and Student.cfc are the two REST resources. In StudentService.cfc the function getStudent returns a component. In the function, the object of Student is created and the values name and age are set. When the object is specified in the return type, the function defined in the object with the requested httpmethod is invoked.StudentService.cfc can be invoked directly as it has a restPath specified. Student.cfc can only be invoked through StudentService.cfc because the function getStudent in StudentService.cfc is acting as the subresource locator and returns Student.cfc.StudentService.cfc:
<cfcomponent rest="true" restpath="/studentService"> <cffunction name="addStudent" access="remote" returntype="void" httpmethod="POST"> <cfargument name="name" type="string" required="yes" restargsource="Form"/> <cfargument name="age" type="numeric" required="yes" restargsource="Form"/> <!--- Adding the student to data base. ---> </cffunction> <cffunction name="getStudent" access="remote" returntype="student" restpath="{name}-{age}"> <cfargument name="name" type="string" required="yes" restargsource="Path"/> <cfargument name="age" type="string" required="yes" restargsource="Path"/> <!--- Create a student object and return the object. This object will handle the request now. ---> <cfset var myobj = createObject("component", "student")> <cfset myobj.name = name> <cfset myobj.age = age> <cfreturn myobj> </cffunction> </cfcomponent>
Student.cfc
<cfcomponent> <cfproperty name="name" type="string"/> <cfproperty name="age" type="numeric"/> <!--- Getting the student detail. ---> <cffunction name="getStudent" access="remote" returntype="String" httpmethod="GET" produces="text/xml"> <!--- Retrieve the Student from the DB. ---> <!--- get student from db where name and age matches ---> <cfset st.name = "Thomas"> <cfset st.age = "25"> <cfset st.surname = "Paul"> <cfset str = "<student><name>" & st.name & "</name><age>" & st.age & "</age><surname>" & st.surname & "</surname></student>"> <cfreturn str> </cffunction> <!--- Updating the student detail. ---> <cffunction name="updateStudent" access="remote" returntype="void" httpmethod="PUT"> <!--- Retrieve the Student from the DB. ---> <!--- Update the student in DB. ---> <cfset st.name = name> <cfset st.age = age> </cffunction> <!--- Deleting the student. ---> <cffunction name="deleteStudent" access="remote" returntype="String" httpmethod="DELETE"> <!--- Delete the Student from the DB. ---> <!---<cfset st = deleteStudentFromDB(name)>---> <cfreturn "Student deleted"> </cffunction> </cfcomponent>
Student.cfm
<!--- adding the student ---> <cfhttp url="http://localhost:8500/rest/RestTest/studentService" method="post" result="res"> <cfhttpparam type="formfield" name="name" value="Thomas" > <cfhttpparam type="formfield" name="age" value="25" > </cfhttp> <cfoutput>Student Added</cfoutput> </br> </br> <!--- fetching the details ---> <cfhttp url="http://localhost:8500/rest/RestTest/studentService/Thomas-25" method="get" result="res"> </cfhttp> <cfoutput>#xmlformat(res.filecontent)#</cfoutput> </br> </br> <!--- updating the student details ---> <cfhttp url="http://localhost:8500/rest/RestTest/studentService/Thomas-25" method="put" result="res"> </cfhttp> <cfoutput>Updated the student</cfoutput> </br> </br> <!--- deleting the student ---> <cfhttp url="http://localhost:8500/rest/RestTest/studentService/Thomas-25" method="delete" result="res"> </cfhttp> <cfoutput>Student Deleted</cfoutput>
By default, ColdFusion provides default HTTP success and failure responses to the client as follows:
Default Response |
Description |
---|---|
200 OK |
Sent if the response has body . |
204 No Content |
Sent if the response does not have body . |
Default Response |
Description |
---|---|
404 Not found |
Request URL is not valid. |
406 Not Acceptable |
No function in the REST service can produce the MIME type requested by the client. |
415 Unsupported Media Type Error |
A resource is unable to consume the MIME type of client request. |
405 Method not allowed |
If the client invokes an HTTP method on a valid URI to which the request HTTP method is not bound.This error does not appear if the client requests for HTTP HEAD and OPTIONS methods.If a resource method that can service HEAD requests for that particular URI is not available, but there exists a method that can handle GET, it is invoked and returns the response from that method without the request body. If there is no existing method that can handle OPTIONS, a meaningful automatically generated response is sent along with the Allow header set. |
In addition to the default responses available with ColdFusion, you can set custom responses.
For example, assume that you have to provide a success response 201 Created. Such a default response does not exist. You can only have 200 OK or 204 No Content to send.
In such scenarios, you can create custom responses in either of the following ways:
When you define the CFC as REST service, ensure that the returnType is set to void in the cffunction(the function for which you want to send the custom response).For example,
<cffunction name="create" httpMethod="POST" produces="application/xml" returnType="void"> <cffunction>
Create a struct for the custom response that you want to send in the cffunctionas shown in the following example:
<cfset response=structNew()> <cfset response.status=201> <cfset response.content="<customer id="&id&"><name>"&name&"</name></customer>"> <cfset response.headers=structNew()> <cfset response.headers.location="http://localhost:8500/rest/CustomerService/customers/123">
In this example, you have set 201 as the status of the response, content that you want to send. For example, customer details and the location where you have created the resource for the POSTrequest.
If you do not specify the status in the custom response, 500 Internal server error is sent as the response status.
Use the function restSetResponseas follows:
restSetResponse( response ); |
Assume that you want to send a custom error response. For example, consider the following:method.service.cfc
<cffunction name="getCustomer" httpMethod="GET" produces="application/xml" restPath="{id}" return="string"> <cfargument name="id" type="numeric" argtype="PathParam"> <!--- Getting the customer. ---><cffunction>
In this case, you have a customer database and you are doing a GET HTTP request on /customers/123.But you find that the customer with the specified ID 123 is not available. So you want to send 404 Resource Not Found response back to the client, which is not possible by default.In this case, you can use cfthrow to send custom error response as follows:
<cfthrow type="RestError" errorcode="404">
The following enhancements have been made to Application.cfc for REST support:
Variable |
Description |
---|---|
this.restsettings.cfclocation |
To publish the CFCs only in a particular location, provide comma-separated list of directories where the REST CFCs are located. The directory paths can be absolute or relative.If not set, all the CFCs from the application root are published. |
this.restsettings.skipCFCWithError |
When an error occurs, continue publishing, ignoring the CFC that has caused the exception.If true, the CFC with error is ignored and the rest of the CFCs are published. By default it is false.If set to false, in case of an error, the application itself is not published. But other registered application are published.If an error occurs during application startup, the error is printed in console .Each application has separate log files for logging the issues. |
The following conditions apply when you extend the RESTful CFCs:
You can define the REST attributes for functions in the base CFC. So all the CFCs that extend from the base CFC inherits the REST attributes.In the following example, CustomerResource. cfc extends BaseCustomerResource.cfc:BaseCustomerResource.cfc
<cfcomponent> <cffunction name="SayPlainHello" access="remote" produces="text/plain" returntype="string" httpmethod="POST"> <cfreturn "BaseCustomerResource Plain"> </cffunction> <cffunction name="SayXMLHello" access="remote" produces="text/xml,application/xml" returntype="string" httpmethod="POST"> <cfreturn "BaseCustomerResource XML"> </cffunction> </cfcomponent>
BaseCustomerResource.cfc has all REST attributes applied to functions within the CFC. After you define BaseCustomerResource.cfc, you can define CustomerService.cfc that extends BaseCustomerResource.cfc as follows:Customerservice.cfc
<cfcomponent rest="true" restpath="/customerservice" extends="BaseCustomerResource"> <cffunction name="SayPlainHello" access="remote" returntype="string"> <!--- Implement the method. ---> <cfreturn "CustomerResource Plain"> </cffunction> <cffunction name="SayXMLHello" access="remote" returntype="string"> <!--- Implement the method. ---> <cfreturn "CustomerResource XML"> </cffunction> </cfcomponent>
BaseCustomerResource.cfm
<cfhttp url="http://localhost:8500/rest/RestTest/customerservice" method="post" result="res"> <cfhttpparam type="header" name="accept" value="text/plain" > </cfhttp> <cfoutput>#res.filecontent#</cfoutput> </br> </br> <cfhttp url="http://localhost:8500/rest/RestTest/customerservice" method="post" result="res"> <cfhttpparam type="header" name="accept" value="application/xml" > </cfhttp> <cfoutput>#res.filecontent#</cfoutput> </br> </br>
Except the rest and restPath, no other REST attributes are required within CustomerService.cfc.
When you inherit a RESTful CFC, you can choose to override the attributes used in the CFC that you extend. For example, the following CFC extends the BaseCustomerResource.CFC, but the function SayPlainHellooverrides the function in Base CFC.
<cfcomponent rest="true" restPath="/customerservice" extends="BaseCustomerResource"> <cffunction name="SayPlainHello" access="remote" produces="text/plain" returntype="string" httpmethod="PUT"> <cfargument name="username" type="string" argtype="pathparam"> <!--- Implement the method. ---> </cffunction> <cffunction name="SayXMLHello" access="remote" returntype="string"> <cfargument name="username" type="string"> <!--- Implement the method. ---> </cffuntion> </cfcomponent>
Even if you override only one attribute in a function, you have to respecify all REST attributes
REST services in ColdFusion can be represented in XML or JSON formats for transmitting over the web. ColdFusion takes care of the serialization/deserialization of the ColdFusion data types used in the services to XML or JSON implicitly.
A function that is REST-enabled can take the following ColdFusion data types as arguments: query, struct, CFC type, array, array of CFCs, XML, string, numeric, boolean , date, and binary (for XML).
ColdFusion serializes data to pre-defined formats of XML and JSON. Similarly, ColdFusion deserializes the body only if the body is in the format defined by ColdFusion.
Cyclic arrays are not supported. You might see the serialized string published, but not with the expected output as explained in the following example:
<cfset this.arr1 = arrayNew(1)> <cfset this.arr1[1] = "1"> <cfset this.arr1[2] = this.arr1> <cfset this.arr1[3] = "3">
When an array is assigned to a variable, in this case, <cfset this.arr12 = this.arr1>, you assign arr1 as the item in the second index of arr1. ColdFusion implicitly creates a new array and copies the data from arr1 to the newly created array. The newly created array is assigned to the second index of arr1. Therefore, both the instances are different, and therefore cyclic dependency is impacted.When you serialize, you get the following output:
<array id="1" size="3"> <item index="1" type="string">1</item> <item index="2" type="array"> <array id="2" size="1"> <item index="1" type="string">1</item> </array> </item> <item index="3" type="string">3</item> </array>
As you can observe, the inner array gets truncated after the first element.
In the following example, The root query element has two child elements columnnames and rows. columnnames is the name of the columns in the query. rows can have data in multiple row elements. Here, the order of the column in the row should match the column defined in the columnames. For each column in the row, a type attribute is mandatory. The type attribute can have any of the ColdFusion data types as values.
<query id="1"> <columnnames> <column name="columnnameone"/> <column name="columnnametwo"/> </columnnames> <rows> <row> <column type="string">value one</column> <column type="string">value two</column> </row> <row> <column type="number">444.0</column> <column type="string">value four</column> </row> </rows> </query>
<struct id="1"> <entry name="name" type="string">joe</entry> <entry name="age" type="string">30</entry> <entry name="address" type="string">101 some drive, pleasant town, 90010</entry> <entry name="eyecolor" type="string">blue</entry> <entry name="income" type="string">50000</entry> </struct>
Student.cfc
<component id="1" name="testrest.student"> <property name="name" type="string">paul</property> <property name="age" type="number">444.0</property> <property name="dob" type="date">478377000000</property> </component>
In the following example, testrest .student means the CFC Student.cfc is placed in the testrest directory under webroot.
The following example shows an array containing two struct objects:
<array id="1" size="2"> <item index="0" type="struct"> <struct id="2"> <entry name="name" type="string">joe</entry> <entry name="age" type="string">30</entry> <entry name="address" type="string">101 some drive, pleasant town, 90010</entry> <entry name="eyecolor" type="string">blue</entry> <entry name="income" type="string">50000</entry> </struct> </item> <item index="1" type="struct"> <struct id="3"> <entry name="name" type="string">paul</entry> <entry name="age" type="string">25</entry> <entry name="address" type="string">some other address</entry> <entry name="eyecolor" type="string">black</entry> <entry name="income" type="string">40000</entry> </struct> </item> </array>
The following example illustrates serializing array of CFC to XML and JSON formats.
Create an array of arrayCFCdefinition.cfc:
<cfcomponent> <cfproperty name="str" type="string"/> </cfcomponent>
arrayCFC.cfc produces the required array as follows:
<cfcomponent restpath="arrayOfCFC"> <cffunction name="func1" access="remote" output="false" returntype="arrayCFCdefinition[]" httpmethod="get" produces="text/xml"> <cfset arrCFC = arraynew(1)> <cfloop from=1 to=2 index="i"> <cfset obj = createObject("component", "arrayCFCdefinition")> <cfset obj.str = i> <cfset arrayAppend(arrCFC, obj)> </cfloop> <cfreturn arrCFC> </cffunction> <cffunction name="func2" access="remote" output="false" returntype="arrayCFCdefinition[]" httpmethod="get" produces="text/json"> <cfset arrCFC = arraynew(1)> <cfloop from=1 to=2 index="i"> <cfset obj = createObject("component", "arrayCFCdefinition")> <cfset obj.str = i> <cfset arrayAppend(arrCFC, obj)> </cfloop> <cfreturn arrCFC> </cffunction> </cfcomponent>
Do the following to access the resource:
For XML:
<cfhttp url="http://127.0.0.1:8500/rest/RestTest/arrayOfCFC" method="get" result="res1"> <cfhttpparam type="header" name="accept" value="text/xml"> </cfhttp>
For JSON:
<cfhttp url="http://127.0.0.1:8500/rest/RestTest/arrayOfCFC" method="get" result="res2"> <cfhttpparam type="header" name="accept" value="text/json"> </cfhttp>
You receive the following serialized output as response:
For XML:
<array id="1" size="2" type="cfsuite.restservices.restservices.new.ArrayCFCdefinition"> <item index="1" type="COMPONENT"> <component id="2" name="cfsuite.restservices.RESTServices.New.arrayCFCdefinition"> <property name="STR" type="NUMBER"> 1.0 </property> </component> </item> <item index="2" type="COMPONENT"> <component id="3" name="cfsuite.restservices.RESTServices.New.arrayCFCdefinition"> <property name="STR" type="NUMBER"> 2.0 </property> </component> </item> </array>
For JSON:
[{"Str":1},{"Str":2}]
The following example illustrates deserializing array of CFC from XML format.
Deserializing array of CFC is unsupported for JSON.
Create an array of arrayCFCdefinition.cfc:
<cfcomponent> <cfproperty name="str" type="string"/> <cffunction name="check" returntype="any"> <cfreturn this.str> </cffunction> </cfcomponent>
arrayCFC.cfc produces the required array as follows:
<cfcomponent> <cffunction name="func3" access="remote" output="false" returntype="string" httpmethod="put" produces="text/xml" consumes="text/xml"> <cfargument name="arg" type="arrayCFCdefinition[]"/> <cfif arg[2].check() eq "2"> <cfreturn "true"> <cfelse> <cfreturn "false"> </cfif> </cffunction> </cfcomponent>
Do the following to access the resource for XML:
<cfhttp url="http://127.0.0.1:8500/rest/RestTest/arrayOfCFC" method="put" result="res3"> <cfhttpparam type="header" name="content-type" value="text/xml"> <cfhttpparam type="header" name="accept" value="text/xml"> <cfhttpparam type="body" value="<ARRAY ID=""1"" SIZE=""2"" TYPE=""cfsuite.restservices.restservices.new.ArrayCFCdefinition""><ITEM INDEX=""1"" TYPE=""COMPONENT""><COMPONENT ID=""2"" NAME=""cfsuite.restservices.restservices.new.ArrayCFCdefinition""><PROPERTY NAME=""STR"" TYPE=""NUMBER"">1.0</PROPERTY></COMPONENT></ITEM><ITEM INDEX=""2"" TYPE=""COMPONENT""><COMPONENT ID=""3"" NAME=""cfsuite.restservices.restservices.new.ArrayCFCdefinition""><PROPERTY NAME=""STR"" TYPE=""NUMBER"">2.0</PROPERTY></COMPONENT></ITEM></ARRAY>"> </cfhttp>
Refer to the function. You are verifying the value of the property of arrayCFC definition.cfc for the second index of the array.
Specify the values directly in the body of the request.
In ColdFusion, cyclic dependency is handled using the ID reference. All ColdFusion complex data types have unique IDs when serialized. If the same object has to be serialized elsewhere, instead of serializing the object again, a reference is made to the already serialized data using its ID. In the following example, the main object is a struct. The struct contains an array of objects. The array has two elements and both the elements are the same instance of a struct. During serialization, the first element in the array is serialized as it is. The ID of the serialized struct is 2. Instead of serializing the second element, as that object is already serialized, IDREF attribute is used to refer to the already serialized struct instance.
<struct id="1"> <entry name="arrayinastruct" type="array"> <array id="2" size="2"> <item index="0" type="struct"> <struct id="3"> <entry name="name" type="string">joe</entry> <entry name="age" type="string">30</entry> <entry name="address" type="string">101 some drive, pleasant town, 90010</entry> <entry name="eyecolor" type="string">blue</entry> <entry name="income" type="string">50000</entry> </struct> </item> <item index="1" type="struct"> <struct idref="3"/> </item> </array> </entry> </struct>
Object reference is taken care of by ColdFusion at the time of deserialization also.
Cyclic behavior is unsupported. But in the case of arrays, you might see the serialized string published, but not with expected output as explained in the following example:
<cfset this.arr1 = arrayNew(1)> <cfset this.arr1[1] = "1"> <cfset this.arr1[2] = this.arr1> <cfset this.arr1[3] = "3">
When an array is assigned to a variable (in this case) <cfset this.arr12 = this.arr1>, you assign arr1 as the item in the second index of arr1. ColdFusion implicitly creates a new array and copies the data from arr1 to the newly created array. The newly created array is assigned to the second index of arr1. Therefore, both the instances are different, and therefore cyclic dependency is impacted.When you serialize, you get the following output:
[1,[1],3]
As you can observe, the inner array gets truncated after the first element.
{'COLUMNS':['columnNameOne','columnNameTwo'],'Data':[['value one','value two'],['444.0','value four']]}
{'NAME':'joe','AGE':30,'ADDRESS':'101 Some Drive, Pleasant Town, 90010','EYECOLOR':'blue','INCOME':50000}
{'NAME':'Paul','AGE':444.0,'DOB':'July, 27 2011 00:00:00'}
Deserialization is unsupported for components.
[{'NAME':'joe','AGE':30,'ADDRESS':'101 Some Drive, Pleasant Town, 90010','EYECOLOR':'blue','INCOME':50000},{'NAME':'paul','AGE':25,'ADDRESS':'Some other address','EYECOLOR':'black','INCOME':40000}]
Specify the values directly in the body of the request. ----
If the request contains a Content-Encoding header of "gzip" then the request entity (if any) is uncompressed using the gzip algorithm. If the request contains an Accept-Encoding header containing "gzip" and an "If-None-Match" Header, entitytag value is checked: if it contains the -gzip suffix, remove this suffix, otherwise, completely remove the "if-none-match" header.
If the request contains a Accept-Encoding header that contains "gzip", then the response entity (if any) is compressed using gzip and a Content-Encoding header of "gzip" is added to the response. As this filter is active, the resource representation can be compressed. the value "Accept-Encoding" is so added to the Vary header. If any entityTag is used and content may be gzipped, the "-gzip" suffix is added to entitytag value.
In ColdFusion 10, multiple applications cannot have the same name, even if the applications are residing in different hosts. With the enhanced ColdFusion 11 REST feature, you can have multiple applications with the same name but available in different hosts. Also, you can set one default application (containing the REST service) for each virtual host.
You can register the directory containing the REST service by using any one of the following options:
A new Application setting autoregister is introduced in ColdFusion 11.
<cfset this.restsettings.autoregister="true"/>
<cfset this.restsettings.servicemapping="testmapping"/>
<cfset this.restsettings.usehost=true/>
<cfset this.restsettings.host="www.adobe.com"/>
<cfset this.restsettings.isDefault=true/>
When the first request comes to the application and if that request is non-REST request, the application will be started and registered. If both usehost and host are not specified, the apps will be registered without host name.
If the first request itself is a REST request, then the application will not get started.
You can use functions defined in CFIDE. adminapi .extensions CFC to manage a REST application. The functions are:
You can also register a REST application by calling the method restInitApplication
The syntax is:
restInitApplication(rootPath[,serviceMapping[,options]])
The options are an optional argument. In the options struct you can pass the:
For registering by specifying the host explicitly:
<cfset str=structNew()> <cfset str.host = "www.site1.com:82"> <cfset str.isDefault = "true"> <cfset RestInitApplication("C:\dev\ColdFusion\cf_main\cfusion\wwwroot\withhostAndDefault", "withhostAndDefault", str)> App registered
For registering by specifying the UseHost attribute: The host name will be extracted from the request URL and will be used for registration.
<cfset str=structNew()> <cfset str.useHost = "true"> <cfset str.isDefault = "true"> <cfset RestInitApplication("C:\dev\ColdFusion\cf_main\cfusion\wwwroot\withhostAndDefault", "withhostAndDefault", str)> App registered
You do not need Administrator privileges to perform the task. The syntax is: restInitApplication(rootPath[,serviceMapping[,options]]) |
In the application.cfc, you can register your own handler for serializing and deserializing the complex types. If the serializer is not specified, ColdFusion uses the default mechanism for serialization.
Example: If you have a phone directory to be serialized on the following parameters:
Array
Struct [ name(String], phoneNo(Struct) [ code(String), no(String) ] ] Struct [ name(String], phoneNo(Struct) [ code(String), no(String) ] ]
And in this example, you want to serialize only struct in a simple format and want the result as follows:
<Array size="1"> <Item index="1"> <root> <Name>Paul</Name> <PhoneNo> <root> <Code>080</Code> <No>411150326</No> </root> </PhoneNo> </root> </Item> </Array>
With the enhanced ColdFusion 11 REST feature, the user can use the plugged-in custom serializer instead of using the default serialization function. The custom serializer has four functions:
The below CustomSerializer code sample will help you to achieve the result for the scenario explained above (Customizing serialization /deserialization of phone directory):
<cfcomponent> <cffunction name="serialize" access="remote" returntype="String"> <cfargument name="arg" type="any" hint="The object to be serialized"/> <cfargument name="type" type="string" hint="The accept header of the request in array format. The order of types in the array is according to the priority of the MIME types in the header."/> <cfset var result = ""> <cfset var key = ""> <cfif arguments.type eq "XML"> <cfif isStruct(arguments.arg)> <cfset result = "<root>"> <cfloop collection="#arguments.arg#" item="key"> <cfset result = result & "<" & key & ">"> <cfset result = result & serializeXML(arguments.arg[key], true)> <cfset result = result & "</" & key & ">"> </cfloop> <cfset result = result & "</root>"> <cfreturn result> <cfelse> <!--- SerializeXML is a new function added in ColdFusion 11. This function will serialize the object to XML using ColdFusion's default serialization mechanism." ---> <cfreturn serializeXML(arguments.arg)> </cfif> <cfelseif arguments.type eq "JSON"> <cfdump var="#arguments.arg.getClass().getName()#" output="console"> <cfif arguments.arg.getClass().getName() eq "java.lang.String"> <cfreturn "test" & arguments.arg> <cfelse> <cfreturn serializeJSON(arguments.arg)> </cfif> <cfelse> <!--- Serialize is a new function added in ColdFusion 11. This function will serialize the object to a a specified type using ColdFusion's default serialization mechanism. ---> <cfreturn serialize(arguments.arg, arguments.type)> </cfif> </cffunction> <cffunction name="canSerialize" access="remote" returntype="boolean"> <cfargument name="type" type="string"/> <cfif arguments.type eq "XML"> <cfreturn true> <cfelseif arguments.type eq "JSON"> <cfreturn true> <cfelse> <cfreturn false> </cfif> </cffunction> <cffunction name="canDeserialize" access="remote" returntype="boolean"> <cfargument name="type" type="string"/> <cfif arguments.type eq "XML"> <cfreturn true> <cfelseif arguments.type eq "JSON"> <cfreturn true> <cfelse> <cfreturn false> </cfif> </cffunction> <cffunction name="deserialize" access="remote" returntype="any"> <cfargument name="arg" type="String" hint="The string to be deserialized"/> <cfargument name="type" type="String" hint="The content-type header of the request."/> <cfset var xmlDoc = ""> <cfset var result = ""> <cfset var numEntries = ""> <cfset var key = ""> <cfset var value = ""> <cfif arguments.type equals "XML" and isXml(arguments.arg)> <cfset xmlDoc = xmlParse(arguments.arg)> <cfif xmlDoc.XmlRoot.XmlName equals "root"> <cfset result = StructNew()> <cfset numEntries = ArrayLen(xmlDoc.root.XMLChildren)> <cfloop index="i" from="1" to="#numEntries#"> <cfset key = xmlDoc.root.XMLChildren[i].XmlName> <cfif ! len(Trim(xmlDoc.root.XMLChildren[i].XMLText))> <cfset value = deserializeXML(ToString(xmlDoc.root.XMLChildren[i].XMLChildren[1]), true)> <cfelse> <cfset value = deserializeXML(xmlDoc.root.XMLChildren[i].XMLText, true)> </cfif> <cfset result[key] = value> </cfloop> <cfreturn result> <cfelse> <cfreturn deserializeXML(arguments.arg, true)> </cfif> <cfelse> <cfreturn deserializeXML(arguments.arg, true)> </cfif> </cffunction> </cfcomponent>
The CustomSerializer that you have implemented can be specified through application.cfc.
<cfset this.customSerializer="CustomSerializer">
Fazer logon em sua conta