Archive for the ‘ColdFusion’ Category

Implementing Design by Contract in ColdFusion using Coldspring AOP

Monday, August 25th, 2008

I have been playing around with implementing Design by Contract in ColdFusion using Coldspring's AOP functionality.

ColdContract is a Coldspring AOP Advice which allows Design by Contract assertions to be added to ColdFusion components and for those assertions to be executed during program execution.

Design by Contract assertions are a mechanism for defining the specification of software components, in such a way as to allow the implementation of the specification to be tested in-line with program execution. This provides a difference (and arguably quicker) method of implementing TDD to Unit Testing.

Assertions are added to components using meta data attributes as shown below:

  1. <!---

  2. /**
  3. *
  4. * Copyright (c) 2008 David Beale (http://www.BealeARTS.co.uk)
  5. *
  6. **/
  7. --->
  8.  
  9. <cfcomponent displayname="Stack"
  10. hint="A FILO Stack example showing the use of ColdContract assertions. Stack items cannot be objects (Components)."
  11. invariants="this.getNumberOfItems() gte 0, this.getNumberOfItems() eq arrayLen(variables.stack)"
  12. >
  13.  
  14. <!--- INIT --->
  15.  
  16. <cffunction name="init"
  17. hint="Constructor"
  18. access="public"
  19. returnType="Stack"
  20. output="false"
  21. >
  22. <cfreturn this />
  23. </cffunction>
  24.  
  25.  
  26. <!--- PUBLIC --->
  27.  
  28. <cffunction name="push"
  29. hint="Push an item onto the stack"
  30. access="public"
  31. returnType="void"
  32. output="false"
  33. preconditions="not isObject(arguments.item)"
  34. postconditions="this.getNumberOfItems() eq oldThis.getNumberOfItems() + 1"
  35. >
  36. <cfargument name="item" hint="Item to add" type="any" required="true" />
  37.  
  38. <cfset arrayAppend(variables.stack, arguments.item) />
  39. <cfset variables.stackIndex++ />
  40.  
  41. </cffunction>
  42.  
  43.  
  44. <cffunction name="pop"
  45. hint="Pop an item off the stack"
  46. access="public"
  47. returnType="any"
  48. output="false"
  49. preconditions="this.getNumberOfItems() gt 0"
  50. postconditions="this.getNumberOfItems() eq oldThis.getNumberOfItems() - 1, not isObject(cfreturn)"
  51. >
  52.  
  53. <!--- LOCALS --->
  54. <cfset item = '' />
  55.  
  56. <cfset item = variables.stack[variables.stackIndex] />
  57. <cfset arrayDeleteAt(variables.stack, variables.stackIndex) />
  58. <cfset variables.stackIndex-- />
  59.  
  60. <cfreturn item />
  61. </cffunction>
  62.  
  63.  
  64. <cffunction name="getNumberOfItems"
  65. hint="Get the number of items on the stack"
  66. access="public"
  67. returnType="numeric"
  68. output="false"
  69. >
  70. <cfreturn arrayLen(variables.stack) />
  71. </cffunction>
  72.  
  73.  
  74. <!--- PRIVATE --->
  75.  
  76. <cfset variables.stack = arrayNew(1) />
  77.  
  78. <cfset variables.stackIndex = 0 />
  79.  
  80. </cfcomponent>

Odd Error using CFFLUSH

Saturday, April 12th, 2008

Thought I would blog about this, as it wasted almost 2 hours of my time trying to get to the bottom of it.

I was using CFFLUSH on a work project and ColdFusion was returning the following error message:

"You have called cfflush in an invalid location, such as inside a cfquery or cfthread or between a CFML custom tag start and end tag."

What was confusing, was that there were no CFQUERY, CFTHREAD or Custom Tags in the code!

The problem turned out to be an output="false" attribute on a component function, which called the function containing the CFFLUSH. This is obvious with hindsight, however the error message sent me on a wild goose chase :-)


A Practical Use for ColdFusion 8′s Object Serialization

Tuesday, January 29th, 2008

ColdFusion 8 added the ability for objects to be serialized. Although you can not serialize/un-serialize objects with CFML, you can use underlying Java functions to do so as described by Pete Freitag's post Serializing CFC's in ColdFusion 8. In this post a commenter asked whether there is a use-case where this ability would be useful. While contemplating a problem at work, I think I may have found one.

The problem involves building an asynchronous process queue which sits between a "real-time" web service and the system's database. The web service will be used to import large amounts of data and the queue is required due to the length of time required to process and then store the data in the database. The idea is to store the data, which will be in the form of CFML beans, in an array in application scope and then have a CFTHREAD process the beans into the database.

Where does serialization come in? Well suppose something happens to the server while there are items in the queue. A restart will lose all the data in the queue. Although this is an edge case, the data is critical to the business and cannot be lost. So, when an item is added to the queue it is serialized and stored to the file system. When an item is removed, the serialized file is removed. On start up, any serialized files on the file system are read and the queue is repopulated without data loss.

This is purely theoretical at this point, but I think the idea has enough merit to give it a try.


Creating a Server.cfc

Sunday, January 27th, 2008

This is technique I have been using for a while to handle environmental (development, test, production etc) configuration settings. It mimics the Application.cfc added in ColdFusion 7, creating a Server.cfc shown below.

