Coldfusion Framework one Tutorial

cold-fusion login framework and ColdFusion logging framework and ColdFusion testing framework and ColdFusion framework comparison best ColdFusion mvc framework
Dr.NaveenBansal Profile Pic
Published Date:25-10-2017
Your Website URL(Optional)
C H A P T E R 23 ■ ■ ■ How Base Classes Can Help You Generate Your Applications by Peter Bell Base classes don’t just make your applications leaner and quicker to develop. They can also be a great first step toward generating more of your code. This article examines what base classes are, why you should care, and how they can be used as a starting point when generating code for your applications. Base Class Basics One of the biggest problems with object-oriented programming is that it takes a lot more typing than “the good old way.” What is worse, a lot of the typing is repetitive, dull, and error-prone. For example, Data Access Objects (DAOs) are commonly used to hold your “single-record” queries (create, read, update, and delete against a single record). If you look at a DAO for a user (Listing 23-1) and compare it to a DAO for a product (Listing 23-2), you’ll see they are similar. Listing 23-1. Part of a simple user DAO cffunction name="getUser" returntype="query" output="false" hint="I return a recordset containing the requested User based on the provided User ID" cfargument name="UserID" type="numeric" required="yes" hint="The ID of the User to return" cfset var Local = StructNew() cfquery name="Local.GetUser" datasource="variables.datasource" SELECT UserID, FirstName, LastName FROM tbl_User WHERE UserID = cfqueryparam value = "arguments.UserID" CFSQLType = "CF_SQL_INTEGER" /cfquery cfreturn Local.GetProduct /cffunction 249 CHAPTER 23 ■ HOW BASE CLASSES CAN HELP YOU GENERATE YOUR APPLICATIONS Listing 23-2. Part of a simple product DAO cffunction name="getProduct" returntype="query" output="false" hint="I return a recordset containing the requested product based on the provided product ID" cfargument name="ProductID" type="numeric" required="yes" hint="The ID of the product to return" cfset var Local = StructNew() cfquery name="Local.GetProduct" datasource="variables.datasource" SELECT ProductID, Title, Price FROM tbl_Product WHERE ProductID = cfqueryparam value = "arguments.ProductID" CFSQLType = "CF_SQL_INTEGER" /cfquery cfreturn Local.GetProduct /cffunction Base classes are one way to avoid much of the repetitive typing. Imagine that ProductDAO and UserDAO both extend a BaseDAO (using the extends property of cfcomponent). You could then create a base getbyId() method that both DAOs could use. It would probably look something like Listing 23-3. Listing 23-3. getbyId base method used by both DAOs cffunction name="getbyId" returntype="query" output="false" hint="I return a recordset containing the requested object based on the provided Id" cfargument name="Id" type="numeric" required="yes" hint="The Id of the object to return" cfset var GetRecord = "" cfquery name="GetRecord" datasource="variables.datasource" SELECT variables.FieldNameList FROM variables.TableName WHERE variables.IdFieldName = cfqueryparam value = "arguments.Id" CFSQLType = "CF_SQL_INTEGER" /cfquery cfreturn GetRecord /cffunction Now, instead of writing nearly identical getUser() and getProduct() methods, you can let the base class do the heavy lifting using its generic getbyId() method, and just set the field name list, the table name, and the name of the Id field in the init() method for the UserDAO and ProductDAO, respectively. For example, Listing 23-4 shows what the init() method for the ProductDAO might look like. Listing 23-4. A sample ProductDAO init() method cffunction name="init" returntype="ProductDAO" access="public" output="false" hint="I initialize the Product DAO with Product specific parameters." cfscript var Arguments = StructNew(); Arguments.FieldNameList = "ProductID,Title,Price"; Arguments.TableName = "tbl_Product"; 250 CHAPTER 23 ■ HOW BASE CLASSES CAN HELP YOU GENERATE YOUR APPLICATIONS Arguments.IdFieldName = "ProductId"; 1 Super.Init(argumentCollection=Arguments); /cfscript cfreturn This /cffunction This method, in turn, would call the BaseDAO init() method using the Super.Init() call. Note the explicit passing of the object-specific parameters to the base class init() method to provide for encapsulation and validation. Listing 23-5 contains the BaseDAO init() method that was called in Listing 23-4. Listing 23-5. BaseDAO init() method cffunction name="init" returntype="BaseDAO" access="public" output="false" hint= "I return the initialized Base DAO." cfargument name="FieldNameList" type="string" required="true" cfargument name="TableName" type="string" required="true" cfargument name="IdFieldName" type="string" required="true" cfscript variables.FieldNameList = arguments.FieldNameList; variables.TableName = arguments.TableName; variables.IdFieldName = arguments.IdFieldName; /cfscript cfreturn This /cffunction This might not be worth the effort if there were only one method in a DAO. But since there are get(), insert(), update(), and delete() methods, being able to set just a few properties, instead of having to cut and paste all of the methods, can save you a lot of time. In addition, having only one copy of each query means that you need to update the code in only one place if you want to make a systematic change, such as adding a LastUpdatedDate property whenever you do an update. With base classes, adding a new object becomes much easier. If you need an ArticleDAO, for example, just take a copy of the ProductDAO, change a few well-named properties in the DAO’s init() method, and you’re finished. Of course, you can do the same for your business objects, service objects, controller objects, and gateway objects, which will make your application much quicker to code. It’s All About the API Creating a base class is very easy. Creating a good base class is not. The difficult part lies in coming up with the appropriate base methods with just the right arguments to be easy enough for simple cases, but flexible enough to cover most of the special cases as well. One of the best ways to write an application programming interface (API) is to examine the APIs that other people have written. It makes sense to look initially at the popular frameworks to see how they work. Want to come up with an API for your controllers? Look at Model-Glue, ColdBox, FW/1, Mach-II, and Fusebox 5 (specifically lexicons). Interested in an API for your DAOs and gateways? Check out the documentation for Hibernate, Transfer, and Reactor. 251 CHAPTER 23 ■ HOW BASE CLASSES CAN HELP YOU GENERATE YOUR APPLICATIONS A Simple Example Let’s take a simple example of a base get method for returning 0 to n records from a single database table based on a filter clause. There are no joins, group bys, aggregates, calculations, or aliases in this example. Even for this simple case, we need to be able to set which field names to return, a where filter, and an order by clause. We’re getting records from a database using a filter (the WHERE clause), so let’s call this method getbyFilter(). What might this base method look like? Take a look at Listing 23-6. Listing 23-6. getbyFilter base method cffunction name="getbyFilter" returntype="query" output="no" hint="I return a recordset containing all of the records matching the provided filter." cfargument name="Filter" type="string" required="no" default="variables.DefaultFilter" hint="The SQL Where clause (excluding the actual word 'WHERE')." cfargument name="FieldNameList" type="string" required="no" default="variables.DefaultFieldNameList" hint="The field names to be selected by the query." cfargument name="OrderBy" type="string" required="no" default="variables.DefaultOrderBy" hint="The sort order of the query." cfset var GetbyFilter ="" cfquery name="GetbyFilter" datasource="variables.datasource" SELECT arguments.FieldNameList FROM variables.TableName WHERE arguments.Filter ORDER BY arguments.OrderBy /cfquery cfreturn GetbyFilter /cffunction There are all kinds of issues with this code. Some are simple. For example, this will break if the Filter or OrderBy arguments are of zero length. Others are more profound. For instance, the query doesn’t have any cfqueryparam tags, so the important associated security and performance benefits are lost. However, this is just a simple example, so please bear with me. First, notice that all of the arguments are optional. So, if we just wanted to get a default field list with any default filters in the default order for (say) a product, we would call ProductDAO.getbyFilter(). As long as ProductDAO extends BaseDAO, it will return the default product list. Second, notice that all of the variables holding the configuration data for a given object (in the cfquery) are in the Variables scope. (The Variables scope is private within a CFC.) The Variables Define the API What does that tell us? If we use this base getbyFilter() method, and it works for most of our needs, all we need to do when adding a new object DAO is to define the object-specific parameters we saw earlier: data source, table name, default filter, default field name list, and default order by. Then we will have provided all of the information required to implement the DAO for that object, other than the few special cases we’ll always need to code by hand. We have gone from needing to copy, modify, and debug what might be hundreds of lines of code for a real-world class to just setting a few properties, simplifying and speeding the development process. 252 CHAPTER 23 ■ HOW BASE CLASSES CAN HELP YOU GENERATE YOUR APPLICATIONS Composition or Inheritance? An object-oriented purist might suggest using composition instead of inheritance. How would that work? Instead of having the classes like ProductDAO and ArticleDAO inherit the methods like getbyFilter() from a base class, they would include another object that would contain those methods. So, ProductDAO and ArticleDAO would be composed with a DAOHelper class by including the following code within their init() methods: cfset variables.DAOHelper = MyFactory.create("DAOHelper") where MyFactory is the code responsible for creating objects. We would then need to add very simple methods to the ProductDAO and ArticleDAO for each composed method. For example, ProductDAO.getbyFilter() would have just this line: cfreturn variables.HelperDAO.getbyFilter(argumentCollection=Arguments) where Arguments was a structure of all of the arguments passed to the DAO method. With composition, we have the benefit that if the DAOHelper.getbyFilter() API changed, we might need to edit only the getbyFilter() methods in our other DAOs, rather than in every single place that called those DAOs (simplifying maintenance). The downside of composition is that now we’re back to having to put a simple implementation of every single method into every single DAO, which is a lot of typing. It also means that if we want to add a new method to our DAOs, we must add a simple wrapper method to every single DAO. While we should usually favor composition over inheritance, in this case, inheritance is the appropriate tool for the job. How do I know when to use inheritance rather than composition? I like my code to pass three key tests: • Is it a DAO? A product DAO very clearly is a DAO—that is the essence of what it is and does. • Are the functions I am inheriting cohesive with the intent of the class? For example, an order should be able to return its status, but should it really know how to send an e-mail when its status changes? Clearly, the ability to perform create, read, update, and delete (CRUD) operations is essential to a DAO, so the base methods are cohesive. • Is the API to the methods likely to change? If it is likely to change, I will use composition to hide the likely interface changes within the composing class. In this case, the API to the base methods is my core DAO API and is very unlikely to change, so I am comfortable exposing those classes through inheritance, rather than encapsulating them with composition 253 CHAPTER 23 ■ HOW BASE CLASSES CAN HELP YOU GENERATE YOUR APPLICATIONS Types of Methods We can classify most methods with only a few method types. For example, getProductsinCategory() and getNewestUsers() are really just types of getbyFilter(). getUserbyEmail() and getProductbySKU() are really just types of getbyAttribute(). As you become more comfortable working with base classes, you can replace most of your custom methods with a couple of static parameter or runtime property settings and a call to a base method. For example, if you had a getbyAttribute(AttributeName, AttributeValue) base method, you might have a getProductbySKU() method (Listing 23-7). Listing 23-7. getProductbySKU() method cffunction name="getProductbySKU" returntype="query" output="no" hint="I return a recordset containing the product with the requested SKU." cfargument name="ProductSKU" type="string" required="yes" hint="The Product SKU" cfreturn variables.getbyAttribute( "SKU" , arguments.ProductSKU ) /cffunction As you substitute parameters and base method calls for your methods, it becomes much easier to use metaprogramming to generate those methods. But what is metaprogramming, and how can you use it? Metaprogramming Metaprogramming is all about writing programs that write programs, so we don’t have to do the extra coding. What we have just done is a type of metaprogramming called dynamic programming. We have written generalized code that will do different things for different objects, so that we can just provide different parameters to our dynamic code, instead of needing to write different code for each similar problem. In theory, all programming could be called dynamic programming, unless you’re just writing HTML. In practice, dynamic programming usually refers to programming that is more dynamic than that commonly being written at the time. It is a relative measure, rather than an absolute measure. The other type of metaprogramming is application generation (or code generation). The difference between dynamic programming and application generation is that when you write a code generator, you are writing code that creates a file that is saved to the file system and then executed. The benefit of code generation is that the actual code you run is simpler. It may also perform better. The downside of code generation is that you now must manage all of the generator code, either as part of your project or as a separate dependency. It is quicker to prototype a new class of solution using dynamic programming than to write and maintain an application generator. You can use simple patterns to generalize the behavior of your code and can quickly change your code if you didn’t capture the correct API the first time around. Once you have a solid working prototype using dynamic programming, you can then examine whether the application would benefit from generated code. For instance, you may decide to generate a set of object- specific DAOs instead of using your base class. The good news is that you need only three things to generate an application: an application generator (which is usually pretty simple), a template, and the metadata required to create the instances you want to generate. 254 CHAPTER 23 ■ HOW BASE CLASSES CAN HELP YOU GENERATE YOUR APPLICATIONS If you have written a base method, you already have the most difficult two of those three things How? The base class acts as the template, with a few syntactic tweaks depending on the template language you are using, and the object-specific parameters define the metadata. Drop those parameters into a database or an XML file, run it against your template, and you will be up and generating your DAOs within a few hours Summary Base classes are a great way to prototype applications, and in many cases allow for cleaner, more maintainable production code. Even if you outgrow the capabilities of your base classes for reasons of flexibility or performance, if you think of them as “prototype templates” for your application generator, and think of the properties as the metadata, you’ll be able to leverage what you learned in building your base classes, and you will be up and generating applications in no time at all. Resources Here are some resources for learning more about base classes • Wikipedia, “Superclass”: • Bell, Peter, “The Benefits of Base Classes”: 2006/6/25/The-Benefits-of-Base-Classes • Wikipedia, “Fragile Base Class”: And here are some code generator resources: • CF Template: • Illudium PU-36 Code Generator: • Rooibos (Bean Code) Generator: 255 PART 6 ColdFusion Frameworks C H A P T E R 24 ■ ■ ■ An Introduction to Frameworks by Jared Rypka-Hauer Within minutes of the first ColdFusion framework (Fusebox) being announced on CF-Talk, questions arose: Why bother? What do we need a framework for? Isn't it just more work? The questions have not been resolved, despite the fact that Fusebox is now in its fifth iteration. So we asked Jared Rypka-Hauer to take on frameworks—explain what they are and why they are useful, and delve into the differences among the many frameworks available to the ColdFusion community. I’ll never forget my first experience with ColdFusion. I bought a copy of Ben Forta’s now-ubiquitous WACK (Web Application Construction Kit) book at the suggestion of a friend and had the ColdFusion server installed and serving up the responses to queries within minutes. In less than three days I had a corporate text paging system up and running using the typical 5–10 ColdFusion tags and our group’s Lotus Notes database. That was around 1998. Today we like to think that ColdFusion is less about simple scripts and more about real programming, yet I could still sit down with someone and have him reading data from a database and displaying master/detail pages within minutes. Our beloved language has become far more flexible and is able to cater to advanced techniques without sacrificing the simple, old- fashioned techniques we’ve come to both love and hate. While we should not allow ourselves to forget that ColdFusion, at its most fundamental level, is about making complicated things easy, we shouldn’t shackle ourselves, either. We need to continue discussing advanced techniques and building our skills on the programming side of things. Frameworks are a fundamental part of advanced techniques and, fortunately, the concepts behind using any given framework are portable from one language to almost any other. Can Someone Just Tell Me What They ARE Already? Before we go digging through information about which frameworks are available, I want to address a common misconception. Frameworks aren’t magic, nor are they terribly difficult to learn. A framework is simply a collection of code and a particular methodology for blending that code into your own applications, creating a more organized application while saving you some time and effort. Frameworks answer questions such as where to put the business logic of your application, where to place your display files, and what directs the framework to take actions or display pages when an event or file is called. By taking care of many of the mundane aspects of application logic, frameworks give us much faster time-to-production on a site and a better shot at being consistent when writing our applications. All frameworks have the following two things in common: 259 CHAPTER 24 ■ AN INTRODUCTION TO FRAMEWORKS • Core files (that generally come in a zip file) • Instructions on how to get your code to work with the code provided by the framework The various frameworks out there can be divided into the following two basic groups: • Frameworks intended to deliver HTML content to a browser • Frameworks (or libraries) intended to provide services and support your applications Frameworks that Focus on HTML and the User Interface The first category of frameworks focuses on connecting back-end systems with your user interface (UI). • Fusebox • Model-Glue • Mach-II • ColdBox Most of the time, at least in the ColdFusion world, a framework used to deliver content will receive its instructions in the form of URL or form variables and XML config files. For example, URL variables such as fuseaction=blog.showentry&entryId=122 (Fusebox) or event=blog.showentry&entryId=122 (Mach-II, ColdBox, and Model-Glue) tell the code in the framework to look in a particular XML file, look up blog.showentry to get further instructions, and finally, to run the code associated with the blog.showentry fuseaction or event handler(s). That code is written by the developer and will (in this case) fetch the blog entry from the database and display it, along with any pods and special links (such as links), and perhaps update a view counter. The way this code is blended with the code supplied by the framework can reduce development time. And by creating a common language of sorts (in terms of framework-specific terminology), frameworks can also facilitate communication with other developers. Most frameworks also include certain settings that turn caching on and off to accelerate performance when the site is in production, change the way pages are reloaded or not, and alter other actions the framework itself takes as it processes requests. Fusebox Fusebox is a procedural framework that takes all the information provided by the developer via two or more XML files and compiles a complete page of CFML for each distinct fuseaction URL variable. These pages, once compiled, are used for subsequent requests unless the developer informs the framework otherwise. Fusebox contains facilities to make using CFCs (ColdFusion Components) quite easy, so “procedural framework” isn’t meant to imply that object-oriented practices have no place in Fusebox applications. Fusebox 5.5.1, which was released in March 2008, offers more tools than previous versions for using CFCs, along with many new enhancements to the framework that make application management that much easier. For example, application startup hooks have been added (AppInit and fusebox.appinit. cfm) that control tasks the application must perform the first time one of its pages are requested; also, 260 CHAPTER 24 ■ AN INTRODUCTION TO FRAMEWORKS the XML files have been made optional by adopting a set of conventions for locating code instead. Fusebox applications have a reputation for being incredibly fast and performing extremely well under load. And because the process of compiling a whole page out of several smaller chunks of code only happens once (at least in production mode), there’s actually very little of the framework involved in the request after the first run of the fuseaction. It doesn’t do quite as well in situations where you may have dynamic execution paths, but for sites with static layouts and very little need for dynamic event handling, Fusebox is very hard to beat. When should you use Fusebox? Well, that’s easy. You should use Fusebox if you’re still developing your applications in a page model but want to make a move toward more modular applications, or if you want to use a framework but have a mixed-ability team with persons that might not be comfortable with an object-oriented approach. You can organize your applications into various architectural patterns, such as Model-View-Controller (MVC), more easily with something like Fusebox than you can by rolling up your own architecture—and you can learn a lot about application architecture in the process. Fusebox is also quite handy for the following: • Podded static layouts with dynamic content • Sites requiring support for plug-ins • Sites migrating directly from a procedural page model (things such as blogentrylist.cfm or blogentrydetail.cfm become index.cfm?fuseaction=blog.showentrylist or index.cfm?fuseaction=blog.showentrydetail) Model-Glue Model-Glue is a relative newcomer to the frameworks scene, with a version 3.0 released in August 2009 after an initial 1.0 release in 2005. It has gained rapid acceptance in the ColdFusion community because it makes the transition to a purely object-oriented framework much easier than rolling your own object- oriented application architecture. Originally written by Joe Rinehart, who made a great effort to provide rich features while keeping the framework as simple as possible, it’s gained enough ground (and features) that it’s now supported by a team of volunteers led by Dan Wilson. In Model-Glue, events replace pages and are triggered via an event variable passed through the URL or form. If at one point you had a page called blogentrylist.cfm you would, in the Model-Glue world, have an event that looks like index.cfm?event=blog.showentrylist instead. Model-Glue is also based on MVC. A developer creates an application by writing CFCs that comprise the model section and CFM templates that comprise the views. He then writes CFCs that extend the framework’s core controller CFC to provide interaction between the two. When an event is requested, any number of controller methods are fired that access data in the application or session scopes, the database, or from other data sources. Events also include views to render the final output to the browser. For more detail on how this all works, see the Model-Glue Fundamentals article in Chapter 27 of this collection. The other guiding design principle behind Model-Glue is the concept of implicit invocation (II). This means that if the getProductsList message is broadcast, for example, all controller methods configured in the Model-Glue config files’ controller section listening for the getProductsList method will fire. To put it in more tangible terms, if clean the kitchen is a message broadcast by the mom.isTired event, then any subtasks (such as sweep the floor and load the dishwasher) registered under the KidController will fire. Implicit invocation abstracts a larger task, such as products.list, into smaller tasks, such as get products query and render products list page, by making it the listener’s responsibility to respond instead of the broadcaster’s responsibility to delegate explicitly. 261 CHAPTER 24 ■ AN INTRODUCTION TO FRAMEWORKS When should you use Model-Glue? If you’re familiar with CFCs and want to take a crack at an object-oriented framework, Model-Glue is definitely a bit easier for the newbie to get his or her head around than Mach-II. Model-Glue finds its strength in simplicity and a limited number of XML files that make it possible to see what the entire application is doing step-by-step without looking anywhere else. Mach-II Mach-II was originally created as an advanced version of Fusebox in 2003 and is currently at version 1.8. Like Model-Glue, Mach-II is an implicit invocation framework. It provides some extended functionality beyond that of Model-Glue, such as programmatic access to its event queue, plug-in points, and filters that are used to alter the instructions to be executed as a request is processed. This adds up to a potentially more powerful framework. But at first blush, Mach-II is more complex and harder to understand than the alternatives and, consequently, may be harder to implement according to best practices. The core components of a Mach-II application are listeners, filters, and the event, and you tie these CFC-based objects together using a rich XML syntax. Mach-II event handlers can check the status of anything in the environment, access the currently queued batch of instructions waiting to be processed and change its contents, call upon objects in the model to get data in or out of a database or other data store, redirect the application’s flow from the current event to a new event, and any number of other tasks. The framework’s richness is largely due to the number of options available when building your own application in Mach-II, which, in many ways, bears some similarity to a J2EE application’s structure. So it fits well in the same sort of environment in which J2EE thrives. You should try Mach-II if you’re accomplished with CFCs and want to take a crack at something new. Or, if you are familiar with computer science terminology and Java design patterns, it should feel very homey. If you’re familiar with Model-Glue and want to add another tool to your toolbox, it’s a good next step. It does provide some industrial-strength functionality, but it’s often a toss-up between Model- Glue and Mach-II in terms of choice for a project. It usually comes down to developer preference. Mach- II has many options and can yield many CFC files, but is quite powerful. ColdBox ColdBox, written by Luis Majano and originally released to the public in 2006, favors convention over configuration and can be used without a config file by placing CFCs in particular directories using a particular naming convention—just like the no-XML approach offered by Fusebox 5.5. It has a very robust feature set, lots and lots of extension points (including a plug-in API), and a strong internal event model. And some say that its biggest claim to fame is the volumes of documentation out there on ColdBox, most of which, remarkably, was created by Luis himself. ColdBox does basically everything the other frameworks do, with one significant difference: Without plug-ins or some other sort of modification it’s not implicit invocation. It’s explicit invocation, which means you have to abide by naming conventions to guide your application’s execution path through each request. Is this better or worse? Neither, really. But it is different and worth mentioning. Generally people either love ColdBox or hate it based on whether convention over configuration rings true for them. ColdBox, like most other frameworks, has the capacity to be simple or extremely robust and complex depending on how it is used. It is, however, best used by those with at least minimal experience with CFCs. 262 CHAPTER 24 ■ AN INTRODUCTION TO FRAMEWORKS Back-End and Service Frameworks Some frameworks aren’t intended to deliver HTML-based content to the end user. They’re designed to make it easier to interact with databases and provide services to your applications and clients, while lessening the code required by the developer. These include • ColdSpring • Reactor • Transfer This type of framework receives instructions via code written by the developer rather than through a URL or form variable. By calling some fairly simple code, the framework can be set up to access data sources such as databases and libraries of other objects. Most of the time, the code required looks something like the following: cfset reactor=createObject("component","reactor.reactorFactory").init("reactorConfig.xml") cfset User = reactor.createRecord("User").load(url.userId) In this case, I’m creating an instance of the ReactorFactory (which is used to create instances of other objects that represent rows in your database), and then accessing all the data in the User table for a record that has an ID value of 1. Reactor is configured via an XML file, which is the file referenced in the first line of the snippet (reactorConfig.xml). ColdSpring also uses an XML file for configuration and has very similar syntax to the first line of the snippet. Transfer is also similar in syntax, but uses two XML config files rather than one. These frameworks reduce the amount of code a developer has to write to get a particular subsystem within an application up and running, like reading from or saving data to a database (Reactor, Transfer) or managing the CFCs that provide services to your actual application code (ColdSpring). ColdSpring ColdSpring is meant to manage CFCs in the application or server scopes and to make it much easier to interconnect various CFCs than if you were writing all the code by hand. ColdSpring also makes remoting a lot easier when providing ColdFusion services to Flash or Flex movies and Ajax clients. In addition, ColdSpring provides tools to use aspect-oriented programming (AOP), which is far beyond the scope of this introductory article. Suffice it to say that AOP can be a very valuable tool for injecting standard behaviors into your CFCs. Reactor Reactor, a framework authored by Doug Hughes and now managed by Mark Drew, is used to read and save data from a database—it has a robust code-generation library that allows you to read a record from a database in as little as five lines of CFML. It features one XML configuration file and can read records from a table across link tables; read, save, and delete records; and aids in creating a CFC-based object model out of your database schema. Obviously this means that your objects are directly related to your database design, and Reactor may not always be suitable. But in a majority of situations Reactor is an ideal tool to get you off the ground with an object-oriented framework by creating your objects for you and giving you quick and easy access to your database. 263 CHAPTER 24 ■ AN INTRODUCTION TO FRAMEWORKS Transfer Transfer, a framework authored by Mark Mandel, is also used to read and save data from a database. Like Reactor, it can read records from a table across link tables, and read, save, and delete records. Transfer provides options for adding your business object methods to your persistence code either by specifying methods directly in one of the XML configuration files or by using the decorator design pattern, keeping business methods separate but allowing Transfer to blend the resulting code. Transfer features a sophisticated caching system and, like Reactor, now offers integration with Model-Glue:Unity for scaffolding and generic data messages. Transfer is worth considering as an alternative to Reactor. Summary As you can see, ColdFusion has an active and involved developer community and a growing and robust set of development tools. In terms of HTML-based UI frameworks, there is enough variety to provide a solution for almost any preference. And as for back-end or service frameworks, we have a powerful set of tools at our disposal, all of which are written by developers to solve pain points experienced by developers. The future is shaping up brightly for ColdFusion programmers with a wealth of powerful tools at our disposal and an array of options that should fit nearly any project. 264 C H A P T E R 25 ■ ■ ■ Fusebox 5 Fundamentals by Sean Corfield Updated by Jeff Peters Fusebox 5.5 is the latest release of ColdFusion’s oldest and most popular application framework. This article introduces Fusebox. And for those who have been using Fusebox 4, 4.1, or 5, it covers what’s new in Fusebox 5.5. Fusebox—What and Why Let’s start by defining what we mean by an application framework in the context of Fusebox. An application framework is a set of files that provides two things: • Reusable code that is common across most web applications • A standardized structure for your applications so that maintenance is easier Fusebox has been designed specifically to help you build more maintainable applications, regardless of your skill level with ColdFusion. Whether you write procedural code or object-oriented (OO) code, and whether you are a novice or an expert, Fusebox can support your style of programming. This makes Fusebox particularly attractive to development teams with members who have varying skill levels or use different programming styles, encompassing both procedural and OO approaches. Fusebox tries hard not to enforce a particular programming style, but it strongly encourages best practices such as separating display code, database code, and other business logic. Fusebox supports the widely used Model-View-Controller (MVC) design pattern, but does not force you to use it. Fusebox supports using ColdFusion Components (CFCs) in your application, but again, does not force you to do so. 265 CHAPTER 25 ■ FUSEBOX 5 FUNDAMENTALS Fusebox Concepts The basic metaphor behind Fusebox is a practical, everyday one: the electrical circuits in your home. In the same way that electricity flows into your house through a central fusebox and is then routed to individual circuits that control related appliances, the Fusebox application framework has a central control point— the fusebox—and organizes code into circuits containing related functionality. For example, a task manager application might have a circuit that handles user identity and a circuit that handles tasks. As the application grows, new circuits can be incorporated, each containing a group of related functionality. If you build a new application, you may be able to reuse a circuit from a previous application, such as user identity. All requests come through the central fusebox by way of a standard URL or Form variable, often called fuseaction. The value of this variable specifies which circuit to route the request to and which fuseaction to invoke within that circuit. Here’s an example that specifies that the login fuse action within the user circuit should be executed: index.cfm?fuseaction=user.login Within a fuseaction, you can specify that Fusebox execute multiple operations, using verbs in an XML file for each circuit. This could be as simple as including a ColdFusion source file using the include verb, or as complex as conditional and looping control logic, using the if and loop verbs, for example. Fusebox has a very small set of verbs that allows you to perform basic control logic. This makes the Fusebox syntax easy to learn. Versions of Fusebox prior to 4 used a file called fbx_switch.cfm to define the actions, and didn't have formalized verbs. Fusebox 4 introduced the XML vocabulary with formalized verbs, and used the circuit.xml file to contain them. As of Fusebox 5.5, you can choose to omit the XML file and use either a CFC or a directory containing .cfm files to represent a circuit, as long as you follow a convention for organizing your code. This makes Fusebox 5.5 a good choice for programmers who like the style of earlier Fusebox versions, as well as those who prefer the XML-based style. For example, the preceding fuseaction example could be implemented as user.cfc with a login() method or as a user directory with a login.cfm file. This convention-over-configuration approach follows the lead of frameworks such as Ruby on Rails. In keeping with the electrical metaphor, Fusebox refers to any included ColdFusion files as fuses to emphasize their intended small, atomic nature. In addition, Fusebox encourages the use of a file- naming convention to remind developers to separate their code appropriately. Files containing display logic (and HTML) are usually given the prefix dsp (for display) or lay (for layout); files containing database queries are usually given the prefix qry (for query); and files containing other business logic are usually given the prefix act (for action). In the first few releases of the Fusebox framework, all of this was very much just convention, with only a few core files in the framework. With Fusebox 4, the structure became more formalized with the introduction of XML files to specify the fusebox itself—the set of circuits in the application and the various parameters of the framework—and to specify the fuseaction code in each circuit. 266 CHAPTER 25 ■ FUSEBOX 5 FUNDAMENTALS Returning to our task manager application, we might choose to organize our code like this: Application.cfm index.cfm fusebox.xml user/ circuit.xml dsp_login.cfm … other CFML fuse files task/ circuit.xml dsp_task_list.cfm qry_task_list.cfm qry_update_task.cfm … other CFML fuse files In this structure, the index.cfm file includes the main Fusebox core file, the fusebox.xml file specifies where to find the user and task circuits (and other application parameters), and the circuit.xml files specify the various fuseactions in the circuits. Here, we have just two circuits: one containing all of the fuses related to user identity and the other containing all of the fuses related to task management. We can see a display fuse in the user circuit that would contain the login form. In the task circuit, we see query fuses that fetch tasks and update a task. There would be a number of other fuse files that contain the rest of the logic and display code for the application, but the preceding outline should give you a sense of how a Fusebox application is structured. As noted, Fusebox 5.5 offers the option of omitting fusebox.xml and instead having circuits determined by convention. A no-XML version of the same task manager application might look like this: Application.cfm index.cfm user/ showLogin.cfm dsp_login.cfm … other CFML fuse files task/ showTaskList.cfm addTask.cfm dsp_task_list.cfm qry_task_list.cfm qry_update_task.cfm … other CFML fuse files 267 CHAPTER 25 ■ FUSEBOX 5 FUNDAMENTALS Still another approach to the same application is to use CFCs to contain circuits, which might look like this: Application.cfm index.cfm controller/ user.cfc showLogin() method task.cfc showTaskList() method addTask() method model/ m_user.cfc m_task.cfc qry_task_list.cfm qry_update_task.cfm … other CFML fuse files view/ v_user.cfc v_task.cfc dsp_login.cfm dsp_task_list.cfm … other CFML fuse files Operations on tasks might be protected by a security check. We might require that users are logged in before they can use the task manager. We may want to execute the user.authenticate fuseaction prior to any fuseaction in the task circuit, for example. Fusebox provides an easy way to do this by specifying prefuseaction and postfuseaction operations on each circuit: prefuseaction do action="user.authenticate"/ /prefuseaction Fusebox would then automatically run this fuseaction before executing any other fuseaction in the task circuit. user.authenticate would check that the user is logged in and, if not, would cause a redirect to the user.login fuseaction. This modularity can allow developers to reuse whole circuits in other applications. In the no-XML approaches, a circuit CFC may contain a prefuseaction() method, and a circuit directory may contain a prefuseaction.cfm file. Fusebox Benefits The simple structure and organization of a Fusebox application make maintenance easier by allowing any developer who is familiar with the framework to pick up the code and get a sense of its purpose just by looking at the circuit layout and, within each circuit, the available fuseactions. Similarly, the file- naming convention allows developers to quickly locate code and make changes in a systematic way. 268

Advise: Why You Wasting Money in Costly SEO Tools, Use World's Best Free SEO Tool Ubersuggest.