Blog

Blog Archives - 15 Record(s)

Year: '2014' - Month: '2'

27
February 2014

Gavin Pickin

WireBox - Possible Gotcha with Binder Config File Settings and using Full CFC Path

CFML Language, ColdBox, Techie Gotchas, WireBox

My last post, I looked at Installing ColdBox's WireBox Standalone library into one of my legacy sites. We got the Core downloaded, mapped, we created an Injector, and looked at how to create your Objects using the Injector. We even looked at using Annotations and the Binder Config file to tell WireBox how you wanted those Objects wired.

At the end, we came across one of thos gotchas. When you use the Binder, whether you explicitly map an alias, or not, WireBox by convention creates an Alias for you... matching the name of the CFC... in our case "Theme". So when you use the following code, you get an interesting side effect.

<cfset ThemeService = application.injector.getInstance("CFCs.Theme")>

Wirebox looks through its list of CFCs mapped, and looks for CFCs.Theme… and it cannot find it in the list of Aliases, so it looks for the full path, and sets it up, but since there is no matched Aliases / Mapped settings, it does not set it up with the Binder Config, it uses annotations, if any, and thats it.

But wait? We did set it up, didn't we? Yes… we did, but, by default, Wirebox maps it with the Alias, and it does not use the path to check if that exists. I talked with Brad, and it seems like I'm one of the few who found this… because usually when you map a CFC, you would refactor your code to use the Alias, because Aliases are awesome, and usually that isn't a problem.

Don't get me wrong, refactoring is great, using an Alias is awesome, you can move your CFCs around, reorganize them, change the path in the binder, and it still works… but what about those people with 10000s of files, and refactoring is a nightmare? I spoke with Brad, and discussed a couple of simple fixes.

  1. Add an alias, which is the full path as an annotation
  2. Add an alias, which is the full path in the binder
  3. Write a plugin that looks for beforeInstanceInspection or afterInstanceInspection and adds the full path as an alias on the fly
  4. Make a pull request on Wirebox to do it automatically
  5. Bribe someone else to do it and make a pull request

1 and 2 are easy, and work great in this example. Its much easier than refactoring all of your code calling the injector, but in all reality, if you are installing Wirebox, and refactoring the injector in, you could just map all your CFCs at the same time, and use Aliases to begin with. 

1 - Add an alias, which is the full path as an annotation

In your component declaration or cfcomponent tag, just add this 

alias="CFCs.Theme"

 

And now, you have an alias, so your full path call will find the Mapped version, with that name. What if you want to use Theme as well as the full Path? Just do this

alias="Theme,CFCs.Theme.ThemeService" 

 

You have have multiple names/aliases, which will make this an easier transition... which will allow WireBox to match the full path, with the alias and the settings in the binder.

2 - Add an alias, which is the full path in the binder

Just like we did with the annotation, you can easily get around this with the binder config, by setting the mapped aliases there. Remember, when you map something to a CFC, the map is the aliasing part. So this would work.

component extends="coldbox.system.ioc.config.Binder"{

    function configure(){

        map("Theme,CFCs.Theme,ThemeService")
            .to("CFCs.theme")
            .asSingleton();

    }
}

 

Simple fix, now when you getInstance("Theme"), or getInstance("CFCs.Theme") or getInstance("ThemeService") all of them will work, and they will respect all annotations, and Binder config settings, just remember, Binder Config overrules the annotations.

Of course, if you are refactoring all of your code to use application.injector.getInstance("Full.Path"), you might as well just use application.injector.getInstance("Alias") while you're at it.

 

Hope this helps someone, I know I'll be using them as I slowly refactor.
Thanks for reading,

Gavin

27
February 2014

Gavin Pickin

Adding ColdBox's WireBox to Legacy Site - Installation 1 2 3 Go

CFML Language, ColdBox, Dependency Injection, WireBox

I'm dealing with a the task of bringing more and more of my legacy code projects into this decade, especially when we're doing upgrade and continuous work, so we can eliminate some of the headaches as we move forward. One of the steps is ensuring we are using our CFC components properly, so today, I am going to install Wirebox into our app, which is easy, but this series, we'll go through the other steps to being able to use Wirebox properly. I use that word like I know what Properly is, I guess we'll find out soon if I do know, or not.

Download and Map ColdBox / WireBox Standalone 

First of all, you do not need to download all of ColdBox.
WireBox is a standalone library, and can be used by itself.

For me, I'm going to grab ColdBox standalone, and store it in a location we can map to it for shared use. We could just get the wirebox bundle, but I want to use TestBox and other pieces, so I'll download the whole Core, then I can just use the pieces I want in the apps I want to use them in. I assume you can go find the ColdBox files and map it. Just remember, you want to map the coldbox directory to /coldbox. If you look in your folder, and you see a coldbox folder in it, you've mapped it 1 directory too high. If you see the "system" folder, you have the right one.

If you want to just get the WireBox standalone, make sure you map WireBox to the Wirebox directory, again, make sure you see the system folder in that folder. The only difference in this article is that mapping to the Injector.

