Almost every application needs logging. Instead of writing your own logic in cfml applications it is a lot easier to use Logbox. It is based on the concepts of the Apache Log4J library. Logbox makes it easy to log messages to a file, a database, email, sockets and many more destinations, and it even allows you to write your own code for special logging targets.
Logbox can be used standalone so you are not limited to coldbox applications. It is very flexible and you can create many different loggers. For so far the good news. The bad news? Well, it is not really really bad, but I think the logbox documentation is confusing in some places. I have been using Logbox for a very long time, but even though I can create my own code for logging I was always struggling to get it right, so every component was logging in the right places and at the desired logging level. There is a lot of documentation for logbox and log4j but a non-native english speaker like me is missing a good starting point and an explanation of the basic components. So I decided to ask around in some slack channels and read some Logbox source code, so after 10+ years I finally took some time to investigate Logbox a bit better, so now I understand all details. I want to share this in a few posts. Topics I will address:
basic configuration : logbox, loggers, appenders, categories and severity levels.
how to extend logging capabilities by creating your own appender.
a very simple way to display all logging details in our applications.
some logging examples: audit logging of your database changes, condition logging of performance
Ok, this may sound like a somewhat cryptic title. We are talking about the importance of this, and now I mean the this keyword. To be honest I never worried too much about the this keyword. I know it is a component scope and when you refer to this inside your component, you refer to the public scope, so everything from this component which is visible to the outside world.
But now I had some issues (explanation will follow). I was surprised to see how hard it was to find a decent explanation of the this component scope. Not easy to google, because ‘this’ shows up in a lot of web pages…
Using dynamic datasources in a cfml ORM system can be hard. I am working on some project full of cform, and as mentioned in my post on dynamic datasources in qb I have a project with a lot of legacy code, full of cfquery, queryExecute, some qb queries and… tons of cform entities. And for all this code I should be able to change my datasource on the fly, based on URL or the authenticated user. I already had all solutions in place for qb and queryExecute, but cform is a showstopper. Back in CF9 when cform was introduced you could only work with ONE datasource, the default datasource. Since default datasources where introduced in CF9 I suspect this was only done to accommodate for the lack of datasource awareness of the cf9.0 orm entities. In CF9.01 this became slightly better when we could specify some datasource property, but it has always been a pain to get this right. And unfortunately we often worked with a multidatasource setup. When we switched from Lucee 4 to 5 it took several years before a very important multi datasource bug was fixed. And now we even needed dynamic datasources, which is a real NO! in cform. So how about quick?
Recently I was working on a project where we wanted to reuse our code for multiple customers. The only difference: they all have their own database where their data was stored. We can do this in two different ways
deploy a new application for every customer. For a smal amount of customers that might be acceptable.
Based on the url we can detect which datasource we need for a customer. If we would be using the same url for all customers, we can have some central database which keeps all kind of information including datasource name for each individual customer. We could store the datasource name in a private request collection variable called mainDatasource (or put it in some user specific cache or session variable), so each customer has his own datasource.
Since our project was existing code, I have a few hundred references to <cfquery> and queryExecute and many queryBuilder (qb) calls for newer code.
I want to share some recent experience with you, when I created a new coldbox app. Disclaimer: Actually I would like to improve the first impression when generating a new coldbox app, but I may sound a bit biased. As some of you might know I am not always happy with commandbox, especially with the way it handles lucee in production environments. We had some issues recently with pinning lucee versions so we didn’t get unwanted updates, and the way it handles updates combined with some licensing issues. Our cases were probably very specific, but one of my major points with commandbox/lucee setups is that our sysadmins need additional training, because the setup is very non-standard. For a sysadmin who has to master multiple environments the locations of configuration files and log files is very non-standard, and release notes are not easy to find in the documentation. If you are well known in the commandbox and lucee environments it is not too hard to master, but for these sysadmins it is just one of the many tricks they have to master. They love uniformity, especially at 2 am with some failing websites after an update.
Interceptors in coldbox are very powerful. They are components which listen to events which are announced by the core framework or modules or custom events created by your application. But this post is not about all details of creating interceptors, you can read all about it in the coldbox documentation. I am using them all the time since they are so powerful, but sometimes they don’t behave as expected, especially when your interceptor depends on other modules.
Ahh yes, the good ol chicken and the egg problem
So, what’s the problem with this chicken and her egg? Actually there are two related problems. One of them is easy to solve, the other takes some more effort.
I often post about problematic stuff, like bugs, incomplete documentation or other annoyances. This post is different, and not even very detailed. We are talking about scheduling tasks. Luis Majano recently described the coldbox 6.4.0 release, which is mainly about scheduling. There is extensive documentation but scheduling is now so easy to code, I just wanted to share some examples with you. Coldbox 6.4 was only released a few weeks ago, but I think is is so extremely useful, we already implemented it in several projects. Ok, there was one bug which I will share with you, but that will be fixed soon, and is easy to avoid.
We all know, commandbox is a wonderful tool for cfml development projects. It is very easy to spin up some version of Lucee or Adobe ColdFusion, configure a few settings and try out your code with this version. If you want to try other Lucee or ACF versions, you just spin up another version and try again. If you want to save yourself the hassle of configuring this new server again, you can export your settings from the previous version by using cfconfig and import it again. Since commandbox can install lucee and ACF versions, the question arises if commandbox lucee (or ACF) is suitable for production. This question will come back now and then on the coldfusion and boxteam slack, and until recently I would say: no problem! As CTO and owner of a hosting company I decided this setup was capable for production for several of our customers. But I changed my mind, so let me explain.
I am a bit frustrated. Usually we spin up our lucee servers in a commandbox environment, and since this is so easy most of the time we also use it in production. But upgrading these servers can be done in different ways.
Don’t use the admin
If you like to do this the oldfashioned way, you can open your lucee admin console, and use the update command. Please DON’T do this, it will get very messy soon. Let me show you. I start a lucee machine from the 5.3.5 range like this