Blog

ColdBox 3.0.0 Milestone 4 released!

Luis Majano January 19, 2010

Spread the word

Luis Majano

January 19, 2010

Spread the word


Share your thoughts

WOW! This one took a while but finally our M4 release is now available. So is this a final release, beta, or what? Well, we are taking off the beta name and will use our Milestone release as it is now deemed production ready even though I see a lot of users already running production sites with 3.0.0 Beta. Anyways, this milestone release has tons of fixes and updates in preparation for our next milestone which we should introduce in the coming months in preparation for a Release Candidate in Mid or Late April. Our milestones are evolving as planned and our core is getting more solid and solid with each release. This one especially really tightens the bolts on a lot of features introduced since the first betas. So let's start looking at what we did. However, please look at the tickets that have a (COMPATIBILITY) tag on them, if they do, then this means that this release has changed behavior from previous releases and you must see if you use that particular piece of code because most likely it needs to be updated. Please bear with us as all our docs are been reviewed for updates and more are added every day. Our new wiki is also online, powered by CodexWiki of course, and it will contain only 3.0.0 documentation. The 2.6.4 and less docs will remain in the orginal location. Here are the tickets for this milestone:

 

748 SES can now be configured to use logbox debugging using its class category Fixed
835 i18n update locale methods: setfwLocale(), getfwLocale() Fixed
841 Add a button to the debugger to turn debugging OFF Fixed
844 Debugger panels url location discovery Fixed
853 resource bundle plugin update to support concurrency issues, default locales and default values when getting resources Fixed
877 handlerservice not reacting consistently on invalid events when handler/event is invalid Fixed
887 remove purgeView() calls, they don't make sense anymore as all this is done via the cachemanager (compatibility) Fixed
893 Enhancement of request captures of variables in request context, so it can be called on demand. Fixed
903 New interception point onReinit so you can tap when the framework reinits Fixed
904 New interception point: applicationEnd fired when the onApplicationEnd fires on Application.cfc Fixed
905 New global event handler: ApplicationEndHandler Fixed
906 ConfigBean: When you call getKey() with a non-existent key and no default, it would be nice to have the key name in the exception: Fixed
908 New private metadata variable: currentRoutedURL tells you the routed url path, also event.getCurrentRoutedURL() is available. Fixed
909 All current metadata variables are now stored in the private request collection Fixed
912 Add a view argument to renderLayout(view), so it can be used within a alacarte layout for rendering Fixed
914 environment interceptor ability to override cache settings Fixed
921 ability to load coldbox applications via a Coldbox.cfc, no more xml! Fixed
922 New interception points for view rendering: preViewRender, postViewRender Fixed
924 renderView(cacheSuffix), setView(cacheSuffix) now take in a cacheSuffix argument so you can add dynamic suffixes to the cacheable entry. Useful for multi-domain instances. Fixed
925 coldbox js and css is now compressed for faster loading and usage Fixed
926 renderer optimization thanks to non-cacheable instances Fixed
929 xss holes on bug reporting template with usage of cgi information Fixed
934 New CF9 ORM Sample App: TaskManager Fixed
935 New Base ORM EventHandler tied to ColdBox for usage on ORM enabled apps Fixed
936 BeanFactory removal of debugmode arguments and settings. This is now controlled by logBox (Compatibility) Fixed
938 small bug on inline styles for debugger: need the type attribute on the style tag Fixed
939 Remove flash messagebox messages after rendering, not removing now. Fixed
942 Thanks to Kalen Gibbons adding a second set of pre/post observation points for actions in handlers, pre{action} and post{action} Fixed
943 debugger now shows private request collection tracking and cutoff string is 5000 chars Fixed
944 base test case can get the current flash scope: getFlashScope() Fixed
945 bug when removing private rc variables, not removing as no private argument passed Fixed
946 DSL marker for arguments and setters is now "inject" instead of "_wireme" for consistency. (COMPATIBILITY) Fixed
947 sessionEnd interception point not receiving all reference variables, now it does same as session end handler: sessionReference, applicationReference Fixed
948 Utilities plugin not marshalling extended arguments when doing JSON marshalling Fixed

 

The major updates we will discuss, the rest are fixes that you can read the ticket notes if you are interested.

New ColdBox.cfc for configurations, NO MORE XML!

