Вы находитесь на странице: 1из 16

ColdFusion Applications Framework

“Core”
Version 1.2

Oscar Arevalo
oarevalo@sandals.com

Last Updated: June 18, 2007


COLDFUSION APPLICATIONS FRAMEWORK...................................................1

“CORE”..................................................................................................................1

VERSION 1.2..........................................................................................................1

OVERVIEW.............................................................................................................3

APPLICATION STRUCTURE.................................................................................5

APPLICATION CONTROLLER..............................................................................7
Application Initialization...............................................................................................................................8

Restart Key......................................................................................................................................................9

GLOBAL ERROR HANDLING...............................................................................9

EVENT HANDLERS.............................................................................................10

LAYOUT PAGES..................................................................................................12

VIEWS...................................................................................................................13

SYSTEM MESSAGES..........................................................................................14

APPLICATION SETTINGS...................................................................................15

APPLICATION SERVICES...................................................................................16
Overview
This document describes version 1.2 of a very lightweight framework or skeleton for
developing Adobe ColdFusion MX applications based on the MVC approach. Rather
than describing the framework on the context of a full application implementation, this
document describes the essence or “Core” of how it works. Please note that this
framework is concerned only with the presentation layer of the application and is
independent of how other layers of the application are designed or implemented.

The framework has the following goals:

• The framework should provide a bare-bones foundation for developing modular


and extensible ColdfFusion applications while at the same time having a minimal
footprint
• The framework should not impose on the application any dependency on any of
the shared scopes (Session, Client, Server)
• Inner working of the framework mechanisms should have minimal impact on
application performance

This framework is based on the idea of breaking down an application into the following
components:

• A Controller
• Multiple Views
• Multiple Event Handlers
• One or more Layouts

Additionally the framework includes certain general features that are intended to support
the very basic functionality of any application. These features include:

• Application Settings
• Application Services
• System Messages
• Restart Key

In order to improve performance and decrease complexity, the framework requires the
application to follow certain conventions regarding directory structure and naming, as
well as the use of a few files that can be reused with little or no modification.

The Core framework allows the developer to create any type of web-based applications
ranging from dynamic websites to full multi-user intranet applications. To create
applications using the framework described on this document, the developer needs to
create the required directory structure and copy the required framework files. The
easiest way to start a new application using the framework is to expand the framework
files (provided on zip file) into the server and rename the expanded directory to the
desired name of the application. After this is done, the developer can start building on
top of the expanded file structure to complete the application.
Application Structure
Applications developed using this framework are required to adhere to a few guidelines
and specifications regarding file and directory structure and naming.

Framework files are distributed as a compressed file. The compressed file can be
expanded into the application directory and serve as the initial foundation in which the
application will be developed.

The following diagram shows the initial structure of an application:

In this diagram “app” is the name of the directory where your application is located.

The following table describes each of the directories and its purpose:
Directory Description
config This directory is used to store any configuration files used by the
application. The framework only requires the presence of
config.xml.cfm, but other files can be placed here if the application
requires them.
handlers All the event handlers are stored here. Event handlers are CFCs that
handle all of the actions or events of the application. Event handlers
must extend the eventHandler.cfc located on this directory.
images Used to keep any images used by the application, initially only
contains a few images used by other parts of the framework.
includes Contains special purpose templates and reusable files
layouts Contains the page layouts for application pages. Layouts describe
the overall structure of each page displayed; they also are
responsible for displaying the selected view.
Views Contains all application views. Views can be organized within
subdirectories if needed.

The Application.cfc template acts as the application controller. This is described in


detail on the following section.
Application Controller
The controller is an implementation of the Front Controller design pattern. In the case of
the framework this is implemented using the Application.cfc provided by ColdFusion.
The controller's job is to intercept every request to the application, process any
requested events and then select the appropriate view and layout for display.

The Controller is built as a generic component so that it can be reused by many


applications without having to modify how it works. However, since it is implemented in
the Application.cfc, some settings such as the application name must be set
appropriately for each individual application.

Besides the standard application settings defined on the Application.cfc


(clientManagement, sessionManagement, etc), there are a few framework-specific
settings that should be modified on a per application basis:

