Photo from Chile

Getting Started with VT and Transfer - Part II - The Initial Sample App

Update: The information in this post is no longer correct due to changes to the framework. A new series is available via the Getting Started with VT category of my blog.

Original content of the article follows:

In the previous post in this series about getting started with Transfer and ValidateThis!, my validation framework for ColdFusion objects, we looked at the frameworks required and the configuration of those frameworks. This post will cover the remainder of the initial sample app, so we have a starting point for integration.

First off, you can view an online version of the sample application at

The code that we're going to look at now resides in the following three files:

  • index.cfm, which drives the app.
  • theForm.cfm, which is the form that is used to add a new User.
  • UserService.cfc, which is the User Service Object.

Let's start by looking at index.cfm:

view plain print about
2    <cfif StructKeyExists(url,"init") OR
3        NOT StructKeyExists(application,"BeanFactory")>

4        <cfset application.BeanFactory = CreateObject("component","coldspring.beans.DefaultXmlBeanFactory").init() />
5        <cfset application.BeanFactory.loadBeans(beanDefinitionFileName=expandPath("/model/config/Coldspring.xml.cfm"),constructNonLazyBeans=true) />
6    </cfif>
9    <head>
10        <title>ValidateThis! and Transfer Sample App</title>
11        <link href="css/style.css" type="text/css" rel="stylesheet" />
12        <link href="css/uni-form-styles.css" type="text/css" rel="stylesheet" />
13    </head>
14    <body>
15    <div id="container">
16        <div id="sidebar">
17            <cfinclude template="theSidebar.cfm" />
18        </div>        
19        <div id="content">
20            <cfinclude template="theForm.cfm" />
21        </div>
22    </div>
23    </body>

Nothing earth shattering here. Basically it just checks to see if the Coldspring bean factory needs to be initialized, and if so does it. Then it includes the cfm files for the Sidebar (which is just text) and the Form. Looking at the code for theForm.cfm:

view plain print about
1<cfset UserService = application.BeanFactory.getBean("UserService") />
3<cfif NOT StructKeyExists(Form,"Processing")>
4    <cfset UserTO = UserService.getUser(theId=0) />
6    <cfset UserTO = UserService.updateUser(theId=0,args=Form) />
10<h1>ValidateThis! and Transfer Sample App - Part I - No Validations</h1>
11<cfif UserTO.getUserId() NEQ 0>
12    <h3>The user has been added!</h3>
14<div class="formContainer">
15<form action="index.cfm" id="frmMain" method="post" name="frmMain" class="uniForm">
16    <input type="hidden" name="Processing" id="Processing" value="true" />
17    <fieldset class="inlineLabels">    
18        <legend>User Information</legend>
19        <div class="ctrlHolder">
20            <label for="UserName">Email Address</label>
21            <input name="UserName" id="UserName"
22                value="#UserTO.getUserName()#"
23                size="35" maxlength="50" type="text"
24                class="textInput" />

25            <p class="formHint">
26                Validations: Required, Must be a valid Email Address.
27            </p>
28        </div>
29        <div class="ctrlHolder">
30            <label for="UserPass">Password</label>
31            <input name="UserPass" id="UserPass" value=""
32                size="35" maxlength="50" type="password"
33                class="textInput" />

34            <p class="formHint">
35                Validations: Required, Must be between 5 and 10 characters.
36            </p>
37        </div>
38        <div class="ctrlHolder">
39            <label for="Nickname">Nickname</label>
40            <input name="Nickname" id="Nickname"
41                value="#UserTO.getNickname()#"
42                size="35" maxlength="50" type="text"
43                class="textInput" />

44            <p class="formHint">
45                Validations: Custom - must be unique. Try 'BobRules'.
46            </p>
47        </div>
48    </fieldset>
50    <div class="buttonHolder">
51        <button type="submit" class="submitButton">Submit</button>
52    </div>

We start off by asking the Coldspring bean factory for our UserService object, which we'll need in order to get a User object to display on the screen, and will also be used to persist a new User object to the database.

This is essentially a self-posting form, so next we check to see if we're displaying the form for the first time, or processing a form post. If the former, we simply ask the UserService for a brand new empty User object, which is done by passing in an Id of 0. If the latter, we ask the UserService to persist a new User object to the database for us, by passing in an Id of 0, and the contents of the Form scope.

The remainder of the code renders our form:

  • If a User object was just saved (which means that the UserId property of the object will not be 0), we display a message to that effect.
  • We then render each form field, asking the User object for the value of its property for each form field. For example, the value of the UserName field comes from UserTO.getUserName().

Finally, we look at the code for UserService.cfc:

view plain print about
1<cfcomponent displayname="UserService" output="false">
3    <cffunction name="init" access="Public" returntype="any">
4        <cfreturn this />
5    </cffunction>
7    <cffunction name="getUser" access="Public" returntype="any">
8        <cfargument name="theId" type="any" required="yes" />
9        <cfreturn getTransfer().get("user.user",arguments.theId) />
10    </cffunction>
12    <cffunction name="updateUser" access="public" returntype="any">
13        <cfargument name="theId" type="any" required="yes" />
14        <cfargument name="args" type="struct" required="yes" />
16        <cfset var objUser = getUser(arguments.theId) />
17        <cfset objUser.setUserName(arguments.args.UserName) />
18        <cfset objUser.setUserPass(arguments.args.UserPass) />
19        <cfset objUser.setNickname(arguments.args.Nickname) />
20        <cfset getTransfer().save(objUser) />
21        <cfreturn objUser />
23    </cffunction>
25    <cffunction name="getTransfer" access="public" returntype="any">
26        <cfreturn variables.Transfer />
27    </cffunction>
28    <cffunction name="setTransfer" access="public" returntype="void">
29        <cfargument name="transfer" type="any" required="true" />
30        <cfset variables.Transfer = arguments.Transfer />
31    </cffunction>

Looking at the bottom of the file first, the setTransfer() method is there so that Coldspring can automatically inject Transfer into the UserService, and the getTransfer() method is there so that we can access Transfer from within the UserService.

The getUser() method simply asks Transfer for a User object that corresponds to the UserId that is passed in. The database is configured so that there will never be a User with a UserId of 0, which is why we can pass 0 into that method and know that we'll get back a new, empty User object.

The updateUser() method calls the getUser() method to get a User object, after which it populates the User object with data from the Form and then asks Transfer to save the User object, which persists the User object to the database.

And that's it. As I mentioned in the previous post, this is not even close to the way I actually do things, but it works and it's a very simple example.

As I also mentioned in the previous post, there are no validations in place. We can see from the form that some validation rules exist for the User object, but there is no code in place to enforce those rules. So our next step will be to integrate VT into this simple application and implement the validation rules for the UserName property. That will be covered in my next post.

Again, an online version of this sample application is available at, and all of the code for it can be found attached to this post.