dev.Objective() Wrap-up

Well, dev.Objective is wrapping up now. This week has been my first week presenting at a conference, and I’m grateful to everyone that came out to hear what I had to say. Links to the slides are available below.

CFML Sessions for Dummies
Live Testing a Legacy App

Overall, I enjoyed the conference. As a CFML developer, I gravitated more to the CFML specific tracks and even wished there was more of it. After 3 days (4 with Into the Box) I am more than ready to head back home. I think I would just enjoy a 2-day conference track just as much, maybe even more.

One thing I especially liked was that I can’t remember hearing any one apologize for CFML here at dev.Objective(). That was a welcome change from CFSummit, where I feel that’s the pitch of the entire conference.

My favorite sessions were definitely the ones on Lucee. It was really neat to see behind the curtains, if you will, of Lucee — seeing the build happen, seeing a bug get fixed, seeing the community in action. I even entered a feature request (LDEV-888) yesterday that was added within 12 hours! Lucee is a breath of fresh air coming from ACF. I hope that I can get better at contributing back. I now know that test cases are just TestBox cfcs (like this), so I can definitely include one with a bug report.

I think my biggest complaint about dev.Objective() would be the cost. Both the conference and the hotel were pretty expensive and made it so my entire team couldn’t come. Hopefully those items can be addressed in the future in some way.

These conferences always remind me of how good the active CFML community is. I hope we can all work at getting more of the community active and contributing!

Until the next CFML conference.

Cheers,
Eric

dev.Objective() Wrap-up

Into the Box Wrap-up

Into the Box 2016 just finished up. What a great conference! It was my first time speaking and I feel like it was the perfect venue — only 30 minutes long in front of a small, supportive group about a fairly specific subject matter. Thank you to everyone who came to my sessions and supported me!

Below are the links to my slides for the presentations:

Mixing Up the Front-end with ColdBox Elixir
Integration Testing in a Modern World

I’m really excited for Into the Box next year, as well. The plans are right now to expand Into the Box to a 2-day conference all focused on Box products. I think that is a good idea. I really enjoyed how specific the content was, and I definitely have more to learn about this awesome framework and the tools around it. Looking forward to it!

Next up is dev.Objective(). I have two presentations there as well. If you’re in town, I hope to see you there.

CFML Sessions for Dummies
Live Testing a Legacy App

Into the Box Wrap-up

Multi-Engine CI in Travis with CommandBox 3.1.0

CommandBox 3.1.0 is just around the corner and comes with a host of amazing features! While the new ForgeBox integration deserves an entire post on its own, I want to talk about starting different CFML engines all from CommandBox.

Brad Wood outlines it on his blog here. Basically, the CFML engines are now packages on ForgeBox, and you can start a specific engine by setting the cfengine parameter for the server start command. It has never been easier!

But this is all on Brad’s blog post. I don’t need to review that for you. What I want to show is how this makes continuous integration testing on multiple CFML engines a breeze.

I’ve used CommandBox to run my continuous integration (hereafter CI) tests on Travis for a while now. It was super simple to use the testbox run command to run my tests and search for any failed tests. The one drawback with this approach, though, is that CommandBox only runs Lucee 4.5. This was okay for certain projects where the app would only be ran in Lucee, but it didn’t work well for libraries and modules.

For libraries and modules, I mostly turned to CFML-CI, a template to get multi-engine CI running on Travis using Ant. Take a look at that build.xml file, though:

(Prepare to scroll…)

😳

Hard to grok, isn’t it? Up until now, it was arguably the best way to run multiple engines.

Enter CommandBox 3.1.0.

Everything can be done from the .travis.yml file. Here’s the one I use as my template:

Up in the matrix section, I can define all the platforms to run my tests against. In the before_script section, I use the platform to start a server. Then, my simple script mentioned earlier runs my tests for me. Travis will run these engines concurrently, so I can test all my engines in the time it would take to test one.

Here’s what it looks like on Travis:

Multi-Engine CI in Travis

It’s. That. Easy.

Huge props to Denny Valiant and Brad Wood for the amazing work here. Because of this, I can better support Adobe ColdFusion on my modules, something I was constantly reacting to instead of catching with my tests. My CI set up has never been so easy.

Multi-Engine CI in Travis with CommandBox 3.1.0

When does `BeforeAll` run in TestBox?

Just a quick gotcha I found tonight.

I was trying to get Selenium running in a project using Ortus Solution’s fork of CFSelenium. Here’s the test for the login page:

I thought it would be neat and clean to write the setup for the tests after the given and when sections. Only one problem.

