Aliaspooryorik
ColdFusion ORM Book

FW/1, WireBox and ValidateThis

I've been trying out two new frameworks today, FW/1 and WireBox, along with ValidateThis.

FW/1 is a really nice lightweight MVC framework and WireBox is a Dependancy Injection framework. Getting FW/1 has a handy setBeanFactory method which allows you to use any BeanFactory that responds to containsBean and getBean calls. WireBox doesn't have these methods, but it does ship with an adapter which lets you expose those methods. These adapters are primary for replacing LightWire or ColdSpring with WireBox, but as this is a new applicaiton I'm building, I'm using the bundled wirebox.system.ioc.adapters.WireBoxAdapter. In my Application.cfc I use the setupApplication() method of FW/1 to load and configure WireBox.

// executes when application starts
function setupApplication()
{
var beanFactory = new wirebox.system.ioc.adapters.WireBoxAdapter( definitionFile="model.config.binder" );
beanFactory.createFactory();
setBeanFactory( beanFactory );
}

You may notice that I'm passing the definitionFile argument into the WireBoxAdapter. This is the dotted path to my binder, which is where I setup my relationships and configure ValidateThis. My binder looks like:


component extends="wirebox.system.ioc.config.Binder"
{
function configure()
{
// map all cfcs in this directory and subdirectories
mapDirectory( "model" );
// define and configure validatethis
mapPath("validatethis.ValidateThis").asSingleton().initWith(
{
JSIncludes = "false"
}
);
}
}

I can now have ValidateThis injected into my controller by simply creating a setValidateThis method like so:

component
{
variables.fw = '';

/* CONSTRUCTOR
------------------------------------------------------------------------------ */

function init( required any fw )
{
variables.fw = arguments.fw;
}

/* EXPLICIT
------------------------------------------------------------------------------ */

function dosave( required struct rc )
{
rc.foo = EntityNew( "Foo" );
variables.fw.populate( rc.foo );
rc.validationresult = variables.validatethis.validate( foo );
if ( rc.validationresult.hasErrors() )
{
variables.fw.redirect('foo.maintain','validationresult,foo');
}
else
{
transaction
{
EntitySave( foo );
}
rc.message = ["foo saved"];
variables.fw.redirect('foo.bar','message');
}
}

/* DI
------------------------------------------------------------------------------ */

function setValidateThis( ValidateThis )
{
variables.ValidateThis = arguments.ValidateThis;
}

}

It took me a while to figure this out as the docs, but as you can see it's pretty simple and a very powerful combination.


9 comments

  1. Might have to take a look at WireBox - although I'm eagerly awaiting Sean Corfield's DI/1...

    One thing: shouldn't it read:

    rc.validationresult = variables.validatethis.validate( foo );

    Comment by Seb Duggan – March 23, 2011
  2. I freaking LOVE FW/1. Love it, love it, love it.

    Thanks for pointing out the Adapter for WireBox.

    Comment by John Allen – March 23, 2011
  3. Good stuff. You could clean it up even more by turning on accessors and using a validateThis property rather than explicitly creating the setValidateThis method.

    component accessors="true" {
    property validateThis;
    }

    Also, your example references validateThis inside the request collection (rc.validatethis), which I believe is incorrect.

    Comment by Tony Nelson – March 23, 2011
  4. @Tony - in FW/1 you can't use implicit accessors to autowire your beans into controllers.

    I believe that this will be possible in FW/1 v2, as a result of it being limited to more recent CFML engines (CF9, etc).

    Comment by Seb Duggan – March 23, 2011
  5. @Tony & Seb, thanks for catching that, I'll update the post.

    I did try using property first off and was surprised it didn't work. I haven't had a chance to dig around in the FW/1 code to see what it does. From what Sean said at SOTR recently version 2.0 is going to be awesome!

    Comment by John Whish – March 23, 2011
  6. @Seb & John,

    I find it hard to believe that accessors don't allow for autowiring, since the accessors simply create the get/set methods for you. There's really no way for FW/1 (or WireBox) to tell if those methods are manually created or not...

    Comment by Tony Nelson – March 23, 2011
  7. @Tony, I've just step debugged it to see what is happening. The autowire method in FW/1 doesn't use getMetaData to get the method names; instead it does:

    <cfloop item="key" collection="#arguments.cfc#">

    This only seems (on CF9.01 anyway) to loop through the "concrete" methods. I guess this is done for compatibility with other CFML engines.

    Comment by John Whish – March 23, 2011
  8. I usually end up creating a base cfc which all of my other controllers extend. My base cfc contains all of my getter and setter methods. Wish I could use implicit accessors though.

    Comment by Stephen Weyrick – March 24, 2011
  9. Hi Stephen, I don't mind using concrete setters too much as I have a Eclipse snippet to do it.

    I asked Sean about this and FW/1 v2 will support implicit accessors. The reason why it doesn't use metadata is because of performance and inheritance. Also, when FW/1 was released implicit accessors didn't exist.

    Comment by John Whish – March 25, 2011

Leave a comment

If you found this post useful, interesting or just plain wrong, let me know - I like feedback :)

Please note: If you haven't commented before, then your comments will be moderated before they are displayed.

Please subscribe me to any further comments
 

Search

Wish List

Found something helpful & want to say ’thanks‘? Then visit my Amazon Wish List :)

Categories

Recent Posts