Environment Control Via Interceptors
Introduction
One of the cool things about interceptors is that so much can be done with them. This little interceptor is very useful when you are dealing with multiple environments and you would like different settings or aspects according to environment. Therefore, ColdBox comes with a basic environment control interceptor that you can use for your projects. Below is a quick guide to show you how to use it.
How to Configure it?
The way to configure the environment interceptor is via your configuration file. Look below for the sample:
<Interceptor class="coldbox.system.interceptors.environmentControl"> <Property name='configFile'>config/environments.xml.cfm</Property> <Property name='fireOnInit'>false</Property> </Interceptor>
This declares that you want to use the environment control interceptor and assign a configFile property to where you environment settings xml exists. I usually place all my configuration files in my config directory. You also need to set the fireOnInit Boolean flag. This flag, tells the interceptor to fire itself on creation also. This is useful, if you are declaring a chain of interceptors that also need settings as per their environments. The default value is true. Why? Well, because, this way, all the interceptors can make use of per-environment settings. Just make sure that the first declared interceptor is this one.
That's it, this configures your application for using the interceptor, now to the fun stuff.
The Environments Configuration
In order for the interceptor to know which environments you want, where you are and what settings to override, you must fill out an xml file similar to the following:
<?xml version="1.0" encoding="ISO-8859-1"?> <!-- Declare as many tiers as you like with a unique name --> <environmentcontrol> <!-- give an environment a name and a comma delimited list of url snippets to match --> <environment name="development" urls="localhost,dev,jfetmac"> <!--ColdBoxSpecific Settings --> <Setting name="HandlerCaching" value="false" /> <Setting name="HandlersIndexAutoReload" value="false" /> <Setting name="IOCObjectCaching" value="false" /> <Setting name="DebugMode" value="false" /> <Setting name="DebugPassword" value="" /> <Setting name="ReinitPassword" value="" /> <Setting name="EnableDumpVar" value="false" /> <Setting name="EnableColdboxLogging" value="false" /> <Setting name="onInvalidEvent" value="" /> <!-- AppSpecific Settings: <Setting name="MySetting" value="Hello" /> --> </environment> </environmentcontrol>
As you can see from the sample xml, you need to define the following:
<environment> element
This element tells the interceptor to look for this environment. You can create as many environment elements as you like and it has the following attributes:
- Attributes
| Attribute | Description |
| @name | The name of the environment |
| @urls | The url snippets (comma-delimited) to look for in the CGI.HTTP_HOST |
The interceptor grabs the urls attribute and scans the CGI.HTTP_HOST variable to see if the snippets can be found. If it is, then it will set the following in the application configuration settings:
- ENVIRONMENT = The @name attribute of the environment element.
It will then read in all the Setting elements and place them in your configuration structure. You can also use complex variable declarations as defined in the Configuration Guide which by default uses JSON syntax notation.
If you would like to see the entire structure graph for all the settings that you can override, you can dump the actual configuration structure and see the path of all the variables by using the controller.getConfigSettings() method. For example, to override a particular nested setting, I can just say:
<Setting name="CacheSettings.ObjectDefaultTimeout" value="0" /> <Setting name="Datasources.myAlias.password" value="" />
You can also define settings in JSON notation:
<Setting name="Datasources" value="{'MyDSNAlias': {'Alias': 'MyDSNAlias' , 'Name': 'MyDSN', 'DBType': 'mssql', 'Username': 'dbusername', 'Password': 'dbpass'}}" />
That setting overrides all of the Datasources defined in your configuration file by using a JSON nested structure.
Extending The Interceptor
The interceptor has a separate function for environment detection called detectEnvironment. You can now extend the interceptor an just override this method and you can have your own detection schemas at your disposal. Below is the method that you can override:
<cffunction name="detectEnvironment" access="private" returntype="string" hint="Detect the running environment and return the name" output="false" > <!--- *********************************************************************** ---> <cfargument name="environmentsArray" required="true" type="array" hint="The environment array"> <!--- *********************************************************************** ---> <cfscript> for(i=1; i lte ArrayLen(arguments.environmentsArray); i=i+1){ if ( listFindNoCase(trim(arguments.environmentsArray[i].XMLAttributes.urls),cgi.http_host) ){ //Place the ENVIRONMENT on the settings structure. setSetting("ENVIRONMENT", trim(arguments.environmentsArray[i].XMLAttributes.name)); return trim(arguments.environmentsArray[i].XMLAttributes.name); break; } } return ""; </cfscript> </cffunction>
