ColdBox's Plugins Guide

Introduction

Welcome to the ColdBox plugins guide. This guide will give you a brief overview of what plugins are, what are the core plugins, how you can extend them and how you can create your own custom plugins.

What Are Plugins?

What are plugins? Plugins are cfc's that are built to extend the core framework or application functionality without hindering system performance. The main distribution of ColdBox contains several useful plugins that not only makes ColdBox a framework, but also a developer toolkit. The idea behind the plugin concept is to create a reusable and extensible architecture for developers to build applications or framework specific tasks that could be easily shared and loaded on demand within your applications and keeping true to the framework's regulations and part of the framework life cycle. This means that you can easily code plugins, completely extend your application and even share them with your friends. You can create as many plugins as you want and build a plugins' library that can be used in your applications by just specifying it on the configuration file or by using the conventions. You will then be able to get the custom plugin and use it on any of your ColdBox applications.

Not only can you use them, but ColdBox maintains their persistence for you and can do cleanup on those objects for you. Via metadata (annotations) you can tell how the plugin behaves and persists. ColdBox detects that and it will cache and persist them in its built in cache manager. You don't even have to worry about creating them, you just worry about how to use them. More free time to contribute to this project!!

Another important aspect of plugins, is that you can configure them using simple or complex settings from your configuration file and we will see some samples below.

Core Plugins

In this section I will cover the core plugins that come pre-bundled with ColdBox and have a brief explanation of each. In the next sections we will cover usage and techniques.

The main core plugins are used in order to provide several functions to your applications a part from the MVC methodology. Below is a table and brief description of each core plugin:

Plugin Description cached (timeout)
applicationstorage A facade to the application scope. Yes (Default)
beanFactory A factory that will create named beans and it will also populate beans using the request collection. Extremely useful when using an ORM or OO Domain models. Yes (Default)
cfcViewer Created originally by Oscar Areavalo. This plugin will introspect cfc's and generate documentation for them. Yes (Default)
clientstorage A facade to the client scope. It will also take care of wddx serializations for complex variables for you. Yes (Default)
cookiestorage A facade to the cookie scope. It will also take care of wddx serializations for complex variables for you. Yes (Default)
fileUtilities Deprecated to favor Utilities ---
i18n A contribution by Paul Hastings for Internationalizing your applications Yes (Unlimited)
ioc A proxy object to your Inversion of Control framework. Yes (Unlimited)
JavaLoader A jewel by Mark Mandel to load java classes Yes (Default)
logger A jewel by Luis Majano :) to support ColdBox file logging and tracing with features such as AOP Exception logging, auto-archiving and rotation to zip files, highly customizable. Yes (Default)
MTLogger A jewel by Luis Majano :) to support ColdBox file logging and tracing with features such as AOP Exception logging, auto-archiving and rotation to zip files, highly customizable, and Multi-Threaded on CF8 and BD7. Yes (Default)
messagebox A visual plugin to help render message boxes on your applications for errors, warnings, and informational messages. Yes (Default)
queryHelper A utility helper to sort and filter queries on the fly Yes (Default)
renderer The main ColdBox renderer and layout manager. Yes (Unlimited)
resourceBundle Another gem by Paul Hastings for Internationalization Yes (Unlimited)
sessionstorage A session scope manager and facade Yes (Default)
StringBuffer A wrapper to a java string buffer class No
timer A code timer for your development and timing needs Yes (5 min)
Utilities A great plugin to help on all kinds of file, system, java, etc functions Yes (5 min)
webservices A library to help you get per tier WSDL's and Web Service Objects, Refresh Stubs and more. Yes (Default)
XMLParser The Frameworks main parser for the coldbox configuration files. No
zip A wrapper to Artur Kordowski's zip object. No

This are the core plugins that are shipped with ColdBox and as you can see they are highly configurable and will help you build your applications faster. What is also important to note, is that you can extend these plugins and create your own versions of them. I know I have!! I have taken core plugins such as the messagebox and extend it to my custom plugin with custom css, images, and even storage. The possibilities are endless.

How do I use plugins?

The easiest way to use them is via one method getPlugin() which is dissected below:

Method : getPlugin([string plugin], [boolean customPlugin="false"], [boolean newInstance="false"])

Arguments:

  • plugin : string : The name of the plugin to create or retrieve
  • customPlugin : [boolean = false] : The boolean flag if this is a core or custom plugin.
  • newInstance : [boolean = false] : The boolean flag if the factory should create a new instance of the named plugin.

The other method you can use is the getMyPlugin method for retrieving only custom plugins, which in actually calls the getPlugin() method with the appropriate settings.

Method : getMyPlugin([string plugin])

This is the way that the framework provides in order for you to call and use plugins. Once you do a getPlugin call, the framework will verify that the plugin is valid, it will then check if it is in cache, if it is, it retrieves it and returns it. If the object is not in cache, it will then go ahead and instantiate it and configure it by calling the init method on it. Once this is done, the plugin will be inspecting for the caching metadata, if found, it will cache it and if not, it will just return the plugin ready for usage. This is great because with one single getPlugin() call, I can create, configure and execute a method on my plugin. Just look at the sample below:

<cffunction name="preHandler" access="public" output="false" returntype="void">
  <cfargument name="Event" type="coldbox.system.beans.requestContext">
  <cfscript>
    getPlugin("logger").logEntry("information","I am just inside the pre-handler method. #logger.getHash()#");
  </cfscript>
</cffunction> 

What have I done? Well, I have created a preHandler event that will log something to a ColdBox log file via the logger plugin. With one line, I create, configure, cache and execute the logEntry method on the logger plugin. The next time I call it, I will only retrieve from cache and execute to increase performance. You can now start to see the power behind plugins and how they can be easily brought in to your application for usage.

Code Samples

Below you can see some code snippets of useful plugin calls:

<!--- Use the fileUtilities plugin to read a file, the file is actually retrieved via the logger plugin to get the log file. --->
<cfset rc.LogFileContents = getPlugin("fileUtilities").readFile(getPlugin("logger").getlogFullPath())>

<!--- Prepare the i18n Locale --->
<cfset getPlugin("i18n").setfwLocale(getSetting("DefaultLocale"))>

<!--- Change Locale --->
<cfset getPlugin("i18n").setfwLocale(Event.getValue("locale"))>

<!--- Java loader setup --->
<cfset getPlugin("JavaLoader").setup("includes/helloworld.jar")>

<!--- Set a message Box --->
<cfset getPlugin("messagebox").setMessage("error","Error retrieveing news feed")>
<cfset getPlugin("messagebox").setMessage("warning","Warning message")>
<cfset getPlugin("messagebox").setMessage("info","User created successfully")>

<!--- Get a Web Service Object declared in your config --->
<cfset wsObj = getPlugin("webservices").getWsobj("newsfeed")>

<!--- Clear ClientStorage News --->
<cfset getPlugin("clientStorage").deleteVar("newsfeed")>

There are so many that I cannot list them all here, but if you look at the sample applications, you will get a feel of how to use them.

Custom Plugins

You can also create your own plugins to expand the framework and application functionality. You can take a look at the following guide for an in depth view of how to create: My First Custom Plugin Guide. This guide will give you a very practical way of how to create and use custom plugins. The great thing about the conventions in ColdBox is that you don't even have to declare the plugins in order to use them. Just drop them in the appropriate locations and they will be searched for and configured. No extra labor in declaring them, just use them.

So what Can I use custom plugins for:

  • As helper classes, loaded on demand and used on demand
  • UI elements for reusable tasks
  • For reusable tasks
  • Security
  • AJAX enhancing features
  • Query related
  • ANT
  • anything you can imagine.

Custom Plugins Location

All custom plugins should be placed in the plugins directory of your application. This is the location where ColdBox will look for custom plugins. However, you can also change this convention via the Dashboard or settings.xml file. All of the framework's conventions can be customized to your liking. Please see Naming Conventions Guide

|ApplicationRoot
|----+ plugins (Custom Plugins Directory)

Custom Plugins External Location

You can also declare a MyPluginsLocation setting in your configuration file. This will be a dot notation path or instantiation path where more external custom plugins can be found (You can use coldfusion mappings). So this way you can bring in an entire library of plugins for your usage on-demand. You can share plugins with your entire server and even create packages for them.

Please note that the custom convention takes precedence over the external location. So if two of the same plugins exists on both locations, the custom convention location will take precedence.

How to Use Them

You can call a custom plugin by using the following methods:

  • getMyPlugin( plugin, [newInstance:boolean=false] )
  • getPlugin( plugin, [customPlugin:boolean=false], [newInstance:boolean=false] )

So to used them it would be:

<cfset getMyPlugin('datePlugin').getToday()>

//or

<cfset getPlugin('datePlugin',true).getToday()>

Again, please see the My First Custom Plugin Guide to get an in depth look at how to create custom plugins.

Rules and Anatomy of a Custom Plugin

  • First of all, these cfc's must extend the coldbox plugin base cfc: coldbox.system.plugin
  • They must have an init method implemented as shown below.
  • They must exist in the correct plugins directory under your application. See Directory Structure or wherever you have pointed your external library to be.

Sample Custom Plugin Component Declaration

Below is a sample component declaration which can exhibit some caching parameters discussed below:

<cfcomponent name="mySecurityPlugin" hint="This is my security plugin" extends="coldbox.system.plugin" cache="true" cachetimeout="50">

  <!------------------------------------------- CONSTRUCTOR ------------------------------------------->

  <cffunction name="init" access="public" returntype="mySecurityPlugin" output="false">
        <cfargument name="controller" type="any" required="true">
        <cfset super.Init(arguments.controller) />
        <cfset setpluginName("My Security Plugin")>
        <cfset setpluginVersion("1.0")>
        <cfset setpluginDescription("A Very cool security plugin.")>

        <!--- My Custom Constructor code goes here --->

        <!--- Return instance --->
        <cfreturn this>
  </cffunction>

  <!--- All my methods go below --->