You heard right, no more XML in ColdBox. You can now configure the entire application using our new ColdBox.cfc which is a simple CFC that you place in your config folder with some cool methods and variables you set. No need to extend or anything, we mix it for you and it is about 5 times faster to load an application with this approach than with XML. Not only that, but we added environment detection built in, no more environments xml or interceptor. So how does it work. Well, you have to create a method called configure() which is called to configure your application. Inside of this method you can set the following elements:

  • coldbox : struct of coldbox settings
  • settings : struct of your settings
  • conventions : struct of custom conventions
  • environments : struct of environment patterns to listen to
  • ioc : struct of ioc factories
  • models : struct of model settings
  • debugger : struct of debugger settings
  • mailSettings : struct of mail settings
  • i18n : struct of i18n settings
  • bugTracers : struct of bug tracer reports
  • webservices : struct of webservices
  • datasources : struct of datasources
  • layoutSettings : struct of layout settings
  • layouts : struct of layout definitions
  • cacheEngine : the cache engine settings
  • interceptorSettings : the main interceptor directives
  • interceptors : an array of interceptor declarations

We also create some objects and variables in the object's variables scope:

  • controller : A reference to the coldbox controller
  • AppMapping : The AppMapping of the application
  • logBoxConfig : The logBox configuration object so you can configure the logging for your application

