A few days ago I blogged about some annoying lucee or coldbox behaviour. On syntax errors in components often I didn’t get feedback on the offending file or line numbers. This makes it very hard to debug your application if you made changes in several files at once. After my post I was contacted by Zac Spitzer who asked me if I could file a bug. I already did this a few months ago, but they couldn’t reproduce my case. So we talked about this bug and I digged a little deeper to find out what was wrong.
Finally I discovered coldbox was failing on a getComponentMetaData call. When you try to inject a component coldbox will call getComponentMetaData and if there is a syntax error in you component you will get this message lucee.transformer.bytecode.statement.ExpressionAsStatement cannot be cast to lucee.transformer.bytecode.statement.tag.TagComponent
which is about as helpful as your average hibernate error message, since it didn’t show filenames or line counts. If you do the same in Adobe ColdFusion with full debugging it will show you all necessary info.
I agreed I would create some simplified demo project without coldbox and file a bug with Lucee. I also created a pull request for a workaround in coldbox, so it would at least show me the name of the component which was failing so miserably.
But on creation of my simplified testcase I stumbled upon something weird: suddenly I had a descriptive error in my simple TestComponent. So let’s say I had this component:
component {
function someFunction() {
return {
"foo": : "bar"
}
}
}
I created a script which just called the metadata on my component with syntax errors, e.g. writedump( getComponentMetaData("FailedSyntaxComponent") )
and now suddenly it returned this informative message:
instead of something undescriptive like this:
So as you can see I had two colons on one line, but the same kind of erratic behaviour was seen on missing commas in arrays, semicolons in the wrong place and more. This kind of small typo’s is easy to make when refactoring code. I focused on the difference between my sample code and the real problematic component. I finally stripped down my code to nothing more than a component definition and a simple function with a syntax error. I came with something like this and still no filenames and line numbers for my error.
component
{
function someFunction() {
return {
"foo": : "bar"
}
}
}
It still looks almost the same as the first code sample (yes, indeed, ALMOST the same…). But still no informative error messages.
Ok, it tells me getComponentMetaData is failing on line 3, but not WHICH component and which line is invalid cfml. Finally I discovered the difference. Have you ever spent your time debugging a line break in cfml ???? It all boils down to this
component {
//write all your code and all syntax errors show up nicely
//in getComponentMetaData
//versus...Aaargh, this will not show any details
component
{
//yes write code, and you will regret it....
So, just a stupid line break. I was wondering why I never had this error a year ago. And then I realized. I tried to do some better formatting and started using cfformat. And cfformat nicely changes the format of this
component extends="FluentBaseService" singleton accessors="true" {
//etc
to this:
component
extends="models.base.FluentBaseService"
singleton
accessors="true"
{
//etc
I guess I have some 150 components in my current project which will be changed by cfformat, just to make sure Lucee will throw errors but cannot find any typo anymore. Does this mean I shouldn’t format my code anymore? I didn’t think so. These syntax failing components could also be detected by some proper unit testing and we still have cfcompile to rescue me, so I can find my faulty component. And once I put this component {
on a single line it can even point me to the right line number.
So this was a nice use case to sharpen my debugging skills…. Of course Lucee should do a better job on this so I filed this issue. It will probably take some time before this is resolved, so in the mean time I will still be rescued by cfcompile.
Leave a Reply