</cfcomponent>

The Caching Parameters

Since ColdBox is built with a solid cache foundation, your plugins can also be cached if needed. You will do this by adding meta data attributes to the cfcomponent tag. By default, plugins WILL NOT BE cached, unless you specifically use the cache meta data attributes to tell the framework to cache it. Caching of plugins simulates persistence, so remember this if you are planning plugins that can maintain their own persistence. This is a true flexible and awesome feature. Persistence controlled by the framework for you.

ATTRIBUTE TYPE DESCRIPTION
cache boolean A true or false will let the framework know whether to cache this object or not.
cachetimeout numeric The timeout of the object in minutes. This is an optional attribute and if it is not used, the framework defaults to the default object timeout in the cache settings. You can place a 0 in order to tell the framework to cache the handler for the entire application timeout controlled by coldfusion.

Plugin Reserved Words & Methods

ColdBox plugins are the way that you can extend the framework to do more application specific tasks or aspects around an application. For more information on plugins, please see the Plugins Guide. So lets see what variables you inherit.

Reserved Words

controller The ColdBox Controller
instance Internal private scope
instance.__hash An internal hash id for the event handler
instance.pluginName The name of the plugin
instance.pluginVersion The version of the plugin
instance.pluginDescription The description of the plugin
instance.pluginPath The current template path of the plugin location

Reserved Facade/Concrete Methods

set/getPluginName Set/Get the plugin name
set/getPluginVersion Set/Get the plugin Version
set/getPluginDescription Set/Get the plugin description
getPluginPath Get the current plugin path
abort cfabort facade
announceInterception A way to announce custom interceptions
dump cfdump facade
getColdBoxOCM Get a reference to the ColdBox Object Cache Manager
getcontroller Get a reference to the ColdBox controller
getDatasource Get a named datasource bean
getDebugMode Get the current debug mode for the user
getfwlocale If using i18N, then retrieves the current locale
getHash Get the hash
getMailSettings Get a mail settings bean
getMyPlugin Get a custom plugin
getPlugin Get a core or custom plugin
getResource If using i18N, then retrieves a resource from a resource bundle
getSetting Get a setting
getSettingsBean Geta a config settings bean
getSettingStructure Get the ColdBox or Application Settings Structure
include cfinclude facade
includeUDF A mixin injection method, so you can inject your handler with your own methods at runtime.
purgeView The ability to purge a named view from the cache
relocate Facade to cflocation
renderExternalView Render an external view
renderView Render a view
runEvent Execute a ColdBox event
setDebugMode Set the debug mode for the user
setNextEvent Relocate to another event
setNextRoute Relocate to another route
setSetting Set a setting
settingExists Check if a setting exists
throw cfthrow facade

Best Practices

Organization

Always try to package your handlers in logical directories in order for you to have a good and extensible foundation. Plugins are also objects and therefore they should have their specific identity and function. So you need to map them in the best logical way according to their functions. If you need more flexibility you can even create directories (packages) and place them in logical buckets. This is mostly used in large applications as mentioned above. So think of them as entities and how they would do tasks for you, whether programmatic or visual. Once you do this, you can come up with a very good cohesive and reusable plugin or helper model for your applications..

Init Method

Every plugin must have its own init method with its own identity and constructor code. Also, please try to add all the metadata you can.

Advanced OO Features: UDF Injections

ColdBox provides you with a way to actually inject your plugins with custom UDF's so you can change the behavior or expand on the behavior a plugin already has. This is called mixin methods and can be done via the includeUDF() method provided to every custom plugin. The method is a provided way for you to dynamically load UDF's into your plugins at runtime. You can do this in a specific method or at the initialization of the plugin via the init() method. The sample below is using the init method:

  <cffunction name="init" access="public" returntype="mySecurityPlugin" output="false">
        <cfargument name="controller" type="any" required="true">
        <cfset super.Init(arguments.controller) />
        <cfset setpluginName("My Security Plugin")>
        <cfset setpluginVersion("1.0")>
        <cfset setpluginDescription("A Very cool security plugin.")>

        <!--- My Custom Constructor code goes here --->
        <!--- Load my special UDF's for my tools .---> 
        <cfset includeUDF('includes/toolsUDF.cfm')>

        <!--- Return instance --->
        <cfreturn this>
  </cffunction>
        

The includeUDF method call will find the template and inject it to the custom plugin.

WARNING: If you try to inject a method that already exists in the plugin, the call will fail and !ColdFusion will throw an exception.

There you go, that is dynamic loading of methods in your custom plugins. A truly enhancing feature.

Conclusion

So how do you code them, well for that look at the next guides, My First Plugin Guide and also look at the Reserved Words & Methods Guide. This guide has briefly covered what ColdBox plugins are and how you can use them. For an in depth view of what each plugin can do, I suggest looking at the different guides in this wiki, the sample applications and most importantly the Plugins API. The API is the best way to see what a plugin can do for you since they are highly documented.


Copyright 2006 ColdBox Framework by Luis Majano