The amazing adventures of Doug Hughes

Archive for October, 2007

Flex + Ant = No Flex Builder?

For those that have been working with Flex, or at least just reading some of the press, you will know that Adobe also puts out a very nice IDE called Flex Builder.  While Flex Builder gives you a lot of time saving features, it is not strictly necessary for deploying Flex applications.  It is possible to compile your Flex applications from the command line using the free compiler that is available for Flex.

In doing some digging for Ant related materials this afternoon, I came across a project called Flex2Ant which gives you the ability to "add a specific Ant task to the Ant installation that is part of the Eclipse IDE" and enable you to compile your Flex applications within Eclipse and without Flex Builder.

I have not tried this out yet as I like some of the other features of Flex Builder, but I thought it was another interesting use of Ant.

If you want to check it out, take a look at http://www.flex2ant.org/.

First Issue of My New FusionAuthority Column Online

The first installment of my new FusionAuthority monthly column is online. The column is called “Community Chronicles” and the goal is to write impactful and unique columns reflecting the state of the ColdFusion community from a different perspective than has been traditional in the ColdFusion community previously.
In the first installment, I include quotes from Bruce Chizen, CEO of Adobe, and Jonathan Wall, leader of the developer relations team. I had fun collecting my information and writing it, I hope you find it interesting and enjoyable to read!
Here’s the link: Community Chronicles 0.1: Now They’ve Really Done It

Ant + Subversion (on Windows)

In my continuing quest into all that is good with Ant, one of my tasks was to interface with our Subversion repository in order to export the latest code base, possibly tag it, al before shipping it off to the testing or production server.  In looking around, there are several ways to doing this – some that are limited to use within Eclipse, some that require third party downloads, and several others that were not documented well enough to know what they did.  In the end, I chose to use SVNAnt and configure things in a manner that I could run the build file from within Eclipse or from the command line if the need arose.

What is SVNAnt?

According to the documentation, SVNAnt "… is an ant task that provides an interface to Subversion revision control systems …"  Once SVNAnt is configured in your Ant build file, you can do almost anything via your build file that you could do using a Subversion client.  There are a few commands that are not supported, but there are 23 that are including the most common add, commit, export, etc. commands that you typically use.

You can download SVNAnt from http://subclipse.tigris.org/svnant.html.  The current release at this point is 1.0.0 which is available via a zip file.  In all of my incantations trying different things, I actually pulled the latest release from the SVN repository and compiled it to give me a 1.1.0 release.  This is the release I will be setting up below.