Setting Description
this.defaultEvent Name of the event to be executed when no event or
view has been passed.
this.defaultView Name of the view to be displayed when no event or
view has been passed.
this.defaultLayout Name of the layout to use. This must be non-empty
otherwise nothing will be displayed.
this.topLevelErrorRecipient Email address to which to send an email report when
unhandled errors occur.
this.topLevelErrorSender Email address to use as sender for error reports.
this.restartKey See RestartKey below.
this.configDoc Relative path to the config xml document. If
application does not require the use of application
settings or services, then this may be left empty. Path
only needs to be specified from the application root,
not the webserver root.
this.modelsPath Relative path to indicate where the application model
cfcs are located. This is used only when the getModel
function is used on the event handlers.

After the Controller finishes its execution, the control is passed to the selected Layout
Page. A layout page can be selected either by explicitly calling it on the request using the
layout parameter, or it may be set by the event handler using the setLayout() function.
If the layout page has not been explicitly set, then the framework uses the default layout
defined on the Application.cfc. It is the responsibility of the layout page to actually
invoke and display the selected view.

The following diagram illustrates the sequence of events and interactions between the
different elements of the framework for any request coming from the browser. Please
note that the onApplicationStart event is only executed when the application is first
initialized.
From the previous diagram you may see that the controller calls some predefined
methods on the ehGeneral.cfc event handler. This file must be present and must
contain the methods onApplicationStart, onRequestStart and onRequestEnd.
These methods must be defined even when the application doesn't require any specific
actions to occur at those moments.

The controller also is responsible for reading and loading the Application Settings and
the Application Services.

Application Initialization
A very important function of the controller is to initialize the application. The idea of
application initialization is to provide a place to execute tasks that need to happen only
at the beginning of the application lifecycle. The framework handles this by storing a flag
on the Application scope indicating that the application has been initialized. Handling this
at the framework level rather than at the Coldfusion engine level (via the
onApplicationStart method of Application.cfc) allows to manually restarting the
application if needed and for a better integration with the framework. When the
application is initialized, the controller executes the following events in the given order:

1. If a configuration document is provided (using the this.configDoc key) then:


a. Load and parse configuration document
b. Load application settings
c. Load application services
2. Execute ehGeneral.onApplicationStart()
3. Flags application as initialized
4. Updates the restartKey

To manually force the controller to restart the application use the resetApp=1 parameter
on the URL.

Restart Key
When working with an application that is deployed into a cluster of servers, using the
resetApp flag to restart the application on all servers, becomes a difficult and
cumbersome task since each server the reinitialization request need to be send to each
server on the cluster. Furthermore, if the application is still running, having only a few
servers restarted while others are not, could create serious problems. To address this
problem you must use the restartKey. This is a string defined at the beginning of the
application.cfc. The value of this string is hard coded into the application. At the
beginning of each request the controller will read this key and compare it with a
previously stored value on the Application scope. If the values are different then this will
force a reset of the application on the current server (just like if we had sent a resetApp
flag targeted to that unique server). After the application is reset, then the new
restartKey will be recorded on the application scope so that subsequent requests will
not cause a reset of the application.

The value of the restartKey can be any arbitrary value. This value can only be set by
explicitly declaring it on the Application.cfc.

Global Error Handling


The application controller also provides a mechanism for global error handling. When an
exception occurs within the controller, or any other part of the application and it is not
handled when it occurs, then it triggers the onError method of the Application.cfc.
This method is already implemented on the controller. The default behavior is to send an
email with the exception details to the address defined in the
this.topLevelErrorRecipient key. Additionally the application displays the content of the
includes/error.cfm template, which contains a generic error message. This template
can be modified to adapt to the look and feel of the application being developed.
Event Handlers
The event handlers are the elements in charge of performing the actual actions of the
application. They are responsible for calling the appropriate models, pass any
parameters necessary and invoke specific methods to accomplish different tasks. They
also serve the purpose of isolating the model from the environment specific to the web
application, such as HTTP-specific scopes (i.e. form / url), ColdFusion environment
scopes (session, client, application), etc.

Event handlers are implemented as CFCs that follow certain specifications:

• All event handlers must be located within the "handlers" directory.