Cannot find Selenium in variables

This was confusing to me. Dumping the variables scope in the beforeAll method showed Selenium, but not in my when block.

Turns out this is due to how TestBox packages specs and when it runs its lifecycle methods like beforeAll. The new spec keywords — feature, story, scenario, given, and when — are just aliases to describe. describe blocks are executed before the test lifecycle in order to find all the actual specs — the it and then blocks. That’s why Selenium was not available there.

Moving all the login to the then block fixed this up nice and quick:

An opportunity might exist here for a Pull Request to instead run the beforeAll before any describe blocks, but I’m not sure if it matters all that much. For now, I’m content to just be aware of the fact and start testing with Selenium.

When does `BeforeAll` run in TestBox?

Looping over Structs passed through the Arguments scope

This example came up while I was trying to refactor a for loop in to a StructEach. I was getting a weird error:

can't cast [orderNumber] string to a number value

All I was getting from the TagContext was a reference to the closure of the StructEach. After trying it a few different ways, I decided to turn to the trusty TryCF.com site to see what the issue was and if it was different across the various engines.

So, here’s our example snippet:

I’ve included a “Dump by passing struct directly:” section to compare the different results to what I would have hoped to see.

Let’s look at the results in Lucee:

TryCF Results of StructEach experiment

Yikes! The entire struct gets passed in as the key and the value is set to the index in the arguments array. You can imagine that errors out pretty quickly as you try to use the key as a string. (I was under the impression that the key had to be a string.)

As if this weren’t bad enough, Adobe ColdFusion implements it just a bit differently.

TryCF Results of StructEach experiment

First off, ACF11 doesn’t pass the entire array as the third parameter to the closure. 👎

Next, we see that — when passing the struct through the arguments of another function — instead of passing the filter name (ORDERNUMBER) as the key and the array of order numbers as the value, it passes the position as the key (1) and the struct as the value.

There’s one more example I want to cover. A simple for loop. You might be hoping this one acts better.

You’d be disappointed. 😞

Here’s the code:

Here’s the results from TryCF

For Lucee:

TryCF Results of for loop experiment

And ACF 11:

TryCF Results of for loop experiment

Still not what I would hope for, but at least it’s consistent. ¯\_(ツ)_/¯ (In fact, ACF is consistent between the for loop and the structEach loop. Good for them.)

As far as I can tell, this is due to the (strange, to me) handling of the arguments scope as both indexed and named. The easy way to solve this is…don’t pass the arguments scope containing a struct something you need to loop over that struct!

Also, I got to be honest, I’m not even sure where I’d start with reporting bugs on the different platforms. What are bugs and what aren’t? Which platform is doing it right (or at least less wrong)?

So I’m not going to touch that part; I’m going to stick to just making you aware of the pitfalls with using the arguments scope and looping over structs.

Looping over Structs passed through the Arguments scope

Team Pull Requests

We had a fun activity today as a team at O.C. Tanner. Every Friday we try to take an opportunity to train as a team. Sometimes we train individually with screencast sites like Code School. Lately we’ve been taking turns researching a topic and then teaching it to the others (like “An In Depth Intro to Arrays” or “SQL Tips”). Today, we tried a different activity — we did a training on pull requests by each submitting a pull request to cfdocs.org.

cfdocs.org is an open source website dedicated to quick access to cross-platform docs on cfml tags and functions. Highly recommended.

This isn’t a blog post about submitting pull requests (though you can read a great one here or here). This is to promote the idea that you can both (1) train your team and (2) give back to the community at the same time. I have found that my programming skills have grown in leaps and bounds even in the short time since I started really involving myself in the cfml community. Now the same can be said for our team.

The activity was a great success. Seven (7) pull requests total. Try it with your team today.

Team Pull Requests

Server Toggling in CommandBox

Really quick post here.

I was wanting to set up aliases for CommandBox. Here’s a few examples:

Notice Line 2? The problem was that I wanted to use bss for both box server start and box server stop. “Wouldn’t it be nice,” I wondered, “if CommandBox would just choose the right one?”

Yes. Yes, it would.

I started with a pull request. Brad Wood helped me out with some code review and helped me realize that this was better off as a ForgeBox command.

Brad also talked about how CommandBox commands are moving to modules in the next version.
While I’m super excited for that (Modules are the best!), I wanted this now, so this is a normal CommandBox command.

The code was pretty simple:

The new toggle command is nested in a server folder. CommandBox nests commands in namespaces according to their folder structure. By nesting toggle.cfc in server, I am essentially adding the toggle command to the existing server namespace.

