Getting Data From An External Source

After a lot of work trying to get the system up and running, I finally managed to get to the point where I'm actually writing the post I wanted! As you can see from the title, the point of this entry is to discuss how to retrieve data from an external source. Let's say you want to get data to and from different servers. Let's say server A runs on CF / MSSQL and you want to be able to get data from server B, which runs on CF / MySQL. The easiest way to do this would probably be to create a datasource on server A which would point to server B's MySQL. However, that isn't always possible. You might be on a shared environment where those settings aren't available to you; your server admin is on vacation and you need this to work right now; for some reason you just can't get the MySQL driver to work on server A. Regardless, we have to find a different way of getting the data.

A really neat way to do this is to use a web service. Web services use WSDL, or Web Services Description Language, to provide the receiving server with information about the methods available and the returned types. Considering this, web services are a nice, platform-independant way of sharing information between servers. In our case both servers run on Coldfusion, but it's nice to know that this will work regardless of what the service provider is running on.

Creating the web service

The first thing we'll want to do is setup the actual web service on server B. In Coldfusion, a web service is basically just a component (CFC) with some methods. For our example, let's create a simple method that'll create a dummy query and return it.


<cfcomponent output="false">

    <cffunction name="getSomeData" access="remote" returntype="query">

        <!---
            We need to create a local scope to prevent variable leaking
        --->

        <cfset var locals={} />

        <!---
            Let's create a dummy query to send back.
        --->


        <cfquery name="locals.result" datasource="CWsql">
        create temporary table if not exists data (
            COLUMN_A varchar ( 50 ),
            COLUMN_B varchar ( 50 )
        );

        insert into data values ( 'A LITTLE BIT FROM', 'AND A LITTLE BIT FROM' );
        insert into data values ( 'WHAT''S BEHIND DOOR NUMBER 1?', 'AND DOOR NUMBER 2?' );
        insert into data values ( 'FOO', 'BAR' );

        select * from data;
        </cfquery>

        <!---
            Return it
        --->

        <cfreturn locals.result />

    </cffunction>

</cfcomponent>

Nothing too complicated here. Zac made a great comment on my previous post about preventing SQL injection attacks, so I want to stress again that allowing multiple line queries implies that you must ensure that you do not allow malicious queries in your cfquery blocks. The best way to do this is by using Coldfusion's cfqueryparam tag. Since this is a hard coded query and it will never change (it does not accept user input), there's no need to defend against this type of attack.

Calling the web service

Now that our web service is setup on server B, we'll want to call it from server A. This is relatively easy to do, and requires only a single line of code. Using the cfinvoke tag, we can reference the web service directly and ping a particular method.


<cfinvoke
    webservice="http://blog.critical-web.com/blog/blog-entries/2008-07-29/Getting-Data-From-An-External-Source/service.cfc?wsdl"
    method="getSomeData"
    returnVariable="myData"
    timeout="20"
    />

We provide the url to the web service, the method we want to run and in which variable we want the result to be stored. Pretty straightforward, right? I hope you're not surprised on how easy that was, this is Coldfusion, after all .

Here's the complete code for the entire receiving page.


<cfsetting enablecfoutputonly="true" />

<!---
    Ping the webservice and specify which method to call. In this case, getSomeData.
    --->

<cfinvoke
    webservice="http://blog.critical-web.com/blog/blog-entries/2008-07-29/Getting-Data-From-An-External-Source/service.cfc?wsdl"
    method="getSomeData"
    returnVariable="myData"
    timeout="20"
    />


<cfoutput>

    <h2>Getting Data From An External Source</h2>

    <!---
        Let's dump the variable for all to see!
        --->

    <cfdump var="#myData#" label="myData" />

</cfoutput>

In my previous post, I had blogged about Coldfusion's habit of caching the WSDL for a web service the first time it is requested. Although this is great on a production server, when you're preparing your object on dev you might change method names, return types, etc. Since the WSDL is cached the definition sent to the receiving end isn't updated. This can cause error messages, since the requester isn't receiving what it was expecting. To refresh the WSDL, find the web service in Coldfusion Administrator \ Data & Services \ Web Services and click on it's refresh button.

Of course. The sturdy, breathable fabric is designed to maintain mammary elasticity.

BlogCFC was created by Raymond Camden. This blog is running version 5.9.1.002. Contact Blog Owner