Blog

Brad Wood

August 12, 2014

Spread the word


Share your thoughts

This is the second half of our two-part conversion of a FuseBox 5.1 sample app to ColdBox MVC.  If you haven't been following our blog series on converting your legacy FuseBox apps over to ColdBox MVC you may want to back up and read the previous post first..  In that post we took a look at the different files in each version of the app.  We talked about how each framework bootstraps itself up, as well as settings and circuits/handlers.  We'll pick up right were we left off in this post and finish off the code by looking at how we converted the views, models, and error handling.

Views

ColdBox will automatically look for a view file named after your action in a folder named after your handler.  Of course, all this happens in our "/views" convention folder.  You are free to name your view files whatever you want though.  Just use the following code to tell the framework what view to include:

1
2
// Include /views/randomFolder/randomFile.cfm
event.setView( "randomFolder/randomFile" );

Our views are almost identical.  There are two main differences.  The first is that our views "get" data from the handler by accessing the readily-available rc (request collection) and prc (private request collection) scopes.  rc is used for any input from the user via FORM or URL scopes.  prc is for any other data the handler wants to pass along to the view.  The second is in how we build links.

/view/listEmails.cfm

1
<a href="#self##xfa.conform#">Return to Connect Form</a>

/views/list.cfm

1
<a href="#event.buildLink( prc.xeh.conform )#">Return to Connect Form</a>

ColdBox gives you a nice helper method in the event object to build links for you.  It automatically handles HTTPS, the base domain, app mapping, and query string.  event.buildLink() can also generate SES URLs with no changes when you have it enabled.

Layouts

ColdBox layouts are placed in a folder called /layouts by default and unless you've specified something else, will look for a file called Main.cfm.

/layouts/Main.cfm

1
2
3
4
5
6
7
8
9
10
<cfoutput>
    <html>
        <head>
            <link href="/includes/getmymail.css" rel="stylesheet" type="text/css" />
        </head>
        <body>
            #renderView()#
        </body>
    </html>  
</cfoutput>

The renderView() call is where the output from the view will be placed.

Model

Your models are your services, beans, and DAO that represent the business logic in your application.  In ColdBox, these go under a folder called /model.  I created a MailService.cfc which encapsulates getting a list of messages and getting a single message.  

/model/MailService.cfc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
component singleton {
    property name="attachmentPath" inject="coldbox:setting:attachmentPath";
    property name='sessionStorage' inject='coldbox:plugin:sessionStorage';
     
    function getAllMessages( required numeric start ) {
        // Get connection Info
        var connectionInfo = sessionStorage.getVar( 'connectionInfo' );
         
        return new pop().getHeaderOnly(
            server = connectionInfo.serverName,
            username = connectionInfo.userName,
            password = connectionInfo.password,
            port = connectionInfo.serverPort,
            maxrows = connectionInfo.msgsPerPage,
            startrow = arguments.start
        );
    }
     
    function getMessage( required string uid ) {
        // Get connection Info
        var connectionInfo = sessionStorage.getVar( 'connectionInfo' );
                 
        return new pop().getAll(
            server = connectionInfo.serverName,
            username = connectionInfo.userName,
            password = connectionInfo.password,
            port = connectionInfo.serverPort,
            uid = arguments.uid,
            attachmentpath = attachmentPath,
            generateuniquefilenames = true
        );
    }  
}

Note the singleton annotation at the top in the component definition.  This tells WireBox to only create one instance of this service that the entire application shares.  I'm also using properties to inject a reference to my attachmentPath setting as well as the sessionStorage plugin again.  No configuration is necessary for WireBox to find the MailService CFC since we've placed it in the /model convention folder.  Unfortunately, I found that Railo doesn't support the same script syntax for the CFPOP tag so I also created a RailoMailService.cfc file in the /model folder and created the following WireBox configuration file.

/config/WireBox.cfc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
component extends='coldbox.system.ioc.config.Binder' {
    function configure() {     
        // Use this to detect the CFML engine
        var CFMLEngine = new coldbox.system.core.util.CFMLEngine();
         
        // Railo uses a different script syntax
        if( CFMLEngine.getEngine() == CFMLEngine.RAILO ) {
            // This will override the default MailService mappings
            map( 'MailService' ).to( 'model.RailoMailService' );       
        }
         
        // No "else" needed for Adobe CF. WireBox will simply "find" the
        // "MailService" CFC in the "/model" folder automatically.     
    }
}

This file uses a utility built into ColdBox called CFMLEngine to detect the engine in use and conditionally overwrite the MailService mapping to point to the Railo version.

Error Handling

In the FuseBox code, there are try/catches around a lot of code in the "model" files.  If an error occurs, a custom error page is included.  

1
2
3
4
5
6
<cftry>
<cfpop  .../>
    <cfcatch>
        <cfinclude template="../view/error/connectionError.cfm" />
    </cfcatch>
</cftry>

What if an error occurs somewhere else in the request though?  What if you add new code and forget to wrap it in a try/catch.  Even worse, what if you decide to rename your error template after it's referenced everywhere?  In ColdBox, error handling is built in.  All of your code is run in a try/catch at the framework level, and there's a nice default error template that displays.  In your production settings though, you'll want to override this to a more secure page that doesn't divulge information with the customErrorTemplate setting.

1
customErrorTemplate = "includes/templates/oops_sorry.cfm"

You can read more about the exception handling provided to you in ColdBox here.

Conclusion

To see all the code, please visit this repo on GitHub: https://github.com/bdw429s/FuseBox-5.1-Sample-App-Conversion

This sample app was a little more involved than the last one, and hopefully everything makes sense even though I included a lot more code.  If clone the Git repo you can unzip the FuseBox code and open them side by side.  Please comment below if you have any questions or suggestions, and here's our list of handy resources:

 

 

Add Your Comment

Recent Entries

CommandBox 6.2.0 Released!

CommandBox 6.2.0 Released!

We are pleased to announce the release of CommandBox 6.2.0, a minor release in our CLI, Server, and Package Manager.

Download

You can download the latest version by using the upgrade command from the CLI for an in-place upgrade.  It's also available on HomeBrew, and our download page:

https://www.ortussolutions.com/products/commandbox

What's New

This rel...

Brad Wood
Brad Wood
April 01, 2025
TestBox v6.3.0 Release

TestBox v6.3.0 Release

We are excited to announce the release of TestBox 6.3.0. This version emphasizes the all-new BoxLang Reporter, now with vibrant color outputs and seamless execution through BoxLang, improving the testing experience. To benefit from these improvements, update now and ensure your testing remains reliable and efficient.

Luis Majano
Luis Majano
March 31, 2025
BoxLang Virtual Machines Now on Azure – Power Your Applications with Ease

BoxLang Virtual Machines Now on Azure – Power Your Applications with Ease

We’re excited to announce that BoxLang Virtual Machines (VMs) are now available on the Microsoft Azure Marketplace. With just a few clicks, you can now deploy pre-configured, high-performance BoxLang environments in the cloud — including the ability to run legacy and modern CFML applications using the powerful BoxLang CFML engine.

BoxLang is a modern, flexible, and scalable programming language for the JVM, purpose-bui...

Cristobal Escobar
Cristobal Escobar
March 31, 2025