You can also create a method called: detectEnvironment() that if declared the framework will call it to figure out on what environment you are on. You only return a string with the name of the environment. The framework will then look for a method of the same name as your environment can call it! Cool! So if you do this: environments = { // The dev environment is used whenever the cgi.http_host begins with cf8 or railo dev = "^cf8,^railo" }; function dev(){ //override or declare new stuff here }

That's it, if the dev environment is detected, then the dev() method is called. So here is a sample config:

/** structures to create for configuration - coldbox - settings - conventions - environments - ioc - models - debugger - mailSettings - i18n - bugTracers - webservices - datasources - layoutSettings - layouts - cacheEngine - interceptorSettings - interceptors Available objects in variable scope - controller - logBoxConfig - appMapping (auto calculated by ColdBox) Required Methods - configure() : The method ColdBox calls to configure the application. Optional Methods - detectEnvironment() : If declared the framework will call it and it must return the name of the environment you are on. - {environment}() : The name of the environment found and called by the framework. */ // Configure ColdBox Application function configure(){ // coldbox directives coldbox = { //Application Setup appName = "Your app name here", eventName = "event", //Development Settings debugMode = true, debugPassword = "", reinitPassword = "", handlersIndexAutoReload = true, configAutoReload = false, //Implicit Events defaultEvent = "General.index", requestStartHandler = "Main.onRequestStart", requestEndHandler = "", applicationStartHandler = "Main.onAppInit", applicationEndHandler = "", sessionStartHandler = "", sessionEndHandler = "", missingTemplateHandler = "", //Extension Points UDFLibraryFile = "includes/helpers/ApplicationHelper.cfm", coldboxExtensionsLocation = "", pluginsExternalLocation = "", viewsExternalLocation = "", layoutsExternalLocation = "", handlersExternalLocation = "", requestContextDecorator = "", //Error/Exception Handling exceptionHandler = "", onInvalidEvent = "", customErrorTemplate = "", //Application Aspects handlerCaching = false, eventCaching = false, proxyReturnCollection = false, flashURLPersistScope = "session" }; // custom settings settings = { }; // environment settings, create a detectEnvironment() method to detect it yourself. // create a function with the name of the environment so it can be executed if that environment is detected // the value of the environment is a list of regex patterns to match the cgi.http_host. environments = { //development = "^cf8.,^railo." }; //LogBox logBoxConfig.appender(name="coldboxTracer",class="coldbox.system.logging.appenders.ColdboxTracerAppender"); logBoxConfig.root(levelMax=logBoxConfig.logLevels.INFO,appenders="*"); logBoxConfig.info("coldbox.system"); //Layout Settings layoutSettings = { defaultLayout = "Layout.Main.cfm", defaultView = "" }; //cacheEngine cacheEngine = { objectDefaultTimeout = 60, objectDefaultLastAccessTimeout = 30, reapFrequency = 1, freeMemoryPercentageThreshold = 0, useLastAccessTimeouts = true, evictionPolicy = "LRU", evictCount = 1, maxObjects = 100 }; //Interceptor Settings interceptorSettings = { throwOnInvalidStates = false, customInterceptors = "" }; //Register interceptors as an array, we need order interceptors = [ //Autowire {class="coldbox.system.interceptors.Autowire", properties={} }, //SES {class="coldbox.system.interceptors.SES", properties={} } ]; /* //Register Layouts layouts = { login = { file = "Layout.tester.cfm", views = "vwLogin,test", folders = "tags,pdf/single" } }; //Model Integration models = { objectCaching = true, definitionFile = "config/modelMappings.cfm", externalLocation = "coldbox.testing.testmodel", SetterInjection = false, DICompleteUDF = "onDIComplete", StopRecursion = "", parentFactory = { framework = "coldspring", definitionFile = "config/parent.xml.cfm" } }; //Conventions conventions = { handlersLocation = "handlers", pluginsLocation = "plugins", viewsLocation = "views", layoutsLocation = "layouts", modelsLocation = "model", eventAction = "index" }; //IOC Integration ioc = { framework = "lightwire", reload = true, objectCaching = false, definitionFile = "config/coldspring.xml.cfm", parentFactory = { framework = "coldspring", definitionFile = "config/parent.xml.cfm" } }; //Debugger Settings debugger = { enableDumpVar = false, persistentRequestProfilers = true, maxPersistentRequestProfilers = 10, maxRCPanelQueryRows = 50, //Panels showTracerPanel = true, expandedTracerPanel = true, showInfoPanel = true, expandedInfoPanel = true, showCachePanel = true, expandedCachePanel = true, showRCPanel = true, expandedRCPanel = true }; //Mailsettings mailSettings = { server = "", username = "", password = "", port = 25 }; //i18n & Localization i18n = { defaultResourceBundle = "includes/main", defaultLocale = "en_US", localeStorage = "session", unknownTranslation = "**NOT FOUND**" }; //bug tracers bugTracers = { enabled = false, bugEmails = "", mailFrom = "", customEmailBugReport = "" }; //webservices webservices = { testWS = "http://www.test.com/test.cfc?wsdl", AnotherTestWS = "http://www.coldbox.org/distribution/updatews.cfc?wsdl" }; //Datasources datasources = { mysite = {name="mySite", dbType="mysql", username="root", password="pass"}, blog_dsn = {name="myBlog", dbType="oracle", username="root", password="pass"} }; */ }

You can also check out the all new application templates which have the new CFC configuration object.

Localization & Internationalization Major Updates

Our localization, i18n and resource bundle plugins have been majorly overhauled for improvements, thread concurrency, optimizations and fixes. Paul Hastings' contributions have really made a difference and we have improved them tremendously for this release. You can also now request resources from the bundles and even pass defaults and specific locales instead of looking at the user's locale: #getResource("btn_info","NOT FOUND","en_US")#

New Handler Before and After Action Advices: pre{Action} and post{Action}

Thanks to Kalen Gibbons and our wild discussions, we found use cases to create this functionality. You can now create before and after advises (preHandler,postHandler) but on an action level. So if you are about to request an action called "index" then the following will apply:

  • Execute preHandler() if it exists
  • Execute preIndex() if it exists
  • Execute index()
  • Execute postIndex() if it exists
  • Execute postHandler() if it exists

So now you can create two new method signatures according to the requested action and ColdBox will execute them for you.

Autowire Compatibility Warning

  • The default DSL marker for autowiring using constructor arguments and setter methods used to be called "_wireme", which you can programmatically change to whatever you want by setting the setting: "beanFactory_dslMarker". However, now for consistency purposes the default injection name is "inject". This is now consistent framework wide. If you need something injected, then all you need to say is "inject" or "inject={DSL}".

ColdBox Debugger

  • URL discovery fixes when using SES and non-SES url links, css and jss minifications, html updates, and new cool buttons.
  • You can also now see in your debugger the current route that was detected and the current routed URL
  • Private request collection can now be tracked and viewed
  • Outputs of collection tracking are now limited to 5000 chars

onInvalidEvent Reworking and Consistency

If you use onInvalidEvent, you already know that it intercepts whenever an event is invalid. This means that the handler requested does not exist or the action requested does not exist. In pre M4, they both reacted differently and there was no consistency on the two exceptions. They now do. So whenever a handler or action is invalid, M4 will set the "invalidevent" in the private request collection, log it and override the event so you can now execute your onInvalidEvent.

New Interception Points:

You can now intercept on the following new points:

  • onReinit : Whenever the application is reinitialized you can listen to it
  • applicationEnd : Whenever the application is finalized via onApplicationEnd() in Application.cfc you can listen to it
  • preViewRender : You can now listen when ANY view is about to be rendered. You also get as data all the arguments of the rendering.
  • postViewRender : You can now listen when ANY view has been rendered in the Renderer plugin but NOT yet sent for output. You get all the arguments of the rendering plus the rendering content. You can alter the view if necessary, do caching, or whatever you like.

New Global Event Handlers:

  • missingTemplateHandler : So you can intercept ColdFusion 8's onMissingTemplate(). This handler event is called whenever the missing template is detected. You receive the missing template in the request collection.
  • applicationEndHandler : You can now execute an event whenever the application ends.

Request Context Updates

  • Fixes on validating if a value is in the private request collection
  • New method: event.getCurrentRoutedURL() which gives you the routed URL via SES
  • All of a request's metadata like currentView, currentLayout, etc are now stored in the private request collection (COMPATIBILITY)
  • You can now also pass in a "cacheSuffix" to setView() operations. This allows you to modify the cache key when rendering views. Incredibly useful for multi-domain applications.

Rendering Updates

  • The Renderer has been optimized and it has significant rendering improvements in speed.
  • The renderLayout method now can take also a view argument: renderLayout(layout,view). This basically funnels the view argument so you can use it in your layouts for a la carte renderings: <cfoutput>#renderView(arguments.view)#</cfoutput>
  • You can now also pass in a "cacheSuffix" to renderView() operations. This allows you to modify the cache key when rendering views. Incredibly useful for multi-domain applications.

CF9 ORM

  • We have included a cool CF9 ORM sample application called TaskManager that even uses our new ORM event handlers
  • New CF9 ORM Event Handler. You can build a CF9 ORM event handler that extends our core event handler: coldbox.system.orm.hibernate.EventHandler that can give you a bridge into your ColdBox application (as long as it exists within your app). You can then bridge into the ColdBox app and request for anything you like. But not only that, you can annotate your event handler with some metadata and make it behave even more awesome. How awesome? Entity Injector Awesome! Yes, your Event Handler can be activated so it can autowire your entities with dependencies by using our awesome ColdBox DSL and BlenderBox dependency injection framework.

EventHandler Metadata To activate Entity Injector

  • @injector : Boolean [false] You must set it to true to activate the injector on PostLoad()
  • @injectorSetterInjection : Boolean[false] You must set it to true to let BlenderBox autowire it by setter injection alongside cfproperty injections
  • @injectorStopRecursion : String[] A list of classes of when to stop recursion for looking for dependencies
  • @injectorInclude : String[] A list of entity names to include in the injecting process, if entity is not found here then it is not injected
  • @injectorExclude : String[] A list of entity names to exclude from the injection processes.

You can find a demo of this functionality in the TaskManager sample application or in the wiki docs: http://wiki.coldbox.org/wiki/Extras:CFORM.cfm So these are the major updates to this Milestone release. Enjoy it and continue to support ColdBox as 3.0.0 is revolutionizing!

Add Your Comment

Recent Entries

Partner with BoxLang and Ortus at Into the Box 2025: Empowering the Future of Modern Software Development!

Partner with BoxLang and Ortus at Into the Box 2025: Empowering the Future of Modern Software Development!

At Ortus Solutions, we’ve always been at the forefront of innovation in the ColdFusion ecosystem. From pioneering modern ColdFusion practices to developing cutting-edge tools and frameworks, we’ve been passionate to help and sup[port the community into shaping the future of web development.That’s why we decided to build BoxLang, our new JVM programming language that not only builds on the strengths of ColdFusion but takes modern software development to the next level.

Maria Jose Herrera
Maria Jose Herrera
December 23, 2024
Why BoxLang When You Have Kotlin, Groovy, Scala, and more…

Why BoxLang When You Have Kotlin, Groovy, Scala, and more…

As we approach a stable release of BoxLang and our continued marketing reaches more folks, many have asked about its purpose. Why create a new language when the JVM ecosystem already includes established languages like Kotlin, Groovy, and Scala, to name a few.

Luis Majano
Luis Majano
December 18, 2024