Skip to main content

ColdFusion 10: RESTful WebServices in ColdFusion - Introduction

In ColdFusion 10, support for creating and publishing REST services has been added. The ColdFusion components can now be made available as REST services and these services can be consumed by various clients. REST stands for Representational State Transfer. It is an architectural style which is based on web standards and HTTP protocol. The idea here is to use HTTP protocol instead of complex mechanisms such as CORBA, RPC or SOAP to connect between the machines. In fact, the World Wide Web which is based on HTTP can be viewed as a REST based architecture.

REST Architectural principles:

A REST based application follows some architectural principles:

  1. Resource Identification: In a REST based architecture everything is a resource. Each of these resources should be identified with a URI.  In ColdFusion, the functions are identified as resources, each of these resources can then be invoked using an URI.
  2. Uniform and constrained interface: Every resource in a RESTful application should support HTTP common operations. The resources are manipulated with the HTTP protocol methods – GET, PUT, POST, DELETE.  In ColdFusion, the resources (functions) can be accessed via HTTP and each of these resource support the HTTP verbs. Depending on the verb specified in the request, the corresponding resource would be invoked.
  3. Representation oriented: REST allows resources to have different representation – plain, html, xml, json etc. A client can request a specific representation via the HTTP protocol. HTTP provides a simple content-type negotiation protocol between the client and the server. For example, an AJAX application may need data in JSON format, where as a Java application may need it in XML format.
  4. Stateless communication: In REST, the server doesn’t store the client session data. However, many techniques exist to exchange state information such as URI rewriting, cookies and hidden form fields. Also, for encryption REST can be used on top of HTTPS.

Getting Started with creating REST services

New attributes have been added to cfcomponent, cffunction and cfargument to aid in creating a REST service. Once a component is created it has to be registered with the Administrator and then it can be accessed via a HTTP request.

Creating a RESTful Web Service

cfcomponent:

As mentioned above, functions in a CFC are the resources and are invoked using a HTTP request. To mark a component as a REST service, attributes rest and restpath are provided. The attribute rest is a boolean attribute, if true the component is enabled as a REST service. This is an optional attribute if restpath is specified in cfcomponent tag. The restpath attribute is used to specify the path using which the REST service would be accessed. If restpath is not specified then the path to the CFC would be used in the URI to invoke the service.

<!--- component with attributes rest and restpath ---> <cfcomponent rest="true" restpath="/crudService"> <!--- handle GET request (httpmethod), take argument in restpath(restpath={customerID}), return query data in json format(produces=text/json) ---> <cffunction name="getHandlerJSON" access="remote" httpmethod="GET" restpath="{customerID}" returntype="query" produces="application/json"> <cfargument name="customerID" required="true" restargsource="Path" type="numeric"/> <cfset myQuery = queryNew("id,name", "Integer,varchar", [[1, "Sagar"], [2, "Ganatra"]])> <cfquery dbtype="query" name="resultQuery"> select * from myQuery where id = #arguments.customerID# </cfquery> <cfreturn resultQuery> </cffunction> </cfcomponent>
The function ‘getHandlerJSON’ handles a GET request and accepts an argument customerID. Notice the additional attributes in cffunction tag. The attribute ‘httpmethod’ is used to specify the type of request this function would handle (GET,POST etc,.). Attribute ‘restpath’ is used to specify the path that should be used in the URL, here the path is specified in curly braces as {customerID}. When this type of notation is used it indicates that a value is passed in the URL and the same has to be copied to the functions’ argument. Therefore the name of the argument is same as the one specified in restpath. There are different ways to pass arguments to a REST service, I’ll explain this in my next post.

Complex data types in ColdFusion such as Array, Query, Struct etc, will be serialized to either JSON or XML format. The produces attribute specifies the mime type to which the data returned by the function will be serialized to. There is also an attribute ‘consumes’ that specifies the mime type of data present in the request body.

Coming to the function arguments, the new attribute restargsource specifies the way in which arguments are passed to a rest service. In this example it is path which indicates the argument will passed in the URL path itself. The other possible values include Matrix, Header, Cookie, Form and Query.

Registering a REST Service

There are three ways in which REST services can be registered with the ColdFusion Administrator. You can use the Admin API (functions defined in extensions.cfc), the ColdFusion administrator console or use the restinitApplicaiton function. Using the Admin API and ColdFusion administrator console requires Administrator privileges and therefore would be available only to selected users. The function restInitApplication can be used to register a REST service and doesn’t require Administrator privileges.

restInitApplication(‘Absolute_path’,[‘Service mapping’])

The directory containing CFC files with with either rest=’true’ or with a restpath in the cfcomponent tag should be specified as the first argument. To identify the set of CFCs in a directory the Service mapping has to be provided. This is an optional fied, if there is an Applicaiton.cfc file present in the directory. In which case the Application name would be used to identify the REST services in the directory.

If any changes are made to any of the components in the registered directory then the corresponding service has to be refreshed. Again this can be done in the Administrator or a call to restInitApplication would refresh the registered service.

Accessing a REST service via HTTP

A RESTful Web service can be accessed either by using HTTP or HTTPS.  The URL to access a REST service in ColdFusion follows this format:

http://servername:port/context_path_j2ee/ rest/rest_application_name_or_serverMapping/restpath_or_componentPath/additionalrestPaths/params_ifany/

Here, the context_path_j2ee is applicable only if you have installed ColdFusion as J2EE on any of the Application servers. In which the context path would be cfusion (by default). However, this can be omitted on Standalone installation.

The string ‘rest’ in URL specifies that the request is for a REST service. ColdFusion has a servlet mapping for the same and would direct the request to the servlet that handles REST service. If there is a directory in the server webroot with the same name, then the servlet mapping has to be updated in web.xml file inside wwwroot\WEB-INF directory.

As mentioned earlier, while registering a REST service the application name specified in Applicaiton.cfc file would be used in the URL to access the REST service. If there is no Applicaiton.cfc then the specified service mapping would be used. To access a service specified in the component the restpath for the component has to be specified. However, if the restpath is not specified in the cfcomponent tag then the path to the CFC would be used in URL. Also, the functions defined in component can also have restpath defined and this has to be specified in the URL. If arguments are to be passed in the URL path then the same can also be specified.

In this example, the function ‘getHandlerJSON’, can be accessed using cfhttp:

<cfhttp url="http://localhost:8500/rest/restapp/crudService/1" result="restResult" method="GET"/>

Here restapp is the application name defined in Applicaiton.cfc file. /crudService is the restpath specified in the cfcomponent tag and the numeric 1 is the argument to the REST service. There are various ways in which arguments can be passed to a REST service, I’ll explain this in my next post.

Comments

  1. Sagar...

    Is there any way to avoid having the /rest/restapp/ in the URL?

    ReplyDelete
  2. What he said :-) Would be good if the rest/restapp (or at least the rest/) part could be avoided.

    Also could you show how one would handle a PUT request (fileupload) alongside additional parameters? For example a user wants to PUT an image and also supply a title for it. What would that look like?

    Thanks.

    ReplyDelete
  3. It is possible to have the CFCs in a default directory and call the REST service without referring to application name\service mapping (restapp) in the URL. I'll post this soon.

    ReplyDelete
  4. Andy Matthews Stefan Richter 
    I've made blog post that explains how you can access a REST service without specifying the Application name or Service mapping in URL -  http://www.sagarganatra.com/2012/02/coldfusion-10-accessing-rest-service.html  

    ReplyDelete
  5. I have a working ReST function that output json

    I added produces="text/json" (which is what it was returning already) and it still worked

    I changed it to produces="application/json" and while return status was still 200
    and the mimetype has application/json
    Filecontent contains
    object of java.io.ByteArrayOutputStreamClass Namejava.io.ByteArrayOutputStream
    Am I understanding / using produces correctly?

    Thank you

    ReplyDelete
  6. Can you deserialize the JSON string i.e. deserialize httpresult.filecontent, you should be able to see the JSON string.

    ReplyDelete
  7. Hi, I do not get the difference between a normal web service though a cfc, and forms with GET & POST compared to the new rest service. I need some enlightenment, anybody?

    ReplyDelete
  8. There are many articles already written on SOAP vs REST based services. I've written a series of posts on RESTful services in ColdFusion - 
    http://www.sagarganatra.com/search/label/REST; this should give you a good understanding of the feature.

    ReplyDelete
  9. Hi ..could u suggest me ways to create a xml request/response without the soap envelope?

    ReplyDelete
  10. You just need to change the produces attribute's value to application/xml. This will return the data in xml format. Please see - 
    http://www.sagarganatra.com/2012/02/coldfusion-10-returning-complex-data.html and 
    http://www.sagarganatra.com/2012/02/coldfusion-10-using-http-content.html

    ReplyDelete

Post a Comment

Popular posts from this blog

File upload and Progress events with HTML5 XmlHttpRequest Level 2

The XmlHttpRequest Level 2 specification adds several enhancements to the XmlHttpRequest object. Last week I had blogged about cross-origin-requests and how it is different from Flash\Silverlight's approach .  With Level 2 specification one can upload the file to the server by passing the file object to the send method. In this post I'll try to explore uploading file using XmlHttpRequest 2 in conjunction with the progress events. I'll also provide a description on the new HTML5 tag -  progress which can be updated while the file is being uploaded to the server. And of course, some ColdFusion code that will show how the file is accepted and stored on the server directory.

Server sent events with HTML5 and ColdFusion

There are several ways to interact with the server apart from the traditional request\response and refresh all protocol. They are polling, long polling, Ajax and Websockets ( pusherapp ). Of all these Ajax and Websockets have been very popular. There is another way to interact with the server such that the server can send notifications to the client using Server Sent Events (SSE) . SSE is a part of HTML5 spec:  http://dev.w3.org/html5/eventsource/

Adding beforeRender and afterRender functions to a Backbone View

I was working on a Backbone application that updated the DOM when a response was received from the server. In a Backbone View, the initialize method would perform some operations and then call the render method to update the view. This worked fine, however there was scenario where in I wanted to perform some tasks before and after rendering the view. This can be considered as firing an event before and after the function had completed its execution. I found a very simple way to do this with Underscore's wrap method.