Web Services with ColdFusion

Since the ‘.NET’ revolution that started half a decade ago, we have been seeing reinventions of our old web programming languages. ASP has become ASP.net, and JSP has too evolved to JSP.net. “Would there be a ColdFusion.net?”, I have wondered. Thankfully ColdFusion has not gone the way of the dinosaurs. Web services are surprisingly easy to implement on ColdFusion, and consuming web services is equally simple.

Before we step into web services, you will need to realize that they are built upon CFCOMPONENT.  These tags bundles sets of functions into neat OO-objects which you can in turn instantiate and call on your web pages. Stretching this feature slightly, Adobe now expands this concept to allow the same bundle you have built to serve you information irregardless of your platform or server. Hence the birth of “ColdFusion.Net”.

How do we implement this? Assuming you have been a serious devotee to the OO (Object-Oriented) way and have been practicing CFCOMPONENTs in all your work, it would be as simple as changing one parameter:

daoHelloWorld.cfc 

<cfcomponent>
<cffunction name=”sayHelloTo” access=”remote” output=”no” returntype=”string”>
<cfargument name=”name” type=”string” required=”yes”>
<cfset myString = “Hello #name#!”>
<cfreturn myString>
</cffunction>
</cfcomponent>

Save the above codes into your root folder and you have your very first web service on ColdFusion. You may also notice the additional parameter output=”no”. This parameter should be set to “No” since you are not expecting the function print or display anything. All results will be returned to the caller. To inspect your new webservice, you can access via the component browser for this file at http://<your-own-domain>/daoHelloWorld.cfc . Do note that you may need to log into your ColdFusion administrator account to view it.

Now let’s go through how we could consume this new web service. Since this is a ColdFusion blog, let’s see how we could consume web services the ColdFusion way.

<cfinvoke webservice=”http://<your-own-domain>/daoHelloWorld.cfc?wsdl” method=”sayHelloTo” returnvariable=”strg”>
<cfinvokeargument name=”name” value=”James”/>
</cfinvoke>

<cfoutput>
#strg#
</cfoutput>

Neat isn’t it? Do pay attention to your functions which returns non-string variables. By default complex objects returned via the function will be in WDDX. WDDX are structured XML that was built originally for ColdFusion. When returning WDDX, the other non-ColdFusion server may not have the luxuary of a built-in fuction to convert the XML back into objects. These applications will need to built their own xml parser.

CFComponent

For easy maintenance, Coldfusion has come up with a feature which is . This features has the capability to enclose functions for easy sharing from multiple files. As such, codes within the the body of these tags can be executed only when the component is instantiated.

So let’s look at how we can make use of the component.

First we will create a file, eg test.cfc which will stores the relevant functions such as interacting with the database. Content will be as follows:

<cfcomponent> 
     <cffunction name=”GetProductByID” access=”public” returntype=”query”>
        <cfargument name=”ProductID” type=”string” required=”yes”>
        <cfquery datasource=”#application.dsn#” name=”data”>
           SELECT *
           FROM catalogue
           WHERE productid = ‘#CompanyID#’    
        </cfquery>
    </cffunction>
    <cfreturn data>
</cfcomponent>

With references from the codes as shown above, you could see that the function requires a string to be included into the SQL statement and thereafter returns a query as the output. To display the records, you will need the following codes:

<cfset comtest = createObject(”component”,”exec.test”)>
<cfset prod = comtest.GetProductByID(”#form.ProductID#”)>
<cfoutput query=”prod”>
#productname#
</cfoutput>

As you can see from the codes above, the component is instantiated on the first line. Next the variable “products” is being declared to contain the query results from the function “GetProductByID”. The results are then displayed via the

Simple as it can be. Do try it out and you will realise how convenient it can get as the functions stored within can be shared across multiple files.

CF Tooltip

Let’s look at something handy today, Tool-Tips. These are the supplementary information displayed in a small “hover box” when mouse-over certain elements within the web page. We would usually use this feature for explanation of terms, or larger view of thumbnails.

Traditionally, these “boxes” are coded through javascripts and may not be as flexible as we want them to be.

Introduced in ColdFusion 8, we now have, who would have guessed, CFTOOLTIP! This tag allows you to wrap it around almost any visible element within the page. Being a ColdFusion tag, you will be able to manipulate it in any way ‘coldfusioningly’ possible.

Here’s how you use it.

In its simplest form, to display a single line of explanatory text above an element, this is all we need to do:

<cftooltip tooltip=”ColdFusion is a tag-based programming language that was developed by the Jeremy Allaire in 1995″ >
ColdFusion
</cftooltip>

Taking this a step further, instead of feeding text, you may also feed in HTML tags to achieve your necessary formatting.

In a slightly more advance level, what I personally like best about this tag is the ability to tool-tip from html source.
Here is how you could do it:

Album_thumbnails.cfm

<cfset tiptext = “large_photo_caption.cfm?photo_id=candy_&_seet”>

<cftooltip sourceForTooltip = URLEncodedFormat(tiptext)>
Photo : <img xsrc=”img/candy_&_seet_thumbnail.jpg” />
</cftooltip>

large_photo_caption.cfm

<cfset large_pic = daoPhoto.getPhotoByID(URL.photo_id)>
<cfset large_pic_url = ExpandPath(large_pic.location)>

<cfimage action=”read” source=”#large_pic_url#” name=”pic”>
<cfset ImageScaleToFit(pic, 240, 180)>
<cfimage action=”writeToBrowser” source=”pic”>
<br>
<cfoutput>#large_pic.caption#</cfoutput>

Do take note that while the first instance of mouseover loads the html from source, subsequent mouseovers will read from cache until the entire page is reloaded.

For more controls, this tag also allows you to pass in the ‘autoDismissDelay’, ‘hideDelay’, ‘preventOverlap’ and ’showDelay’as parameters. However for most scenarios, the default settings are ususally more than sufficient. You may also find out more about this tag from their official documentation.

Auto-Suggest Inputs

Before jumping into the deep end, let’s look at the various built-in functions that ColdFusion 8 has got to offer.

CFINPUT now includes an autosuggest feature (only available for type=”text”). This entry completion suggestions feature matches and displays the suggestion as the user types into the text input field. The user will be able to select the suggestion to complete the entry. To activate this feature, simply pass the list of suggested words (seperated by commas) into the ‘autosuggest’ parameter field.

search.cfm

<cfquery datasource=”myDB” name=”data”>
SELECT DISTINCT company_name FROM company_data
</cfquery>

<cfform>
Name:  <cfinput type=”text” name=”company” autosuggest=”#ValueList(data.company_name)#”>
</cfform>

For the above codes, the look up for suggestions are not asynchronous. All data is retrieved during the loading of the page and hence only local data. This method is usually preferred for smaller list and information which are not required to be real time.

If you require real time information or have a long suggestion list, you may consider binding an expressions to the autosuggest field. Using ‘bind’, communications will be made to the server to retrieve live data. You may manipulate your data in the function and control your returns in anyway you please. Example as follow:

daoCompany.cfc

<cfcomponent output=”false”>
<cffunction name=”lookupName” access=”remote” returntype=”array”>
<cfargument name=”search” type=”any” required=”false” default=”">
<cfquery datasource=”myDB” name=”data”>
SELECT TOP 5 first_name FROM company_staff
WHERE UCase(first_name) LIKE Ucase(’#ARGUMENTS.search#%’)
ORDER BY artname
</cfquery>
<cfset var result=ArrayNew(1)>
<cfloop query=”data”>
<cfset ArrayAppend(result, first_name)>
</cfloop>
<cfreturn result>
</cffunction>
</cfcomponent>

search_dyn.cfm

<cfform>
Name:
<cfinput type=”text” name=”company” autosuggest=”cfc:daoCompany.lookupName({cfautosuggestvalue})”>
</cfform>

AJAX on ColdFusion 8

AJAX (Asynchronous JavaScript and XML) enables web components to exchange data without being dependent on the loading and reloading of the entire webpage it resides on. It is often seen as a powerful tool to transform and enrich our web pages with more interactivity and engagement.Used by millions, FaceBook offers a fine example of the capabilities of AJAX in action. You would have noticed the functions to approve friends, add friend details send invites are all done without ever requiring reloading the page.

ColdFusion 8 simplifies such implementation by offering a wide array of tags and functions to enable quick development of such applications. ColdFusion reduces the technical challenges by simplifying the frameworks and user interface element libraries. If you are familiar with CFFUNCTION, connectivity to server-side resources such as databases is a breeze.

Detailed functions will be discussed later.