Also note the aliases metadata on the command of toggle. That let’s us just type toggle as opposed to server toggle.

Here’s the box.json:

One thing to note is Line 6. The value in createPackageDirectory overrides the default name for the package. Since my package’s name is server-toggle, CommandBox was installing it to a server-toggle folder. Specifiying server in the createPackageDirectory field ensures this command is under the server namespace.

That’s it! You can check out the code on GitHub or install the package yourself by running install server-toggle in CommandBox.

Server Toggling in CommandBox

Reserved Words in AOP Aspects

If you are new to Aspect Oriented Programming (AOP) in general, I recommend you start here for a crash course.

I was dealing with a strange bug using my QueryToArrayOfStructsConverter in a new project. The code was super simple — just a select * from table as an example for a test I was writing. I expected to get back my array of structs, but I instead got this mysterious error:

Exception mixing in AOP aspect for (TestDAO)

I decided to take the time to dig in to the AOP portion of ColdBox to try to (1) learn about how AOP is implemented in ColdBox and (2) find my problem here.

Side Note:

Whenever I dig in to these packages and frameworks, I’m assuming I’m going to find that I was doing something wrong.
It’s more time consuming than finding an answer in the documentation, but also more enlightening about how the tool I’m using works.

AOP is a fascinating pattern. I was interested to find that ColdBox accomplishes the pattern by writing a dyanmic function to a file and then including that file in the in-memory class using a <cfinclude />. Very smart.

I mention the <cfinclude /> because it was here that I was getting the error. You see, ColdBox is just catching any error and reporting it back as the error message above. By commenting out the try-catch block, we see a different and, in this case, more useful error message:

Better Error Message showing Function Name find was already used by Lucee

Looks like Lucee is using find as a function name under the hood. The method I was trying to join to was also called find. Easy enough fix — I renamed the method to findAll.

There’s probably other reserved words, as it were, that you can’t join an aspect to, but I don’t have a list. What I do have now is a good guess at the problem when I see this kind of error message and a better understanding of how ColdBox puts together AOP.

Reserved Words in AOP Aspects

CFSummit 2015 Reflection

I’m sitting at the airport in Las Vegas thinking about CFSummit 2015.

I was excited for the conference, but it exceeded my expectations. Especially when compared with some other conferences I’ve attended recently, this conference has had a huge impact on my skills and career.

I think that’s partially because it reminded me how much I love programming. There are a lot of different kinds of projects back at work, and not all of them programming ones. This conference reminded me that I really like the programming ones.

I think it’s partially because the conference was well organized. The conference area was nice. Wifi worked well. The sessions were very informative. The food was excellent. This was probably my favorite Vegas conference location yet.

But mostly, I think it’s because of the community. I decided that I was going to be very prolific on Twitter. (Really prolific. Over 100 of my 500+ tweets happened in the last two days!) That led me to interact with a lot of smart people. The CFML community is very friendly and helpful. I already knew this from the CFML Slack (which you definitely should be on), but it was nice to see in yet another venue. I was able to meet some people in person that I had only interacted with online. Their interaction helped build my confidence — confidence to write more and even submit a couple proposals to dev.Objective() 2016.

I think a key step in keeping a language and community alive is to participate. Participate on Slack and on Twitter. Help out where you can. Submit bug reports and pull requests. No community will die when we’re participating. 

This conference was absolutely a success. I can’t wait to come back next year for CFSummit 2016.

Though, I definitely wouldn’t mind if it wasn’t in Vegas.

CFSummit 2015 Reflection

A Call for Proposals — dev.Objective() 2016

I’m a perfectionist.

There, I said it. I don’t like to look foolish or stupid or, really, less than perfect.

And it’s held me back. Especially from participating more in conferences.

I’ve wanted to submit a proposal to a conference for a while, but I was waiting around until I had a talk that was (1) completed, (2) awesome, (3) completely unique, and (4) wanted by the community.

But something clicked last night.

This is a proposal.

And being a proposal, I don’t need my talk to be (1) completed. I just need the outline.

The conference organizers will decide if my talk is (3) unique enough and (4) wanted by the community. And if it isn’t, that doesn’t mean the talk is bad, necessarily; just not the right time and place.

Basically, I was taking on myself the judgement that I should leave up to conference organizers.

So I just submitted a proposal to dev.Objective() 2016. I’m excited. I have no idea if it will be accepted, but I’m glad I finally submitting a proposal.

Now, all I need to focus on and all I should focus on is (2) make the talk awesome.

A Call for Proposals — dev.Objective() 2016