Setting it Up

  1. Download the latest release of SVNAnt from the SVN repository at: http://subclipse.tigris.org/svn/subclipse/trunk/svnant/
  2. Next, go to the folder in which you downloaded SVNAnt and copy the build.properties.example file to build.properties.  Uncomment all of the property lines and then add a single line at the bottom with the following text.

    targetJvm = 1.6

    In my case, I am running JVM 1.6.X with ColdFusion 8.  If you are running a lower JVM, adjust this number to match your JVM.  Then, save the file.

  3. Next, assuming you already have Ant installed (see http://www.alagad.com/go/blog-entry/better-development-practices-with-ant if not ), at the command line move to the folder where you downloaded SVNAnt above and type:

    ant makeDistrib

    You should get a bunch of stuff displayed with the last thing being a build successful message.   You should now have version 1.1.0 compiled and ready to go.

  4. Now, inside of your SVNAnt folder should be a folder called build, in which should reside a zip file named svnant-1.1.0.zip.  If you open up that zip file, in it should be a folder called lib, in which should be a collection of jar files.  These are the important ones that we need.  Extract / copy all of these files to the lib folder under your Ant installation.  In my case, I am using the Ant installation that comes as part of Eclipse, so I copied the files to:

    C:eclipsepluginsorg.apache.ant_1.7.0.v200706080842lib

With that complete, SVNAnt should be setup and we are ready to start writing build files.

A Test Build

I am not going to get into how to write a build file here, but lets at least create one that will test our SVNAnt installation.  Create a file called build.xml somewhere in your file system and put the following XML in it.

<project name="test" default="svn.test" basedir=".">
     <path id="svnant.classpath"  >
        <fileset dir=" [ PATH TO ANT LIB FOLDER WHERE SVNANT JAR FILES WERE PUT ] " >
            <include name="*.jar" />
        </fileset>
    </path>

    <typedef resource="org/tigris/subversion/svnant/svnantlib.xml" classpathref="svnant.classpath" />

    <target name="svn.test">
        <svn>
            <wcVersion path=" [ PATH TO CHECKED OUT SVNANT WORKING COPY ] " />
        </svn>
        <echo message= "Subversion repository url: ${repository.url}" />
    </target>
</project>

Lets break this down to see what is happening here.  The path tag tells the build file where to find SVNAnt.  The only thing you will need to change here is the path to the Ant lib folder where you put the SVNAnt jar files.  Note: for windows, the path needs to contain forward double slashes, so "c:eclipse" would be "c:eclipse".

After the path tag, is the typedef tag.  The typedef tag defines the svn type so that we can use it later on.  Everything here should work as is with no changes.

Last we get to our target.  The target is the portion of the build file that will execute the various tasks you want.  In this case, we are doing a simple wcVersion SVN command to get some information about a subversion repository.  If you replace the contents of the path attribute with the file path to the working copy of the SVNAnt repository you checked out earlier, you should be able to run the build file.  Again, note for windows, the path needs to contain forward double slashes, so "c:eclipse" would be "c:eclipse".

Now, if you run this within Eclipse or run it from the command line, you should get back a nice little Build Successful message.  You now have the ability to perform Subversion operations from Ant and make your deployment process so much easier.

Learn More

To learn more about the commands that are available via SVNAnt, check out the documentation page for SVNAnt at http://subclipse.tigris.org/svnant/svn.html.

Announcing The First Enterprise ColdFusion With Model-Glue Training Session

Earlier this week I announced that Alagad would be offering training sessions on Model-Glue and several related technologies. Simply put, the feedback I received was tremendous. As a result, I’d like to announce that our first off-site training session will be held in Arlington, Virginia, just outside of Washington DC, from February 4th to 7th, 2008.

Program details can be seen here.

Details for the session can be seen here.

Registration has officially opened. Register early and get reduced pricing. Also, the first ten registrations before November 9th, 2007 will get free tickets to CF.Objective() 2008!

Validat 101 :: An Example

With In the previous articles in this series, we looked at all of the different concepts that went into developing Validat and making it as flexible as possible.  In this last article, I want to actually show how easy it is to implement Validat into a form validation scenario.  Validat could easily be used to validate business objects or in other data validation scenarios as well, but for now, we will just look at a form validation situation as I expect that will be the most common usage.

The Requirements

There are a few things that need setting up in order to get Validat working.

  • Validat Source – You can get the latest on Validat using your favorite Subversion client from http://svn.alagad.com/Validat/trunk.  As the project progresses, zip files will be made available via the project site for major releases.
  • ColdSpring Framework – Validat utilizes the factory design pattern and by default, the ColdSpring Framework.  The Bleeding Edge version of ColdSpring is required as there are several new features that have name make it into the main release yet.  ColdSpring can be found at http://www.coldspringframework.com.
  • ColdFusion Mappings – The following ColdFusion mappings are necessary and can be setup via the ColdFusion Administrator or your Application.cfc file if you are running ColdFusion 8.
    • /coldspring – Points to the root directory of the ColdSpring framework
    • /validat – Points to the src folder within the Validat distribution

With that out of the way, we are ready to build our example.

The Form

First off, we need a form to collect data to be validated.  There is nothing fancy here, just plain HTML.

<form action="submit.cfm" method="post" name="simpleForm1">
    <fieldset>
        <div class="formField">
            <label for="firstName">First Name:</label>
            <input type="text" name="firstName" id="firstName" class="inputText" />
            <div class="fieldMsg">required, less than 100 characters</div>
        </div>
        <div class="formField">
            <label for="middleName">Middle Name:</label>
            <input type="text" name="middleName" id="middleName" class="inputText" />
            <div class="fieldMsg">optional, less than 100 characters</div>
        </div>
        <div class="formField">
            <label for="lastName">Last Name:</label>
            <input type="text" name="lastName" id="lastName" class="inputText" />
            <div class="fieldMsg">required, less than 100 characters</div>
        </div>
        <div class="formField formButtons">
            <input type="submit" name="action" value="Submit" class="inputButton" />
            <input type="reset" value="Reset" class="inputButton" />
        </div>
    </fieldset>   
</form>

In this form, we have three text input fields … firstName, middleName, and lastName.  Now, in the submit.cfm script, we want to validate these fields and display any errors that might be found.

Validat Rules

Before we can validate the form data from our form, we need to tell Validat what data it is to be expecting and how to validate that data.  For this example, we will just use the configuration XML document mentioned on the first article in this series. 

To setup the configuration, we are going to create a file called validat.xml.  The name can be anything you want, this just makes it obvious as to what it is.

<validat>
 
    <!– validation rule definitions –>
    <validationRules>
       <rule name="length" validator="validateLength">
            <arg name="min" value="0" />
            <arg name="max" value="100" />
        </rule>
    </validationRules>
    <!– data set definitions –>
    <dataSets>
 
        <dataSet name="user">
 
            <dataElement name="firstName" required="true" message="errors.validation.user.firstName.required" >
                <assert rule="length" >
                    <!– optionally, additional arguments can be provided to the validator function –>
                    <arg name="min" value="1" />
                    <arg name="max" value="100" />
                    <message name="invalid" value="errors.validation.user.firstName.invalidLength" />
                </assert>
            </dataElement>
            <dataElement name="middleName" required="false" >
                <assert rule="length" >
                    <arg name="min" value="1" />
                    <arg name="max" value="100" />
                    <message name="invalid" value="errors.validation.user.middleName.invalidLength" />
                </assert>
            </dataElement>
            <dataElement name="lastName" required="true" message="errors.validation.user.lastName.required" >
                <assert rule="length" >
                    <arg name="min" value="1" />
                    <arg name="max" value="100" />
                    <message name="invalid" value="errors.validation.user.lastName.invalidLength" />
                </assert>
            </dataElement>
 
        </dataSet>
 
    </dataSets>
</validat>       

The first section of this file contains the validation rules that we will be using – in this case we will just be testing for fields within a specified length.   The second section of this file contains the data set definition, which we are calling the ‘user’ data set.   Within this data set definition, it shows there will be three data elements that are validated.   The data collection we pass to Validat might well have more than these three data elements, but these there are all that Validat will check. 

According to the data element definitions, both the firstName and lastName data elements are required and all three data elements must have a length between 1 and 100.  The data element definition for middle name looks a bit weird in that it is not required, but it must have a length between 1 and 100.  The way Validat works is that it will check the required state first and if the data value is not required AND it does not contain any data, it will skip the rest of the assertions.  If the data value is required OR it does contain data, then the assertions will be processed.

If you want to read more about this configuration file and its layout, check out the first article in this series.

The ColdSpring Configuration

Quickly before we get to the form script, we need to let ColdSpring know how to instantiate the Validat service object when we request it.   In your ColdSpring.xml file – or you can just create a new one in the same folder if you don’t have one already – insert the following XML snippet.

<beans>
    <import resource="/validat/config/validat.xml" />
    <bean id="validat" class="validat.validat" >
        <constructor-arg name="factory">
            <ref bean="csFactory" />
        </constructor-arg>
        <constructor-arg name="pathToConfigXML">
            <value>validat.xml</value>
        </constructor-arg>
    </bean>
</beans>

The first import tag is what requires the bleeding edge version of ColdSpring as it imports the default ColdSpring configuration for Validat.  This default configuration sets up all of the validators and data transformers that come with the Validat distribution.

The Validat bean element sets the dot notation class path to the Validat service object and passes a couple of arguments to its constructor.  The first is a pointer to the ColdSpring bean factory itself as Validat uses a bean factory to create instances of the validators and data transformers as needed.  By changing this argument value, you could easily put another bean factory implementation in place of ColdSpring if you desired.  The second argument is the path to the Validat XML configuration file we created above.  At this point, it is assumed everything is in the same folder, so a relative path is used.

The Form Submit Script

Now that Validat is configured and knows to validate the data in the form, we just need to set it loose.  Our original form submitted to a file called submit.cfm, so that is the next and last file we will need to create.

First off, the tough part – validating the data.

<!— initialize the ColdSpring bean factory —>
<cfset csFactory = createObject("component", "coldspring.beans.DefaultXmlBeanFactory").init() />
<cfset csFactory.loadBeansFromXmlFile(expandPath("../_common/coldspring.xml"), true) />
 
<!— get an instance of the Validat validation engine —>
<cfset formValidator = csFactory.getBean(‘validat’) />
 
<!— validate the form and collect any errors —>
<cfset errorCollection = formValidator.validate(‘user’, form) />

But that is only 4 lines of code !!! 

Yep, that is all Validat needs and the first two are just setting up the ColdSpring bean factory instance.  The third line of code uses the ColdSpring bean factory to get an instance of Validat and then all of the work is done in the forth line of code.  To validate a collection of data, we simply pass the name of the data set that we are validating the data against, along with the collection of data being validated to the validate method and in return, we get a collection of errors that were found.  That’s it!

The Error Collection

The error collection is an object that comes with Validat and is simply a container for the validation errors found by Validat.  In has a very simple API that allows you to quickly check if it contains errors and to retrieve those errors.

In the above example, to display a message if errors were found would require the following code snippet:

<cfif errorCollection.hasErrors() >
    One or more errors were found in the data you submitted.
</cfif>

To retrieve the list of errors for a given form field and convert them into a list of errors to be displayed, you would use the following code snippet;

<cfif arrayLen(errorCollection.getErrorsByDataElement(‘firstName’)) GT 0 >
    <cfset arrErrors = errorCollection.getErrorsByDataElement(‘firstName’) />
    <cfset fieldErrors = "" />
    <cfloop from="1" to="#arrayLen(arrErrors)#" index="errorPtr">
        <cfset listAppend( fieldErrors, arrErrors[errorPtr].message, ‘<br/>’ ) />
    </cfloop>
<cfelse>
    <cfset fieldErrors = "" />
</cfif>

And with that, you have a complete form validation solution.

Wrap Up

This article wraps up the Validat 101 series.  If you want to find more information about Validat or try it our for yourself, check out the following sites.

Validat 101 :: Transformers

The last piece of the puzzle for Validat is a concept called Data Transformers.  When we were researching the requirements for Validat, I made several blog postings trying to determine how people handled validation.  One of the things that came out of those postings was that the data being validated was not always in a structure such as the form scope.  Some people liked to take data and stuff it into a bean or business object and then validate the object while others prefer to validate the data before they use it.  Then, there is always the unknown edge case and the goal was really to make Validat work in any situation where you needed data validation.  The answer we came up with to this question is what we call Data Transformers.

What is a Data Transformer?

A data transformer simply transforms data – novel huh?  The Validat data validation engine validates data in a key / value structured format.  So, if you are validating data in the form structure, the data transformer does little more than make a copy of the form structure and pass it to the validation engine.  However, if you are validating data in a business object, the data transformer extracts the data from that business object, stores it in a structure and passes that structure to the validation engine.

Adhering to the concept of abstraction, a data transform is implemented as a simple ColdFusion component that follows a prescribed interface.  Not wanting to limit the use of Validat to ColdFusion 8, we chose to create a single component called transformer.cfc, which all data transformer components extend.

So, when it comes time to validate data that is in a different format, it is simply a matter of creating a new transformer component that follows the prescribed interface, registering that component, and you are off and validating.

The Interface

Within each transformer component are two functions – an init constructor and a function called getData.  It is possible for other functions to be added to support the data retrieval process, but these two functions are all that is required by the API.  If you open up any of the transformer objects that come with Validat, you will notice that the init function does not do much in most cases – the bulk of the work is handled in the getData function.

Deconstructing a Transformer

As mentioned before, the structure transformer does not do much, so lets walk through the bean transformer to see how it works..  The following code is contained in the transformBean.cfc component (comments have been stripped).

<cfcomponent
    displayname="transformBean"
    output="false"
    hint="ColdFusion bean data transformer."
    extends="transformer">
 
    <!— ———————————————————— —>
    <!— constructor —>
 
    <cffunction name="init" access="public" returntype="transformBean"
        hint="The default constructor for the transformer object, returning the initialized transformer object instance">
 
        <!— call the base constructor —>
        <cfset super.init() />
        <!— return the initialized transformer object —>
        <cfreturn this />   
    </cffunction> <!— end: init() —>
    <!— ———————————————————— —>
    <!— public methods —>
 
    <!—
        function: getData
        description:    Retrieves the data values in the form of key / value pairs from the bean object.
    —>
    <cffunction name="getData" access="public" output="false" returntype="struct"
        hint="Retrieves the data values in the form of key / value pairs from the bean object.">
 
        <cfargument name="dataCollection" type="any" required="true" hint="The data collection to be transformed" />
        <!— setup temporary variables —>
        <cfset var beanMetaData = getMetaData(arguments.dataCollection) />
        <cfset var resultStruct = structNew() />
        <cfset var funcPtr = 0 />
        <!— loop over the meta data functions, looking for getters —>
        <cfloop from="1" to="#arrayLen(beanMetaData.functions)#" index="funcPtr">
            <!— if the function appears to be a getter —>
            <cfif left( beanMetaData.functions[funcPtr].name, 3 ) EQ "get" >
                <!— call the getter function and insert the value into the result structure —>
                <cfset structInsert( resultStruct, beanMetaData.functions[funcPtr].name, evaluate( "arguments.dataCollection.#beanMetaData.functions[funcPtr].name#" ), true ) />
            </cfif> <!— end: if the function appears to be a getter —>
        </cfloop> <!— end: loop over the meta data functions, looking for getters —>
        <!— return the result structure —>
        <cfreturn resultStruct />
    </cffunction> <!— end: getData() —>
 
</cfcomponent>

In the <cfcomponent tag, the only thing to take notice of is the fact that we are extending the base transformer.cfc component which is located in the same transformers folder as the bean transformer.

The first method shown here is the init constructor which is public and returns the current transformBean object instance after any confirmation has been completed.  In this example, the only operation this function performs is a call to super.init() which calls the init function on the extended transformer object.

The real work of any transformer object is in the getData function.  The getData function takes as an argument a data collection of any type and returns a structure of key / value pairs extracted from the data collection.  In this case, the data collection represents a business object from which the transformer will be extracting data.

The way the bean transformer works is that it gets the meta data for the business object and from that meta data, extracts any functions that begin with the word ‘get’.  If the business object was build using "standard" development practices, there should be getter and setter methods for every data element in the bean.  Therefore, the transformer finds all of the getters and then one by one, calls each getter and inserts the returned value into a structure.

The transformer now has a structure of key / value pairs that can be returned to the Validat data validation engine for validation.

The Big Picture

Like validator objects, data transformer objects require registering.  After creating a new data transformer object, the first thing that needs to happen is that the transformer object should be registered with the Validat ColdSpring XML configuration file (/scr/config/validat.xml).  In this configuration file, there is a section for transformers and the included transformer objects are setup here.  To add a new transformer object, just add a new line like below to the validat.xml file.

<bean id="transformBean" class="validat.dataTransformers.transformBean" />

The bean id value must be unique, but can be anything of your choosing.  The class value is the dot notation path to your transformer cfc.  Remember your bean id as you will need it in the next part.

Once the transformer is registered with the ColdSpring bean factory, it must be connected to one or more data sets in order to be utilized.  The data definition contains all of the data sets, which if a transformer is not specified, will utilize the basic form structure transformer.  A data set definition with a transformer specified looks like this.

<data-set name="user" transformer="transformBean">

When validate function for Validat is called, it accepts two arguments – a data collection and a data set name to validate that data collection against.  The first thing Validat does is look at the data definition for the specified data set name to determine which data transformer it needs to use to extract the data from the data collection.  In the above case, the transformer attribute of the data-set element indicates that when this data set is validated, Validat should utilize the transformer object with bean id ‘transformBean’ to extract the data from the data collection.  Once the data is extracted, Validat moves on with the validation process for all of the data elements contained in the data set.

Wrap Up

Data Transformers and Validators are what make the Validat data validation engine so powerful and give it the ability to be dropped into virtually any scenario.  If you have a custom situation where you need validation, it is a very quick an easy process to write a data transformer that fits your requirements and to drop it into Validat.  Then you have instant data validation.

In the next part of this series, we will setup a working example where we use Validat to validate the data coming from a form and show exactly how it all works together.  In the mean time, check out the Validat project page (http://trac.alagad.com/Validat) and join the Validat mailing list (http://groups.google.com/group/Validat).  Until then ….

Alagad To Invade Scotland

This was actually announced previously by Andy Allan, but both Scott Stroz and myself will be representing Alagad at Scotch on the Rocks 2008.

For those who are not already aware, Scotch on the Rocks is a premiere ColdFusion conference in Europe. It’s held in Edinburgh, Scotland and, from what I’ve been told about past events, is simply fantastic.

Personally, I’m excited just to be going to Scotland. However, it’s an honor to have been invited and to have Scott invited too.

I don’t want to promise too much, but some other Alagadians may just be attending too.

See you there!

Tag Cloud