Usually the folder you unzip has coldbox in it, with some license, read me files etc. 

I will probably do a post on this later, to make sure its simple enough for everyone. Check back for this.

Instantiate the WireBox Injector to Manage our Objects

First thing we want to do is create an Injector. This is the base for everything we do with Wirebox. The Injector is what manages our objects, and creates new ones, or passes you a reference to existing ones. Normally, I have a series of code that does this, but the Injector will take care of all of that for me. Later, the Injector can also do some magic on the objects we ask for, this is where Dependency Injection comes in, but first, lets create an injector.

Since you want to use the same injector, throughout your complete application (note, you might want several injectors in large apps, where each injector looks after a module or piece of your app, but this isn't that big, one injector will do nicely). So inside the Application file? we're going to add this code to instantiate our injector in OnApplicationStart()

<cfset application.injector = createObject("component","coldbox.system.ioc.Injector").init()>

or if you are using WireBox Standalone

<cfset application.injector = createObject("component","wirebox.system.ioc.Injector").init()>

Now, when our application starts, we'll have our WireBox Injector. 
That is it, it is installed, and ready to use.

You might ask, is it really that easy? and I say, yes, actually it is.

Note: WireBox can actually hoist itself into the Application itself, with certain settings, but this is just a beginner guide.

So how do we use WireBox? How do we use the Injector?

Instead of this

<cfobject name="ThemeService" component="CFCs.Theme">

 

We do 

<cfset ThemeService = application.injector.getInstance("CFCs.Theme")>

 

Now, what if we wanted to get an Object out of our Application scope, if it has been instantiated already.
We might do something like this

<cfif structKeyExists("application.singletons", "themeService">
    <cfobject name="application.singletons.ThemeService" component="CFCs.Theme">
</cfif>
<cfset ThemeService = application.singletons.ThemeService>

 

Or we can do the following (read the note below)*

<cfset ThemeService = application.injector.getInstance("CFCs.Theme")>

 

* How does WireBox know we want a this CFC in the application scope?

That is a good question, WireBox lets you give it settings 2 ways. 

  1. ?With Annotations written into the CFCs themselves? so each CFC tells Wirebox how to use it.
  2. Or a Central WireBox Configuration file, written in CFML called a Config Binder (I'll use Binder from now on)
  3. I guess there is a 3rd way, a combination, but remember, if you have an annotation, the binder can override that setting.

So lets start with the Annotations.

Open your CFC and in the component declaration do this

component name="Theme" scope="application" {

 

Or the cfcomponent tag do this

<cfcomponent name="Theme" scope="application">

 

Then, when Wirebox gets the Instance, it reads that scope annotation, and places it into the application scope. You can do the same with Aliases, setting the CFC as a Singleton, and almost all of the other Wirebox Configuration

Note: When you set a CFC as a singleton, it defaults to a special scope that lasts as long as the injector does? if you store it in the application, it lasts as long as the application does. You can force the injector to clear the singletons with 

application.injector.clearSingletons(); // assuming the injector is names and scoped this way

 

Using the WireBox Binder Configuration File

Now, the Binder Config method is pretty nice. You can set up all of your cfcs from one location, which makes it easy to see the settings for all of your cfcs, without having to open up 20+ files to see which ones are singletons, which scope are they in, etc. 

Now, one of the best things about Wirebox and using the Binder method, is giving your CFCs Aliases? so you no longer have to use the full path. Any CFC you map (or define) in your Binder, Wirebox automatically creates an alias for you, matching the name of the CFC. Lets have a look.

To use a Binder, we initialize the Injector a little differently.

<cfset application.injector = createObject("component","coldbox.system.ioc.Injector").init("WireboxConfig")>

Or if you are using WireBox standalone

<cfset application.injector = createObject("component","wirebox.system.ioc.Injector").init("WireboxConfig")>

 

This time, we're passing something to the Init? which is the WireboxConfig object I made. Its just a CFC? you can use full or absolute path, and the WireboxConfig.cfc looks something like this.

component extends="coldbox.system.ioc.config.Binder"{

    function configure(){

        map("theme")
            .to("CFCs.theme")
            .asSingleton();
    }
}

 

The component extends the ion.config.binder, that's how it inherits all of the important pieces.
It has 1 function, which is configure. This is how you setup all the mappings, or bindings you want Wirebox to handle.

I have just one right now? I map the alias "THEME" to the CFC located at "CFCs.theme" and I want to treat it asSingleton. I think the DSL or Domain Specific Language the ColdBox team use here is really nice, and readable. Wirebox is based on conventions, so I could do that even easier, and use the following code.

component extends="coldbox.system.ioc.config.Binder"{

    function configure(){

        mapPath("CFCs.theme")
            .asSingleton();
    }
}

 

Now, I told Wirebox, I want to map the CFC at CFCs.theme as a singleton, and Wirebox gives the CFC an Alias, by convention, of Theme.
To use this binder mapped CFC, I just use the following code.

<cfset ThemeService = application.injector.getInstance("Theme")>

 

Wirebox looks through its list of Mapped CFCs, and sees Theme? and says, I got that one, and then uses the settings from the Binder. 
Just because you define how you want each and every CFC to work, it doesn't mean that they are all Instantiated when the Injector is made. They are LAZY LOADED, so they are only created as they are needed. If you want them all Instantiated at once, or certain ones, you can add a setting, .asEagerInit() so the Injector will eagerly Init them before needed.

 

Now, there is a catch? One of those techie gotchas with the Binder.

If you use the code below something unexpected happens

<cfset ThemeService = application.injector.getInstance("CFCs.Theme")>

 

Wirebox looks through its list of CFCs mapped by Alias, and looks for CFCs.Theme? and it cannot find it, so it looks for the full path, and sets it up, but since there is no Mapped settings by Alias, it does not set it up with the Binder Config, it uses annotations, if any, and thats it.

But wait? We did set it up, didn't we? Yes? we did, but, by default, Wirebox maps it with the Alias, and if WireBox sees a full path, unless there is an alias that matches that full path, the binder settings do not apply.

I have another post here that explains how to resolve that issue

Recap

WireBox is installed, setup, and you can now use Annotations and the Binder Config method to set how WireBox wires your objects together. Next I'll give you more information on the full path issue, and we'll dive into Dependency Injection and see how that works.

Thanks for reading, as usual, let me know if I missed anything.

Gavin

27
February 2014

Gavin Pickin

Techie Gotcha - Debugging CFML Errors - Unhelpful Error Messages

CFML Language, CFML Server, Techie Gotchas

Debugging your code is one of the biggest parts of your job in my mind, and I believe that you can tell how good a developer is (up to a certain point), by how they debug their code. A lot of people seem to Ask Stack Overflow first, then ask their coworkers, read on google next, and then they try and figure it out themselves these days. Its funny, because, I think it should be the opposite order, you should work it out yourself, then read google, then ask a coworker, then ask for help at Stackoverflow… but I think I'm one of those who can debug pretty well, mainly because I've made LOADS of mistakes in my time.

Just recently, we had a pretty good bug pop up, and since I didn't find anything too helpful elsewhere, I decided I better blog it, for myself down the road, to share and to help those who do google because mindlessly asking on Stack Overflow.

A little background, this site is running on ColdFusion, we have a bare bone web directory, and most of our code is mapped into the app. I went to lunch, everything was working, I get back, and somehow, while I was at lunch, an error started happening, and none of the developers knew why. Its on our Dev server, so no biggie, so I sit take an take a look.

This is a legacy site, lots of old code, I do a lot of work with older code, we're dragging it into this century, but baby steps. So the code breaks with a CFAjaxProxy tag. Yes, I know, we could use jQuery, we do on our new stuff, but we haven't attacked that yet.

So the error code is

The specified CFC cms_files.CFCs.functions could not be found.

 

Message detail:

The path to the CFC must be specified as a full path, or as a relative path from the current template, without the use of mappings.

 

Reading this error message, first I think, thats odd, we definitely have been using mappings with this, for a long time, why in the world would mappings all of a sudden not work. 

Looking in the bug tracker, it looks like you could not use mappings before, and according to the bug, Full Paths would blow up too, but this is marked as fixed, and this is what I assume mappings now work, but that means the ERROR message is Incorrect.

https://bugbase.adobe.com/index.cfm?event=bug&id=3039843

So first thing I do is make sure all the mappings are still in place, and see if anyone "messed" with them. Nothing has changed, just as the developers said.

That error message just irks me… I smell something is not right.
So I put in the full path in, guess what? 

ERROR

I was right, it has nothing to do with finding the CFC… I now think its the fact it can't find a VALID CFC. 

I reload our application, and sure enough, the CFC has an error in it. One of our developers had updated a function, but it wasn't correct, and because they didn't reload the Application, the other functions were working off our Application Singleton Version, and the CFAjaxProxy instantiates the CFC for each call... so they didn't see the error, they just got a vague and misleading error message about not being able to find the CFC.

So if you are getting this error, 

  1. Mappings do work
  2. It might be the fact the CFC is invalid, not necessarily due to not being found at that path

I checked this in Railo, and it identifies the error much better.

For a incorrect path to a CFC you get these results.

For a correct path to a CFC with an error, you get these results.

Railo tells you there is an error in the CFC, and even identifies where it is, so you can fix it. In this case, I was missing the word FUNCTION in my function definition. Error messages should be helpful, that is the reason they exist... they should be accurate, and helpful. In this case, Adobe ColdFusion failed at both of those points.

I have seen a few other error messages similar to this. 

One of the main ones is using cffile.
If there is an error renaming the file, and there is a problem with the path of the source file, usually a forward slash back slash issue when changing from Windows to Linux, it states the problem is with the DESTINATION file, although its actually the SOURCE file.

Before I go post a bug to fix an error message, which seems picky, but hey, its important I believe, I'm going to install CF10 and CF11 to see if these error messages have been fixed over time.

Otherwise, I will file bugs for them… so check back and see CFAjaxProxy and CFFile error messages in a future post.

Thanks,

Gavin

25
February 2014

Gavin Pickin

ColdFusion Betas - Playing with ColdFusion Thunder

Tools and IDEs

With all the noise going on about ColdFusion going into Public Beta, I decided I should probably download the new version of Thunder and play a little. A lot of people are happy using Sublime, or a few other editors, but I have been using CF Builder for a while now, and maybe out of habit haven't really gotten into the other tools. Although, sometimes, builder just drives me mad, so I decided I would download the Beta and see what bugs might have been solved... and what other goodies have I been missing out on since I'm using the Free Express Version ( never bothered to upgrade ).

So far, I like it. Its a little cleaner, neater, the UI looks better, although its probably just the latest build of Eclipse or something, but still I like it.

One weird thing, when you are installing Builder, it asks you if you want to install the Bundled Server or not. This seemed a little strange, but then I heard on CF Hour's latest episode, where they discuss how Builder uses CF Server to bundle the Mobile stuff for you, so I guess this is why they bundle the CF Server with Builder, so you can easily access the parts of CF Server Builder needs for that piece of functionality.

Some might say that the Mobile Bundling shouldn't be a part of CF Server, it should be completely in Builder, regardless of what you think of that, it should be pretty nifty to be able to do a lot of the Mobile Workflow in CF Builder 3 (Thunder). Wait, did I just say I'm using CFClient? 

NO, NO I DID NOT

CF Builder will allow you to use whatever Framework you want, Ionic seems to be the new hotness, especially with the Angular flavor it has, so I should be able to work in Builder, and use Builder to send my project off to PhoneGap, do the debugging etc, all through builder. I haven't tested this yet, so I can't vouch for it, but it sounds interesting, even if it just saves me some command line work... although, with Node etc, I think everyone is getting more and more comfortable with the command line these days.

I did notice a few features I've been missing. I have been doing a lot of work migrating / fixing / touching up some legacy code. The last couple of days I have been integrating WireBox into my app, to handle my Dependency Injection and scoping my CFCs better, since a lot of the old code used cfobjects and cfinvoke to unnecessarily create multiple instances. To clean up this code, I used the Project Search Features, and one thing you do not get in the Express Free Version, is global replace... which is nice when you're changing hundreds of files (make sure you're sure of what you're replacing first though, and you have Source Control in place).

The other nice feature I didn't know I was missing, was when you search the entire project, and you pull up the file with the match found, you can expand the search node, and see all the occurrences, and which lines they are on in the file. In the Free / Express version, you would find all the matches, it would say index.cfm has 15 occurrences, you would have to open the file, and then Ctrl / Cmd F to bring up a find window (if the find window is open and you search, it would search the page the Find window was launched from, not the one you're on, annoying feature by the way) and then search through the file to find the occurrences, and then decide if you wanted to find / replace them or not, in each, and every file, separately.

So, whether I decide on moving to Thunder or not, it has at least helped me in my current project(s).

After using it for a couple of days, I found my first bug, checked the internet, and it looked like a fresh new bug, so I submitted it to the Bug Tracker. 
Its not a major bug in the terms of usability, but its one of those annoying ones. 

https://bugbase.adobe.com/index.cfm?event=bug&id=3713385

To save you the effort of clicking on a link, here is the Bug Description.

Title: Opening a Script CFC Component, comments break Syntax highlighting until you edit a Commented Line

Description

Problem Description:
When you open a Script CFC, any comments seem to break the Syntax highlighting. Everything below the first comment are not highlighted correctly. When you the first comment line, it seems to re-parse and it is ok from then on out.

Steps to Reproduce:
Just Open a Script CFC and you'll see that everything below the first comment has no Syntax Highlighting. 

Actual Result:
You open the file, and syntax highlighting is broken from the first comment, like its an error in the file.

Expected Result:
The CFC opens and the whole CFC has syntax highlighting, and comments are highlighted etc

Any Workarounds:
You have to just edit one of the comments, and then Builder re-parses the entire CFC and works correctly after that.

After editing the line

Abram Adams tweeted me after I posted the bug and said it is a known bug, and was fixed, but obviously it didn't get fixed in the Beta Build... but go Vote it up, so they do fix it.

I'll let you know if I find anything else interesting from my playing with Thunder, but so far, seems stable (always a worry with Betas), and haven't had any issues.

Tomorrow I might test some of my Bugs / Issues with CFB2, and see if Thunder fixes them or not. They are Unverified at this time, I guess it takes them a year to triage Builder Bugs as well as Server Bugs.

Thanks for reading,

Gavin

19
February 2014

Gavin Pickin

CFML Server - A Different type of ColdFusion Repo - Update on the Project

CFML Language, CFML Server, Chit Chat, ColdFusion Install Repo

UPDATE: New home for the CF Install Repo Available: http://www.gpickin.com/index.cfm/blog/coldfusion-install-download-repo-new-home-for-all-your-files

Just an update on the ColdFusion Install Repo I set up not too long ago. If you do not know what I'm talking about, or what to refresh your memory, you can read the first post here. So far, its got a pretty good reception, I see a few people have signed up for new Copy Accounts, giving the repo plenty of room for anything we want to do in all reality. Several people have volunteered to help, which is awesome too. If I haven't responded to you yet, I'm trying to get as much of the stuff I have up there, and then I'll have you guys fill in the gaps. 

Those who checked the repo out, might have seen it organized by system... and then 32 / 64 BIT, and while I thought that might be useful, in fact, it was hard to easily see whats available, so I have eaten some bandwidth, and rearranged it all. Now, when you go to the repo, you'll see a folder for each major version we have, 8.0.1, 9.0.0 and 9.0.1 etc. This makes it very easy to find the version you want, and when you open that folder, you see all of the flavors of that version, and a readme with the size files, and hashes (if available).

Its a simple little change, but it makes it much easier, especially for me, to see what versions we still need to put up there.

Obviously CF11 Codename Splendor is in Beta now, everyone has posted about it. My mate Adam Cameron (ssssh, don't tell him I called him that, and yes, for Kiwis, we can call each other mates without it being some weird thing, unlike aussies lol, they're weird, tangent) has released a series of blog posts about it.
The point of mentioning CF11 was, since its in Public Beta now, the release is closer still, so I'm making sure all the versions of CF9 available on Adobes website will be on the repo before they disappear from the map.

For legal reasons, I am not going to pull down CF11 in beta, if you want to get to the Beta stuff, the best place is http://labs.adobe.com/ and the first link (at the time of writing) is Feb 19 - ColdFusion Beta, which takes you here.http://labs.adobe.com/technologies/coldfusion/ The other reason I am not pulling it down is it will change often, and the best place for all the Beta information etc, is on the Adobe Labs site, so if you are interested, go and check it out. 

Also to note, they have an ColdFusion 11 Express Install (link to Adam Cameron's Post on there is here), and the new Version of ColdFusion Builder, Thunder (CFB3) is available to try and play with too.

Side note, why all the weird names? According to a previous ColdFusion Product Manager, if they refer to a Product with an actual name, like ColdFusion 11, they have a legal requirement to release it within a period of time. That is why they use codenames, like ColdFusion Splendor (CF11) and ColdFusion Builder Thunder (CFB3). If they used the name, and delayed the release, or took longer than they thought, and didn't launch it in time, they might get their hand slapped or something. So thats why they use the names, but I don't know why they use STUPID names. Maybe to get people talking about them, because, they do, but sometimes no publicity is better than bad publicity. Side note over.

There have been a few jokes going around about ColdFusion Studio, Homesite etc, so since there is a lot of space on the Repo, you might see another section for TOOLs soon, and I'll throw up the few old ones I have laying around, but mainly for a laugh :) I wish I still have UltraDev... I know I have Fireworks 1 somewhere, and my Flash Certification Certificate.

Anyways, thanks for the support with this, hope its useful, and let me know if you guys think anything else might be useful.
For example, is there a need for Railo Installs? I haven't been using Railo for very long, so I'm not sure what their Version History is like etc. I assume with their Open Source Status, most are not concerned with the specific versions, unless you are World Singles, like Sean Corfield, and are using a specific version.

Have a good one, and go have some fun with CFClient. (Had to throw that dig in there)

Gavin

17
February 2014

Gavin Pickin

Techie Gotcha - Application CFC inheritance Paths with Mappings - Silly Me

CFML Language, CFML Server, Dependency Injection, Techie Gotchas

There is someone, somewhere, beating their head into their desk and saying to themselves, either very quietly, or yelling it at the top of their lungs, "What the {appropriate bad word} was I thinking, I'm an idiot". It might not be you right now (you're reading this blog post, so its probably not you), it might not be you tomorrow, but we all have those moments, where, something seemingly simple, gets the best of us... because its only simple once you see the light. Hindsight is 20/20, I believe its better to share those moments, so that everyone else can learn from your mistakes, even if it proves you have those moments, and it might prove you have them more of those moments than most people :) 

Today, I have one of those moments to share with you, and today, its about Application.cfc Inheritance Paths with Mappings, and how I finally "clicked" about something I had always wondered about, but hadn't really looked into properly.

If you have not read many of my other blog posts, you won't know that I look after a large number of sites (in comparison to developers who work on a few products or a few projects for their company), over several servers, with a lot of legacy code. We're in the process of migrating from Windows CF8 and CF9 servers to Centos CF9 and Railo, and we're trying to bring our legacy code back into the right century when we work on those projects, including Source Control, using Application.cfc (a lot were built before CFCs even existed) and trying to update to newer Frameworks like FW/1 and or ColdBox, or at least some of their libraries, like TestBox for Unit Testing, DI/1 and Wirebox for Dependency Injection, etc. 

In the process of doing some of these said migrations, or preparation for migrations, I came across an issue that we had noticed several times actually, but with time not being on our side, as life goes, we fixed the symptoms of the issue, but didn't really figure out the base issue, and that was, why our CFCs Inheritance did not work as we expected. As I mentioned earlier, I figured this out, but it wasn't until I really thought about it, did I realize I was just thinking about it all wrong. 

If you want to laugh at me, go ahead, hell, I laughed a little at myself too.

What were the symptoms?

Some of our CFCs would throw errors, almost randomly it seemed, with references to global variables, specifically the issue was usually the Application variables. 

We have all looked at Application Inheritance, so when a file is called… ColdFusion / Railo will traverse up directories until a Application.cfm or cfc is found. 

If you map a directory, like /cms to the root, your code can invoke a cfc or create an instance of a cfc with cms.cfcs.utils using the mapping to path out the cfc. You can pass a reference to the application scope if you're using IOC where you give your CFC everything it needs, or you can reference application.variablename from inside the CFC if you're not using IOC and pulling what variables your CFC needs. Either way, the CFC works, it can see the application.dsn and it can look up other important information from the application scope.

Note: I now know better, that we should pass in the reference, in case we refactor etc, IOC allows us to retain control, but, this is legacy code, not all of it mine, and younger me was not as well informed of better and best practices. 

What's the big deal you're thinking? 

Times have changed, this cool little cool called "AJAX" came about, have you heard about it? Its pretty cool, you should look into it. Usually when people are using Ajax with ColdFusion, it doesn't call index.cfm to route through the framework (which you could do, and is actually a really nice way to resolve these types of issues by the way), you can and do call the CFC directly using a path like this /cms/cfcs/utils.cfc?method=getPageCount and pass in the arguments to the method you're calling. 

This CFC cannot see the application scope? Why not? It sees it most of the time, but why can it not see when its being instantiated by the direct url? Each and every ajax call creates a new object, so any variables you pass into the CFC to set it up would need to be passed each and every time, but wait, we aren't using IOC, this is old school done wrong, pull my variables approach, so this doesn't apply. Why can't I see the Application scope? The CFC can normally see the CFC, whats different with Ajax?

Pretty obvious right?
Maybe, maybe not? 

When any of my pages call that CFC, those pages, hit an index.cfm… in /websites/www.mydomain.com/index.cfm

When ColdFusion looks for Application.cfm or Application.cfc it looks in /websites/www.mydomain.com/
and finds /websites/www.mydomain.com/Application.cfc (if we upgraded them over)
or /websites/www.mydomain.com/application.cfm (if the legacy is still cooking).

So, every CFC call made from inside that page load, which starts with index.cfm has already loaded the Application.cfm/cfc based on the entry point, the index.cfm. If we have a /admin or /login /secretentrance it too has an Application.cfc and index.cfm so the entry point is almost always the index.cfm so it has no problem finding the Application file in the path, no need to even traverse.

Now, say we load another page, /includes/loadfile.cfm which we use to pull content from outside of the web root (because you know you shouldn't put uploaded files in the web root - although, I bet there are loads of people still doing that, I know our legacy does, even though our Application.cfc and Application.cfm stop requests from files not in our whitelist), so this file is websites/www.mydomain.com/includes/loadfile.cfm. ColdFusion goes up a directory, and ta-da, there is the Application file, it works, no problem.

So why does our /cms/cfcs/utils.cfc file not see the application?

Its full path is /websites/_includes/cms/cfcs/utils.cfc
Now do you see it?

There is no Application.cfc in /websites/_includes/cms/cfcs/
There is no Application.cfc in /websites/_includes/cms/
There is no Application.cfc in /websites/_includes/
There is no Application.cfc in /websites/
There is no Application.cfc in /

Duh, of course not. 

For some reason, the entry point being index.cfm tricked me into thinking that calling the CFC from inside the request, and outside the request was basically the same thing. It can be, but not when you have a virtual directory mapped in your web server… because the traversing happens on the entry point path.

When I call the /cms/cfcs/utils.cfc it doesn't have /websites/www.mydomain.com/Application.cfc in its path.

The Solution?

The first thought was, I'll just add a Mapping in the Application.cfc file.
Umn, the file never sees the Application.cfc, so how can it map itself so it can find the Application.cfc that it needs to find to map itself, you get the idea.

We could try and map the cms at the ColdFusion server level, but obviously, if you have a lot of different sites, with different frameworks, you don't want a lot of Global mappings, I assume it would work, I'll have to experiment with that later and update this. Railo makes it easy, I'll have to test it there too, and see if it works from a Mapping, and traverses the Actual Path and the Mapped path or not.
This is a little HOMEWORK for Me.

How do we solve this problem?

We cannot move the CMS into each and every site, we lose the benefits of Multi-tenant, and we obviously don't want to have to manage all of those code bases.

Luckily, ColdFusion is a really cool language… and we can do some pretty nifty stuff.

I say: Why don't I just throw an Application.cfc into the /cms/cfcs/ folder, or into the /cms/ folder?
You might say: if this is shared by 50 sites, how would it work, doesn't the Application.cfc have to match the main Application for it to work right?
I say: Yes, yes it does?
You say: 
How does that work?

Simple.. 1 line in the /websites/_includes/cms/cfcs/Application.cfc file

<cfinclude template="/Application.cfc">

Wait, didn't we just say ColdFusion couldn't traverse and find the Application.cfc file?
Yes, it couldn't Traverse the Actual Folder Structure, but, if you include /Application.cfc ColdFusion is smart enough to look in the webroot for the actual site, and convert that to the Actual Path, and do its thing.

It is pretty cool. It includes the whole file, like it was a copy… and everything will work.

NOTE - Just be aware, if your Application.cfc file sets any Paths, you will need to test that the path is the actual Webroot, not the path of the Application.cfc that is including the Application.cfc from the root… otherwise, it will obviously cause a lot of havoc when pathing anything else based on those Application variables.

As I mentioned before, not a really difficult issue, when you see the answer, and being my issue, sometimes you can see the trees for the forest, sometimes its best to step back and look at the problem in a different light, and you will see the solution too.

I still cannot believe that it got me, I admit, even I'm a dummy sometimes, well, actually more than I'd like…at least I wasn't the only one to not see it, and its good to finally figure it out, even if its one of those DOH moments.

Hopefully this helps someone else out there that maybe runs into the same problem.

Fair warning

This solution isn't necessarily the best way to do it, as usual with Programming there are several ways to solve a problem, some great ideas, good ideas, and some poor ones too. 

I mentioned you didn't have to hit your cfc directly… you can route all requests through your framework, you can make a proxy cfc for remote access, you can use Application.cfc to catch all requests (assuming you fix your mapping issue - the reason for this article), and a lot of other ways, I will try to revisit this shortly, and offer some other ways to work around this type of issue, check back if you are interested.

Better and Best Practices

For the record, talking about Better and Best Practices, your main cfcs should never be located in a web accessible directory. You can call them from ColdFusion using a ColdFusion Mapping, meaning ColdFusion can see and talk to them, but the browser can't, which will make them inaccessible, therefore more secure. Although, leaving a Simple CFC with only Remote Access Functions that act as a Proxy to your main CFCs hidden behind a mapping is a solid way to do this.

We actually briefly discussed a few better/best practices in this post. I have been trying to "find" or "locate" a series of better / best practices to use as a checklist to ask yourselves as you work on a project, but there are so many around. More homework, create a series on different best practices, and why they are said to be best practices.

Why do I call them Better / Best Practices?

Some of you might wonder why I call them Better / Best Practices, when most people just call them Best Practices. Funnily enough, the great resource known as twitter lead me to a discussion on this... and how some people do not like the term Best Practice, as it deems the practice to be the BEST, and means there is no better way. Our industry changes all the time, and the Best Practices 10 years ago are definitely not the Best Practices now (or we wouldn't have issues with Legacy code), and if you have the Best Practice, you might never look for new or better ways to do things. Better Practices acknowledge they are better ways to do things, than the common or entry level way, but leaves the idea open that its an evolution, there is no right answer, just lots of answers, and you might be able to find a Better Practice tomorrow, that the Better Practice of today. I forget the person who blogged about it, I apologize for not crediting them. Any readers (yeah you in the corner) remember, let me know, and I'd be happy to credit them with the thought.

Thanks for reading, sorry it turned into a really long post. Hope you had a good laugh at my expense, or learned something.

Have a good one,
Gavin

15
February 2014

Gavin Pickin

Diversity - The Hot Topic in Tech - Scott Hanselman talks to Model View Culture

Chit Chat, Podcasts

I listen to a lot of Podcasts, and lately I've been listening to a lot of Hanselminutes, with host Scott Hanselman. Today I listened to one of the more recent episodes, with guests from Model View Culture. I was not sure what to expect, but soon learned that Model View Culture was a media company devoted to diversity in Technology... and the most interesting part, it helped me understand some issues and concepts about diversity that I think most people in the "Main System", generally white males, do not understand.

I urge you to step outside your comfort zone, and listen to this show.

  • Its sounds like a great new company pushing to lower barriers and boundaries.
  • Scott asks a lot of good questions, and learns a little more about dealing with diversity
  • You might learn that the small things you say and do might mean a lot more in a minority world.

http://www.hanselminutes.com/409/model-view-culture-a-new-media-platform-covering-technology-culture-and-diversity

The biggest point I took from this was, diversity isn't about me. I might feel awkward, uncomfortable, and not sure how to act because it might offend people... but guess what, THAT DOES NOT MATTER. The small level of discomfort I feel is only a taste of what those fighting diversity feel every minute of every day. So next time you aren't sure how to act, or what to say, think about how weird that makes you feel, how small that makes you feel, and try to imagine others feeling that every minute of every day.

That might help you go from being someone who gets defensive about diversity, and realize we can all act and do things a little different to make the world a little better.

Remember, if you feel out of place, or don't know what to do, then you're aware, and that is one step closer to helping.

I hope you take the time to listen, and think about something new.

Gavin

14
February 2014

Gavin Pickin

Conferences - cf.Objective() - Early Bird Rate Extended

cfObjective, Conferences

I had planned today to write a little message saying, quick last chance for early bird rates, and then I told you to get in while you had a chance. I got busy, as you do, and by the time I got around to it, I saw a tweet stating the Early Bird rate had been extended. Why? I'll let you read the message here but the important thing is, its Valentines, do your thing, and then you have 2 weeks more to convince your manager to send you to cf.Objective().

See you there, or else!!!

Gavin

14
February 2014

Gavin Pickin

Moving SSL certs from IIS on Windows to Apache on Centos

Apache, OpenSSL, Server Admin

We're migrating a series of Windows Servers to Centos, and in doing so, there are a number of SSL Certificates that need to be migrated too. Going through the whole process of creating new Requests invalidates the old SSL, so it can be a tricky transfer process, and in migrations, you want to try and streamline them as much as possible, so we wanted to export our SSL Certs ahead of time, import them and be prepared. To see how to export SSL Certs from IIS 6 to a .pxf here, I will add a few other walkthroughs for other versions as I complete them.

Now we have exported the file to .pfx, we can move the .pfx to our server. Once you download the file (ensure its Binary so the FTP applications do not mess with your line returns) onto your Centos / Linux box, we need to perform a few commands with openssl to take the secure locked pfx file, and extract our key and cert file to include in our Apache Vhost Configuration.

First, we're going to extract the key, and the first step is extracting a password encoded pem file. When you run this command, it will ask you for the password you used to create the .pfx file. Then it will ask you for a PEM pass phrase. You must enter one, or this command will not work successfully.

$ openssl pkcs12 -in www.goodbyeticket.com_cert.pfx -nocerts -out key.pem
Enter Import Password:
MAC verified OK
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:

 

Next, we need to extract the key and remove the passphrase itself. If you did not enter a passphrase, this will give you an error like the following.

unable to load Private Key
140622736611144:error:0906D06C:PEM routines:PEM_read_bio:no start line:pem_lib.c:703:Expecting: ANY PRIVATE KEY

 

Assuming you followed instructions, you should be able to run the following command, reading in the key.pem file we created in the last command (keep that name the same, its short, and its only an intermediate file) and then the -out file is the file you intend to use, so name it however you see fit, for me, I like to keep the year registered, period, the common name or url of the cert, and then .key of course, because this is a key. It will ask you for the passphrase, so enter that when prompted.

$openssl rsa -in key.pem -out 2013.www.goodbyeticket.com.key
Enter pass phrase for key.pem:
writing RSA key

 

If you cat the file, you will see the key is complete, it has no passphrase, no encryption, its a standard key.

Next we need to get the cert file out of the .pfx file. This is a 1 step process, just enter the command below.

-in is the .pfx you downloaded, and the -out is the name of the cert. I like to match my file names, with the suffix or extension to match the type, .key for keys, and .cert for certs, simple.

$openssl pkcs12 -in www.goodbyeticket.com_cert.pfx -clcerts -nokeys -out 2013.www.goodbyeticket.com.cert
Enter Import Password:
MAC verified OK

 

Now, this file does have some other STUFF in the cert file. Simply edit the file, and remove everything above the begin certificate line.

nano 2013.www.goodbyeticket.com.cert

Now, your files are ready to use in your apache configuration.
I got over that in more depth, as well as how to check your SSL is valid and the Chain is intact in this post here

 

Hope this helps, I know I'll be looking it up next time I have to do this.
Thanks,

Gavin

13
February 2014

Gavin Pickin

Exporting SSL Certificates from IIS 6 on Windows into .pfx files

OpenSSL, Server Admin

Working with Windows and IIS, you might come across the time when you want to move an SSL Certificate from one server, to another server, and you wonder how you can do this without starting a new request, and go through the whole process again. If you have the .cert .crt or .cer file, you can try and import it into IIS, but you'll realize, you need the CSR generated from the new IIS server, for the .cert .cer .crt file to match it, so you'll have to export the SSL cert to a .pfx. This makes moving SSL Certs from IIS Server to IIS server, but it also allows you to take the SSL and move it to an Apache httpd server using Openssl. This little guide will walk you through creating the .pfx file, preparing for importing it into your new Web Server, whatever you decide to use.

I assume you know what IIS is, how to open it, and how to view a website's properties. If you do not know how to do that, go use GOOGLE and come back once you get that far :)

So in the IIS display, view the list of sites, and right click > Properties.
Click on the Directory Security tab like the image below, and then click Server Certificate.

 

This will pull up the Web Server Certificate Wizard... here you can Add, Remove, Export etc. Click next to proceed.

 

We want to select the 4th option, Export the current certificate to a pfx file. 

 

Select the location where you'd like to save the pfx certificate file... make sure you name it something useful, and somewhere you can download or ftp the file to the server you're migrating the SSL Certificate to.

 

When creating a .pfx file, you need to supply a password. Make sure you remember this, you will need it later to import the SSL Cert, or extract Keys and Certs from the file (as we will when we move to Apache Httpd server with openssl)

 

Once you enter a password, you will see a summary of the Cert Details. Click next to complete the process.

 

Congrats, you have exported the file. Now you can ftp or download the file onto the machine you wish to migrate to.

 

Thanks for reading,

Gavin

Blog Search