[The requested file http://www.bealearts.co.uk/wordpress/wp-content/uploads/2008/01/server.cfc could not be found]

The Server.cfc is copied to the approot/webroot of the server and the variables.environment property set the the server type e.g. "Development". Then in each Application deployed to the server, the following code is added to the begining of the onApplicationStart method in Application.cfc.

[The requested file http://www.bealearts.co.uk/wordpress/wp-content/uploads/2008/01/run-server-cfc.cfm could not be found]

Environmental configuration changes within each application can then be made by referencing the server.environment and server.name properties of the server scope.


Scotch of the Rocks 2007 Article

Monday, August 27th, 2007

I attended this years Scotch of the Rocks with a press pass from Fusion Authority, and they have just published the articles that I and fellow "member of the press" Kola Oyedeji wrote as reviews of the conference.

Read them at A Tale of CFML, Flex and a Pineapple and A Review of Scotch on the Rocks 2007 respectively.


Railo Customer Service

Monday, June 25th, 2007

I have just installed my first Railo CFML Engine in a production environment.

There was a problem with changing the licence from Community to Profressional. So I emailed Railo and within minutes they came back with a custom solution to my problem.

Now thats what I call Customer Service!!


How to do an OUTER JOIN in Query of Queries

Wednesday, June 20th, 2007

ColdFusion Query of Queries does not natively support OUTER JOINs. The following code demonstrates a work around to perform a LEFT OUTER JOIN between two CF queries, QueryA and QueryB.

i.e. To do this;

SELECT *
FROM QueryA
LEFT OUTER JOIN QueryB ON QueryA.ID = QueryB.ID

One can use;

<cfquery name="joinQuery" dbtype="query" >
SELECT *
FROM QueryB
WHERE QueryB.ID = -1
</cfquery>

<cfset QueryAddRow(joinQuery) />

<cfquery name="result" dbtype="query" >
SELECT *
FROM QueryA, QueryB
WHERE QueryA.ID = QueryB.ID

UNION

SELECT QueryA.*, joinQuery.*
FROM QueryA, joinQuery
WHERE QueryA.ID NOT IN (#ValueList(QueryB.ID)#)
</cfquery>

A common use of an OUTER JOIN is to find the non-matching records between two record sets, a so called NULL Based OUTER JOIN.

e.g.

SELECT *
FROM QueryA
LEFT OUTER JOIN QueryB ON QueryA.ID = QueryB.ID
WHERE QueryB.ID IS NULL

This situation can be more efficiently implemented in Query of Queries by using the following technique;

SELECT *
FROM QueryA
WHERE QueryA.ID NOT IN (#ValueList(QueryB.ID)#)

ColdFusion and SQL 2005 Mirroring

Sunday, June 17th, 2007

After much experimentation, I have finally managed to get Microsoft SQL 2005 Mirroring with automatic failover working with ColdFusion MX 6/7.

The following steps describe how to setup ColdFusion.

  1. Install the latest version of the DataDirect drivers by following these instructions on the Adobe web site - Updated DataDirect JDBC drivers (version 3.5)
  2. Create a new ColdFusion datasource of type "Other".
  3. Enter the following settings, replacing XXXs with your details;
CF Data Source Name XXX
JDBC URL jdbc:macromedia:sqlserver://192.168.1.XXX:1433;
databaseName=XXX;SelectMethod=direct;
sendStringParametersAsUnicode=false;
MaxPooledStatements=1000;
AlternateServers=(192.168.1.XXX:1433)
Driver Class macromedia.jdbc.MacromediaDriver
Driver Name SQL 2005
User Name XXX
Password XXX

You should now be able to manually failover the mirrored database and, after an initial ColdFusion connection reset error, your application to run as normal.

Simple when you now how! :-)


Consuming a .NET Web Service with Complex Types

Saturday, June 9th, 2007

Although simple types such as string and int will be automatically handled by ColdFusion's SOAP mechanisms, the complex types "made up" by .NET are not. This results in "type mismatch" errors.

The following describes the steps needed to use a .NET service with complex types. The ArrayOfString type and a MyDotNetComp Sales API are used as an example.

  1. Try to use the service and get a "type mismatch" error. The Java AXIS system will create .class files for each interface in the service.
  2. Browse the "C:\CFusionMX7\stubs\" folder for these files. They will be under a folder structure unique to the service being called. For example the folder for Travelex is "C:\CFusionMX7\stubs\sometemp\com.mydotnetcomp.www\".
  3. Copy the whole of this folder to "C:\CFusionMX7\wwwroot\WEB-INF\classes\". For example, "C:\CFusionMX7\wwwroot\WEB-INF\classes\com.mydotnetcomp.www\"
  4. Add the path "C:\CFusionMX7\wwwroot\WEB-INF\classes\" to the 'ColdFusion Class Path' in the ColdFusion Administrator in the 'Server Settings > Java and JVM' section and restart the ColdFusion server. This step is required for AXIS to access the .class files.
  5. One of the .class files in this example folder will be ArrayOfString.class which maps the ArrayOfString complex type defined for the web service.
  6. This .class file can be used as an object type and used in the call to the web service, as shown in the example below;
<cfset ary = listToArray("abc", "def", "ghi") />

<cfset aofs = createObject("java", "com.mydotnetcomp.www.ArrayOfString").init() />

<cfset aofs.setString(ary) />

Copyright © 2005, David Beale

  • Valid XHTML 1.0!
  • Valid CSS
  • Level Triple-A conformance icon, W3C-WAI Web Content Accessibility Guidelines 1.0