Web services are really cool. I’ve received a few requests for access to our MySQL database from a few different groups recently. For example, one of the student clubs recently contacted me and told me they wanted to pull a list of their members and use it dynamically on their web site. Problem is they host their site on their own server and I’m not willing to punch holes in the firewall or create MySQL accounts on the server. They left frustrated and I felt guilty that I couldn’t help them out. I kept thinking about it and finally the idea hit me, web services. If this isn’t a perfect example for a web service, I don’t know what is. I’d never developed a web service on Coldfusion before but every thing I’d read indicated it was very simple. So I broke out the developer manual today and started playing around with it. About 30 minutes later it was all done (well, the basics. I plan to add more functionality). Initially I created a plain coldfusion component (CFC) and created a function called “getMembers” (with access=remote) that would return a list of club members. Inside the function I dropped in a simple cfquery tag to pull the list of club members and then return the query. Here’s what the code looks like:
<cfcomponent hint=”Web Service functions for the clubs”>
<cffunction access=”remote” name=”getMembers” returntype=”query” hint=”Returns a list of club members”>
<cfargument name=”user” type=”string” required=”yes” hint=”A valid username to access this resource”>
<cfargument name=”pass” type=”string” required=”yes” hint=”A valid password to access this resource”>
<!— SET THE DEFAULT RETURN VARIABLE TO A NULL STRING —>
<cfset variables.getMembers = “”>
<!— CHECK THE USERNAME AND PASSWORD —>
<cfif arguments.user EQ “SomeUser” AND arguments.pass EQ “SomePassword”>
<!— USERNAME AND PASSWORD ARE VALID, RETRIEVE INFORMATION FROM THE DATABASE
AND SET IT TO THE RETURN VARIABLE —>
<cfquery datasource=”ClubDatasource” name=”variables.getMembers”>
SQL STATEMENT TO RETRIEVE MEMBER LIST GOES HERE
</cfquery>
<cfelse>
<!— USERNAME AND/OR PASSWORD WERE INVALID, THROW AN ERROR —>
<cfthrow detail=”INVALID username AND/OR password” message=”INVALID username AND/OR password”>
</cfif>
<!— RETURN THE RESULT —>
<cfreturn variables.getMembers>
</cffunction>
</cfcomponent>
I wrote a quick test.cfm page to call the web service to see if it worked and it did. The Coldfusion code to invoke such a web service is:
<cfinvoke
webservice=”https://WEBSERVERURL/xml/clubs.cfc?wsdl”
method=”getMembers”
user=”SomeUser”
pass=”SomePassword”
returnvariable=”variables.query”
>
<cfoutput query=”variables.query”>
#clubId# #Name#<br/>
</cfoutput>
That only solved half the problem. I knew how to call and use the web service using Coldfusion, but I knew the club was using PHP on their server. The next step was figuring out how to call a web service using PHP. PHP doesn’t have any built in web service functions (yet), but you can download the NUSOAP library which makes it remarkably easy to use web services in PHP. Here’s the quick PHP script I wrote:
<?php
require_once(’nusoap.php’);
$wsdl=new soapclient(’https://WEBSERVERURL/xml/clubs.cfc?WSDL’);
echo
$wsdl->call(’getMembers’,array(’user’=>’SomeUser’,'pass’=>’SomePassword’));
echo ‘Response: <xmp>’.$wsdl->response.’</xmp>’;
?>
I loaded the page and it worked like a charm. There in front of me was a nice, XML formatted member list from our clubs database. Obviously I still have some work to do, like checking the username and password against our authentication database and such, but for the most part the hard part is done. This little project has got me thinking about what else we can use XML and web services for. I think my next step project will be generating an RSS feed for our news release site.
UPDATE* Coldfusion exhibits some strange caching behavior with web services. After I made my web service and tested it, I added a few more arguments to it. I changed my test invoking method and it said it couldn’t find a matching method with the parameters I passed. Remarkably enough php still worked fine (using the new arguments) but the test.cfm file did not. I did some searching and came across this message thread. It appears the only way to get rid of the cached version is to login to the Coldfusion Administrator, click on web services, delete the appropriate entry and reload the cfm page. So basically you have to do this anytime you add a web service function/method or change the arguments of a function/method. It’s a little annoying.
While looking around in web services in the Coldfusion Administrator I also noticed you can assign a username and password to each web service directly instead of imbedding them in the function like I did. If you want to keep authentication simple that’s a good way to go.