• Must extend eventHandler.cfc
• Event handler actions that can be called by the application controller must be
exposed as public methods.

Because all event handlers extend eventHandler.cfc, they have access to a collection
of functions that allow an event handler to perform tasks such as affecting the flow of the
application, setting or changing the view and layout used, setting and retrieving values
from the request scope, and setting system messages to be displayed on the view.

Most of the time an event handler will need to pass values to be used on a view. To do
this use the function setValue(), any data element set using this function will be
available within the view by referring to the request.requestState structure and then
the proper key. This structure is also shared by the controller to store values used for the
internal workings on the application. These shared keys are: event, view, and layout. To
maintain the proper encapsulation these keys should not be set directly using
setValue() and should be managed using the appropriate functions provided by the
event handler.

The following table provides all functions available to any event handler. These functions
are inherited from eventHandler.cfc

Method Name Description


setNextEvent() Reloads the page and executes the requested event
setNextView() Reloads the page and displays the requested view
setView() / getView() Setter and getter for current view
setEvent() / Setter and getter for current event
getEvent()
setLayout() / Setter and getter for current layout
getLayout()
redirect() Façade for cflocation
throw() Facade for cfthrow
dump() Facade for cfdump
abort() Facade for cfabort
getValue() Retrieves a value from the request collection. If there is no
variable with the given name, then returns the second
argument as default
setValue() Sets a value on the request collection. Views can access
these values later by referring to the request.requestState
structure.
getSetting() Retrieves an application setting loaded from the
config.xml.cfm file. These settings are stored on the
Application scope.
setMessage() Sets a System Message to be displayed on the view or
layout. These messages are persistent across page
redirects, but may only be displayed once. Messages are
displayed on the view or layout by including the template
includes/message.cfm
getService() Returns the stored instance of the requested application
service. See Application Services.
getModel() Returns of a domain model cfc. Use this function to refer to
the model cfc using a relative path and eliminate
dependency on application mappings.

To call an event handler, the browser request must include the variable "event" which
takes as a value the name of the event handler CFC and the method to execute in dot
notation. For example to call the event doLogin on the event handler ehGeneral.cfc,
the HTTP request must have the form:

index.cfm?event=ehGeneral.doLogin

Additionally, the variable may also be passed as a form variable. For example:

<form name="frm" method="post" action="index.cfm">


<input type="hidden" name="event" value="ehGeneral.doLogin" />
...
</form>
Layout Pages
Layout pages are responsible for defining the overall structure of a page. They usually
contain the basic HTML structure and tags, style sheet declarations, navigation
placement and other elements that are consistent across pages. Additionally, the layout
page is responsible for rendering the requested view.

The Layout page is identified by the Layout variable. This variable may be set in either of
the following ways:

* By setting the property this.defaultLayout on Application.cfc.


* By explicitly passing the layout parameter to the page request.
* By calling the setLayout() function within an event handler.

The content of the layout variable is a string with the name of a cfm file within the layouts
directory without the .cfm extension.

Within a layout page use the following code to render the view:

<cfif request.requestState.view neq "">


<cftry>
<cfinclude template="views/#request.requestState.view#.cfm">
<cfcatch type="any">
An error ocurred. Do something.
</cfcatch>
</cftry>
</cfif>

Layout pages also typically handle System Messages.


Views
The views compose the visual part or “screens” of the application. One thing to keep in
mind is the difference between a View and a Layout. Usually, on every page of an
application or a website there are certain elements that remain consistent across all
pages, for example, a navigation menu, a logotype, a footer, etc; and there are also
parts of the screen that change from page to page. The Layout of the page includes all
the constant elements, while the View is the part that is different from page to page.

A View is always contained within a Layout.

The view to display is identified by the View variable. This variable may be set in either
of the following ways:

* By setting the property this.defaultView on the Controller.


* By explicitly passing the view parameter to the page request.
* By calling the setView() function within an event handler.

All views must be stored on a directory named "views".

Also, whenever requesting a view, it is only necessary to indicate the file name of the
view without the ".cfm" extension. For example, if we have a view in
/views/vwMain.cfm then a request for that view should have the form:

index.cfm?view=vwMain

Also, views can be organized in subdirectories inside the /views directory. This
provides for better organization of the application files. In this case, when requesting the
view, use the following format:

index.cfm?view=general/vwMain

This example assumes a view named vwMain.cfm inside the directory


/views/general.

The code within a view usually needs to have access to variables set within an event
handler. To do this, use the request.requestState structure. This structure will contain
all values set by the event handler in the form of keys of the structure.
System Messages
It is very common for applications to display confirmation messages or other types of
notifications to the user. Typically these messages are set by the event handlers and
displayed by the layout pages. The framework provides the functionality to set and
display these messages.

To set a message within the event handler use the setMessage() function. This function
takes two arguments, a message type and a message text. The message type can take
the following values: error, warning and info.

The file includes/message.cfm is responsible for displaying the messages. This file
needs to be explicitly called from wherever you wish to display the message; usually this
is done on the layout page. This file may be modified to display messages accordingly to
the look and feel of the current application.

A particular thing to note on how system messages are handled is that these messages
may be set and displayed on completely different HTTP requests. For example the
browser may send a request to execute an action by calling the event:
ehHandler.doSomething, and this event handler may decide that some error message
needs to be displayed to the user, but instead of just setting the view, this event handler
does a setNextEvent() to the event that prepares the view, effectively creating a
separate HTTP request. Because of this, the messages created require special handling
and cannot just be stored on the request scope. The way the framework solves this is by
setting two in-memory cookies named message_type and message_text that are
destroyed right after the system message is read and displayed.
Application Settings
An optional feature provided by the framework is the use of configurable application
settings. These are application-wide variables that may be used by each individual
application. These settings are loaded into memory by the application controller. Settings
are stored in an XML file named config.xml.cfm within the config directory.

On the configuration document, all settings must be declared as children of the


<settings> tag, which itself is a child tag of the document root: <config>.

Each setting must be defined as a string and declared in the following manner:

<setting name="sampleSetting" value="some_value" />

Where name and value are respectively the name and value of the setting. All settings
are loaded into a structure within the application scope. Event handlers may access
these settings by using the function getSetting() passing the appropriate setting
name.

The controller loads the settings only when the application is started, right before calling
the onApplicationStart method in ehGeneral.cfc. To force a reload of the settings, use
the resetApp flag with a value of true or 1. For example the following request will reset
the application and force a reload of the settings.

index.cfm?resetApp=1

Please note that these kinds of settings are independent from the internal configuration
of the framework and the use of this feature is optional.
Application Services
This feature is similar to the Application Settings except that the values stored are
instances of objects that are used to provide specific services or additional functionality
to the application. Application Services act as Singletons in the sense that the
application only uses one instance of each service. Services are stored on the
application scope and the framework handles its loading and access.

Any CFC can be loaded as an Application Service as long as it provides a public Init
method that take the role of constructor. There are no dependencies between the
framework and the CFCs used as Application Services.

To access Application Services within an event handler, use the getService() method
passing the assigned service name.

Application Services are declared on the config xml document, under the <services>
tag. This tag is a child tag of the document root. Within the services area, each service is
declared using the <service> tag. The attributes of this tag are name and class. The
first one is used to assign a name by which to refer to the service when using the
getService() function. This name can be any string value. The second attribute, class,
is used to identify the CFC that implements the service. This can be expressed in dot
notation or as a relative path starting from the application root. If the cfc is referred using
the relative path, it must include the complete file name.

When instantiating the service, the framework automatically calls the Init() method. To
determine the parameters that will be used when calling this method use the <init-
param> tag. These tags should be children of the corresponding <service> tag of the
service to which they apply. Each <init-param> corresponds to each of the arguments
that will be passed to the init method. This tag uses the following attributes:

Attribute Description
Name Name of the argument. This name must match the definition on the
method signature of the CFC. The framework calls the Init method
using named arguments.
settingName [Optional] use this argument to bind the value of the init()
argument to the value of a setting defined on the Settings section of
the config document. The value of this attribute must match the
name of the setting.

The value of the parameters is defined as the text value of the <init-param> node.
However, if the settingName attribute is used on the <init-param> tag, then the setting
value overrides the literal value.

Since the controller loads the Application Services during application initialization, forcing
an application reset will also force the reload of all services.

Вам также может понравиться