Blog Archives - 21 Record(s)

Year: '2013' - Month: '12'

December 2013

Gavin Pickin

To Init or Not to Init - CFC Component Init Function

CFML Language, Techie Gotchas

In a comment on my Unit Testing on TDDSean Corfield mentioned that I did not need to explicitly call .init() on my object creation when using the new syntax... because the new syntax called it implicitly for you, if it exists, and fails silently if it does not exist. I know I had heard this somewhere, but I knew there was a reason why I was used to putting .init() on all object creation calls, but I had forgotten. Getting older, that time of the year, not sure what the excuse is, so I decided I'd do a little testing and try and jog my memory.

For some reason, I think the core of this issue came from our legacy code, and a lot of it still running on some ColdFusion 8 servers. We had been meaning to upgrade it to ColdFusion 9, but then ColdFusion 10 came out, and then we decided to migrate servers, and now 11 is coming out soon, all out new development is for newer versions, but a lot of our old code, we maintain, on the old boxes. So, the first thing I wondered was, when did this "new" syntax come out... and has it always done the initialization for you?

I have been touching up on my ColdFusion Object Oriented Programming lately, so while I waited to buy Matt Gifford's book Object Oriented Programming for ColdFusion from Packt Publishing (E Book on sale for only $5 right now), I have read over Adrian Moreno's OOP Blog entries at and Kevan Stannard's Site I like to read a lot of different material, and they both have some solid beginner information, but the one thing I didn't notice was, they are a little dated, and neither one mentioned the "new" syntax. All of the examples all explicitly called the init() function, as at that time, it was a convention to call the init() method, but CFML had not actually added it to the language, when those examples were written, in ColdFusion 8's time.

Doing a little research, Dan Skaggs pointed it out on his Blog back in April of 2010, and some of the comments said they didn't notice this change, one of them, even into ColdFusion 10. Ben Nadel had a lot of posts in July and August 2010 on new vs entityNew and CreateObject, using dynamic paths with the new operator, and how to use new with cfimport even with tags  I found some Railo notes, most importantly was a JIRA ticket in May 2010 when Micha added a ticket and completed the ticket (all in a day by the looks of it) and supported multiple syntax param options, released in Railo 3.1. I am not sure if there was script support before, or just some param options or not. 

<cfset test2=new TestNewOperator1(1)>
<cfset test1=NEW TestNewOperator1()>
<cfset test1=new TestNewOperator1(1,2,3)>
<cfset test1=new TestNewOperator1(a:1)>
<cfset test1=new TestNewOperator1(a=1)>


So, thanks to my research assistant Google, it looks like April / May of 2010... the cfml community received the new syntax, whether we all knew about it or not.
I found this article from Adobe, to confirm this... and something I didn't know.

ColdFusion looks for a method called initmethod() first, and runs that if it is found. If not, then it looks for a method called init() and then runs that if it is found, and then if neither are found, it just instantiates the component. Now, I tested this out in CF 9.0.2... and this is incorrect... initmethod does not get called... init is called if they both exist, and if init does not exist, initmethod is not called either. 

Another interesting tidbit, the new operator returns the value returned by init or initmethod, if void, it returns the instance of the CFC... so you dont have to return the THIS pointer. If you return something else, it will not behave as expected... since new will init it, but not necessarily always return the object, as best practices state you should always do. If you had your code setup to run the init as a separate call, and returned some value previously, like a boolean, created, etc, when using the new syntax, you might accidentally store the boolean by mistake, since the init is called implicitly now. I tested that, and it works as expected, although, if you follow best practices and return this, it would not be an issue.

Although, you do not need to return this if using the new syntax... but that isn't intuitive, or obvious, even Ben Nadel mentioned (granted it is an old blog post) that you must return the THIS pointer if you want to return the object instance... but you can return nothing, and the cfml engine will automatically return the pointer for you.

I tested Railo's compatibility, and it matches CF9's results, not the documented initmethod stuff. 
Then, I decided to find out, when did they remove the initmethod stuff? I did some more reading, and I found out they never removed it, it was just not documented in a way that I could understand it. And even when I did understand it, the documentation was still wrong. In Ben Nadels blog entry on cfimport and new works with tags too , he spells out the actual way it works.

  1. ColdFusion looks for the InitMethod attribute on the target CFC's CFComponent tag. If the attribute exists, it executes the method named within that attribute (CAUTION: If the name is not accurate, ColdFusion throws an error).
  2. If the InitMethod attribute does not exist, ColdFusion looks for a function with the name "Init" (which has become the de facto way to name CFC constructors) and executes it.
  3. If neither the InitMethod attribute nor the Init method are found, ColdFusion does not invoke any constructor and simply returns the instantiated CFC. In this case, any arguments to pass in using the new operator are simply ignored.

Adobe's documentation fail to mention initmethod is an "attributes" on the target cfc's component tag. This allows you to specify any tag as the function to initialize. I'm not sure why, but you could have ColdFusion initialize something other than the init, maybe knowing the init was used by legacy code, and the "new" initialization should be something else.

The other issue with their documentation is, they say

If it does not find an initmethod constructor method, it looks for an init constructor method. 
If found, ColdFusion instantiates the component and runs initmethod.

They obviously intended it to say runs the init method / function... not the initmethod method / function.
Note, if your initmethod attributes is misspelled, or set to an invalid function, it will throw an error. I was thinking about how it might be cool to make your init method private, so you could only call the init on new creation using the "new" operator, but the initmethod must point to a valid public, package, or remote method / function.

The short of it is, only CF9+ and I believe it is Railo 3.1+ support the new operator. The operator is pretty flexible, fixed and dynamic paths, it will auto init for you, will return the pointer implicitly (although might be confusing) or return explicitly something other than the THIS pointer (really confusing - I do not recommend this), and work almost identically across the Adobe ColdFusion and Railo, although, Railo does not support the initmethod Attributes in the CFC definition. 

If you use createobject, cfinvoke, or cfobject, you need to initiliaze your components, if you use the "new" operator, you do not.
So do not double init like I did :)

Thanks again Sean Corfield, for pointing it out... and starting me on this journey.


My Index.cfm File

My main.cfc (multiple gist revisions for variations)

December 2013

Gavin Pickin

Unit Testing 02 - TDD - Lets Write Tests for our Objects, then Build them to Pass the Tests

Unit Testing

So we're back for another post in my Getting Started with Unit Testing. In the first post, we got our Testing Environment Setup, so we could browse to our project, then to the first blog, and the first step in that blog, where we could see we had 2 Test Bundles (or Suites) with 1 dummy test in each, copied from the documentation. 

In this post, we're going to remove those dummy or sample tests, and actually write some tests for our new objects. Our objects are actually empty so far, so we'll write some tests, then test them, they'll fail, and then we'll add some code to our objects, to get them to pass. This all part of the Test Driven Development process. I will not explain the pros and cons here in detail, but in short, if you write your tests to cover your specifications, and edge cases, your code will always be better, you can maintain it easier because all of your tests are there, for any member of the team (whether they know the specs and or edge cases) and because your code has to be testable, it should be shorter, single function methods, and just more DRY in general.

Reminder of the setup.

Ok, so, for all of you out there, the Github repo is setup. Star, Fork, Clone, Follow Me, all the GitHub actions you want.

Local will be

Dev Server will be (when I get it setup in the new few days) 

I will not note all the project setup, like naming the index.cfm h1 tags, and adding the links, as thats all unimportant in the scheme of things.

Ok, so I've created a duplicate of the Blog 01 - Step1 from our last post, and we'll start from there. 

Step 1 - Remove the Dummy / Sample Tests from our Test Suites

First thing we're going to do is remove the testIncludesWithCase function / test from the /blog02/Step1/test/unit/CFMLServer.cfc file.
Next we are going to remove the testIncludes function / test from the /blog02/Step1/test/unit/Website.cfc file.

We are also going to update our tests to extend the TestBox BaseSpec. This allows the tests to do a lot more nuts and bolts stuff, especially with MxUnit styled tests -  extends="testbox.system.testing.BaseSpec" - Note, this fixes the isExpectedException error you might see if you do not have this.

Now we are just left with our basic shell, and they'll look like this (apart from the display name of course).

component displayName="Website.cfc Unit Tests" extends="testbox.system.testing.BaseSpec" {

    // executes before all tests
    function beforeTests() {}]

    // executes after all tests
    function afterTests() {}


Now, we're going to browse and run our Empty Tests, and see the results.
You should see something like this.

We have 2 bundles, 2 suites, but no specs / tests? so 0 pass 0 fail 0 error. Now we are moving onto Step 2

Step 2 - Add Tests to Test if Our Objects Initialize Correctly

We're going to work with Website.cfc first, so we open /blog02/Step2/test/unit/Website.cfc and add a function called testObjectInit(). It is going to assert that the variable we pass it, Website, is of type component. The code will look like this

component displayName="Website.cfc Unit Tests" extends="testbox.system.testing.BaseSpec" {

    // executes before all tests
    function beforeTests() {}

    // executes after all tests
    function afterTests() {}

    function testObjectInit() {
        $assert.typeOf( "component", Website );


You might wonder where the Website variable is coming from, and you're right, we haven't created it, but we're going to run the test to see what an error looks like. Your tests might have errors as you write them, and its important to know what the look like, and how to determine how to fix them. So lets browse to our project, click on blog-02, Step2 and see what the results are.

You will see that the summary has 2 bundles, 2 suites, 1 spec, 0 pass, 0 fail, 1 error. If you scroll down through the bundles, you'll see CFMLServer.cfc is ok, we haven't edited that, but Website.cfc has the error. The variable WEBSITE doesn't exist. There is also " + " button, if you click that, it expands, and shows you the stack trace, and allows you to determine your error (normally, not in this case), and fix it. Below is an example of the Stack Trace, its running on Railo, so the colors are not the usual Adobe ColdFusion blues.

Ok, now we're going to edit the Website.cfc located in /blog-02/Step2/test/unit/ folder, and we're going to add some code to the beforeTests() function. This code runs before the tests, as the name explains, and allows you to setup for your tests, so your tests can share some code. In this case, we're going to Init the component. Note, these functions are global, this means beforeTests() is run one time before all these tests in this bundle, and afterTests() is run one time after all the tests. If you need a variable or fresh set of data for each test, you can set those in two functions, called setup() and tearDown() which are performed before and after each test respectively. Since setup() and tearDown() are called for each test, these 2 functions receive an argument called "currentMethod" so if you need to change the setup and tearDown depending on the method, you can easily do so.

In this case, we're going to add the component creation to the beforeTests(), so we can use it throughout our tests. To do so, we add the following code to the Website.cfc Unit Test in the beforeTests() function

Website = new blog02.Step2.model.Website().init();

Remember, each iteration we do, needs to update the Step inside this initialization as well. I'll be doing that each time, so if you're following along, and your test doesn't do what it should, make sure the setup() is creating the right object from the right Step.

Lets browse, and see what the results of our tests are now.

Now, we get an error stating there is no function called init in that component. We haven't created it yet. Since this Error was in the beforeTests() function, the tests do not even run. So, lets add the init function, just an empty one for now, so our tests do not error. Lets add the following code

function init() {}

If we run our tests again, we get an error, because our init method does not pass anything back to be stored in our Website variable. Let's follow best practices and return this, which is the component. That way we can continue to work with the reference to this component.

function init() { return this; }

Now when we run our tests, we test that our Website variable is a component, and indeed it is. The .init() call returns this, which is a reference to the component itself.

Step 3 - Create a Test for Method count() in Website.cfc

We're going to create our first real Method in our Website.cfc (other than the best practice mandatory init() of course)? count(). This function gives us a count of the number of websites we have. Our specification for this method is pretty simple right now, when we call this function, we expect an integer back, greater than equal to 0. We're testing the functionality of the method, not how it does its job, so we don't care if it has a database, a flat file, or like right now, this method will return hard coded numbers.

So, lets add the new test in blog02/Step3/test/unit/Website.cfc called testCount() and we'll add the assertions we need to match our specifications.

function testCount() {
    var count = Website.count();
    $assert.typeOf( "numeric", count );

Ok, so what we have done here is add a function, called testCount(), in that method, we call the count() method on our Global Website object created in setup(), and store it in the variable count. We store it in a variable, because we're going to use it several times. So our first Assertion, is we assert that count is typeof "numeric". Lets save it, and run our first. Browse to blog02 - Step3

You can see in the Website bundle, we have 1 suite, and 2 tests. 1 Pass testObjectInit(), 0 fails, 1 error testCount(). The error is because we wrote the spec, without building the function / method in our object yet. So, thats the next step.

Step 4 - Create the Method count() in Website.cfc

Now we're going to create the actual count() method in Website.cfc that our test is testing. So open up the file /blog02/Step4/model/Website.cfc

If we add this count() function, 

function count() {
    return "there are 15 websites";

The test errors, because the return is not numeric.
Lets change it to 

function count() {
    return 1.5;

And now, Blog 02 - Step4 passes 2 tests.

Step 5 - Add Second Spec / Assertion to testCount() Test

Now we're going to add a Second Spec, to test the count() method more fully. We're going to check and see if its not a floating point number? and that the number is greater than 0, since we cannot have 1.5 websites, or -5 websites. 

Just to clarify, I am going back and forward on purpose to show you piece by piece the steps involved. Once you get into the groove, you might right 8-10 specs in 4-5 tests, and then run the tests, see them fail, and then go and right the methods to satisfy them. You do not and should not do it spec by spec.

function testCount() {
    var count = Website.count();
    $assert.typeOf( "numeric", count );
    $assert.assert( int(count) == count, "An integer was expected, but " & count & " was received");
    $assert.assert( count >= 0 );

Now you can see we have 3 assertions, first, ensuring we are returned a numeric value, then we test to ensure its not a float, and then we assert that its greater than or equal to 0. Lets run the tests, and see what happens. You might wonder what is that message after our float assertion? It is a way you can pass a useful message back to your test, so you know what the test failed. You can leave the generic message, or insert your own. Here, I put the actual value of the count into the message using concatenation. 

Now, if we go back to our /blog02/Step5/model/Website.cfc you can see we were returning 1.5, which of course fails the not float test. Lets update it to -5 and see if our next test fails.
Change from

function count() {
    return 1.5;

Change to

function count() {
    return -5;

Run the tests

Did you see that message, Expected False to be True. That is not a very friendly message, so lets add our own message to that test. We'll update, it so it looks like this

$assert.assert( count >= 0 , "Expected " & count & " to be greater than 0");

You can see that is almost self documenting, it makes the next Developer who looks at your test understand what was expected, and what was actually received, and makes it easier to fix the issue at hand.

Now, we're going to return a valid count, the number 10. It is numeric, not a float, and greater than 0, it should pass.

function count() {
    return 10;

All the tests pass. I've left all the return statements in my code, on github, so you can just uncomment the different return values, so you can see how the tests pass and fail differently.

Now we have build our count() method, and our testCount() method to make sure it works correctly, but its not a very good method, if the count() is hard coded. The beauty of Unit Testing is, when you change the way your functions work, your Unit Tests can make sure your modifications still provide valid responses with the Tests you have already written.

We have covered quite a lot today, including our own flavor to our unit testing with our custom messages. This is quite a long post, so I didn't get it all done and released as quick as I had hoped. Our next post will walk through taking the count() method, and changing the way it gets that value it returns. We'll look at a couple of different ways to do it, so check back then and follow along.






December 2013

Gavin Pickin

Unit Testing 01 - Setting up my Testing Environment to Test Unit Testing

Unit Testing

Getting Started with Unit Testing is my new Series to help myself, and you, get started with Unit Testing. I am definitely not an expert, but as I go through this process, I'll try and learn and share my experiences, so we can add to the number of ColdFusion and CFML developers using Unit Testing, like they should. Today is the first in the series, so its not that exciting, just mainly a lot of setup.

Ok, so I'm going to start doing some Unit Testing, and I'm going to test my unit testing, with my Test Environment. In english, I'm going to setup a play site, so I can walk through setting up a site with the sole purpose of creating Unit Tests, and I'll install TestBox and play with MxUnit Compatible tests, and some BDD (Behavior Driven Development) test style too.

Why did I choose TestBox? Like I mentioned in my last Unit Testing blog post, MxUnit is a great tool, and has been for some time, but due to commitments, changes in the community, and life, it is not currently an actively maintained project, although just to be clear it still works, and is not dead. Luis Majano from Ortus Solutions (the maker of ColdBox) has created TestBox as a way to extend MxUnit (includes backwards compatibility) and develop it further, and in version 1.0 (just released mid December 2013) it already supports MxUnit styled tests, and new BDD test styles. 

If you are an active member of the ColdFusion community, you will know of Sean Corfield, creator of Fw/1, the other big CFML Framework being used right now, has mentioned on Twitter he is already testing his MxUnit tests with it, and would like to see it succeed. Sean has been involved with almost everything in CFML's history that has been successful (IMHO). If he is willing to test it, give feedback, and try to help it success, I think that is a great sign. He tweeted today that he ran several hundred tests using TestBox and got them to pass, I'm eager to see how this plays out.

Long story short: If the 2 biggest CFML Framework creators are behind this, I have a strong feeling it will be successful, and pick up the torch where MxUnit left off.

Please note, no one means any disrespect to MxUnit, its a great tool, and it has served the community well and still does, the efforts every contributor gave it are greatly appreciated. It just seems like it is time for a new team to pick up where they left off, and continue the great legacy that MxUnit started and keep it evolving.

Ok, now lets get this moving. 

To make it easier to follow along, I'm going to make a Git Project, and try and break down my code into steps, so for each blog post, there might be several chunks. It will all be available on Github so you can pull it down, and see the code I write (I'm sure some of it will make you cringe), and run the tests locally. I am also going to setup a subdomain on my site, so you can actually run the tests on each chunk, on the live site, so you can see how the run, if you don't want to download and set them up on your machine.

Ok, so, for all of you out there, the Github repo is setup. Star, Fork, Clone, Follow Me, all the GitHub actions you want.

As we work through this blog entry, we'll setup the overall structure, and get some code in place, and we'll be able to run a couple of basic tests, and make sure our setup is solid, before moving on.

This blog is blog01 in this series, so everything will be put in the blog01 folder, under the root. I am using a local url and dev server url making use of subdomains? Blog-UnitTesting-Series or buts for short. Appropriate because there can be no buts about it, we should all be unit testing.

Local will be

Dev Server will be (when I get it setup in the new few days) 

Now, we need to think about what should we be testing, everyone does a Calculator, because it is simple, and everyone understands the basics of a calculator, there are several functions, but really, that is almost too simple, so let me think about what might be a more interesting, and useful idea to test. Ok, so I decided we're going to build a little tool to help manage our websites, so we'll have a few objects, and we'll build on them as we go. 

So, first we'll make a couple of objects. We'll make a model folder to store our CFCs, this isn't going to be a big project, so we'll keep it pretty flat in nature. We're going to create the following cfcs.


Other files in the folder


Ok? its very simple, lets download TestBox and get it installed. Adam Cameron has started blogging on this very topic, so he's ahead of us, you might want to check out his installation posts if mine are too simplistic. Adam has been doing Unit Testing for a lot longer than me, so mine will be the "dummies" version. 

Lets go to and we'll download TestBox V1.0.0 which is the current latest version. It was only released a couple of days ago, so we'll be part of the group Testing out the TestBox, kind of funny.

Unzip the file, and drop the TestBox directory from the zip into the Root. You can map it, but this is setup as its own site, for simplicity, so we'll drop it there. 

We're going to create a test folder, that will store all of our tests in it. Inside there, we'll create a few subfolders to put our different types of tests in.

integration - for our integration tests
unit - for our unit tests

Inside unit, we're going to add 2 unit tests, one for Website.cfc and one for CFMLServer.cfc
Inside Website.cfc we'll place the following code

component displayName="Website.cfc Unit Tests" {

// executes before all tests
function beforeTests() {}

// executes after all tests
function afterTests() {}

function testIncludes(){
          $assert.includes( "hello", "HE" );
          $assert.includes( [ "Monday", "Tuesday" ] , "monday" );


Inside CFMLServer.cfc we'll place the following code

component displayName="CFMLServer.cfc Unit Tests" {

// executes before all tests
function beforeTests() {}

// executes after all tests
function afterTests() {}

function testIncludesWithCase(){
          $assert.includesWithCase( "hello", "he" );
          $assert.includesWithCase( [ "Monday", "Tuesday" ] , "Monday" );


Now, you might wonder what those weird tests are? right now, they are just placeholders, a couple of Dummy Tests from the TestBox documentation, to test to make sure our Testing Environment is setup right.

Now, to run and display the results of these tests, we will add a little code to our index.cfm page, in the step we're in, Step1.

<cfset r = new testbox.system.testing.TestBox( directory="blog01.Step1.test.unit") >

Now, what this code does it create a new TestBox runner, and we pass the directory of our Unit tests into the runner. The runner gets every CFC in the Unit Tests folder, and will run them all (unless we tell it otherwise). 

So now, we can go to our browser, and test our tests.

As you can see in the screenshot above, if we browse to Blog 01 - Step1 - you can see there was 2 Bundles Run. CFMLServer.cfc and Website.cfc. Each one had 1 test, our dummy test, and they both passed. Now, it looks like we're setup, so we can actually start TDD in building out Tests and Components out.

So I'll leave it there. I'll commit my changes, and post this. The dev server will be online soon with this, so you can follow along, until then? check out my github repo, and follow along.

Thanks for reading, tomorrow, we really dig deeper.






















December 2013

Gavin Pickin

FusionReactor - A little help from my friends and my Blog is up to Full Speed

CFML Server, FusionReactor, Techie Gotchas

If you have been reading my blog over the last few weeks, you might have noticed a few things change this week. I have been running this blog on ContentBox, for a few reasons, one to check it out, and two because I was having trouble deciding, and I knew more about ContentBox via ColdBox Developer Week videos than the other CFML options out there. So far, I have quite liked using it, although I haven't themed it myself, or added any GAVIN styled modules to it, but there has been one BIG issue for me, SPEED. I wasn't sure why there was a speed issue, but I was determined to find out, before just giving ContentBox a "speed" black label. This week, I looked into it deeper, and if you didn't notice, the site is flying now, much like it should have been, so if you thought my site was slow, please don't attribute it to ContentBox... there was something else at fault... read more, and you'll find out what, and how I found it.

A little background. I have been involved with a server migration, we got some snazzy new hardware, which might not be the latest and greatest, but compared to what we were running things on, these are awesome servers. Having 32gb of ram, with SSD drives for the CF box and the DB box, sites fly like I didn't think was possible, and everytime I go back to get a site off the old servers, I am quickly reminded of what we had to deal with. This blog runs on a box with ColdFusion 9 and Railo 4.1, its not fully loaded yet, so performance should be slick. All of our other sites running on this machine, ColdFusion, and Railo seem to be extremely quick, the only slow one, this blog. At this point, I was concerned it might be related to ContentBox, or a piece of it, maybe running on Railo, or MySql... but I was trying to give it the benefit of the doubt, because, I wanted it to be successful. So, time to dive deeper, and see where the problem lies.

The first thing I usually do is look into slow queries running on our MySql Server. I was running MariaDB for a while, but had to roll it back to MySql, but I'll save the rest of that story for another day. Nothing on MySql was close to being slow, which is strange, so I decided to check Railo logs and see what was going on. The requests all seemed equally slow, nothing especially obvious.

This is when I realized it was time to try out FusionReactor. I had seen a couple of presentations at CF Objective, and talked to the FusionReactor guys, and it looked like an amazing product, its been on our list of products to get setup, on the new servers, no point installing it on servers we were migrating off of. I downloaded the trial, and ran into a couple of issues, which I discussed here, but once I got my act together, I installed FusionReactor, setup the monitor for ColdFusion and Railo, and now, its down to business.

I let it run for a little while, so I could compare my blog with the other Railo sites, and get a gauge. I was correct in my assumption, the blog was consistently running much slower than all the other sites. I checked for slow requests, and almost all of the slow requests, were coming from this blog. I guess slow jdbc queries, and none of them were from my blog, so my assumption about the database queries not being an issue were right too. I clicked on the "Relations" tab in the slow requests, and scrolled down all the related calls. On a given request, there were several queries, all 1 ms and 0ms, obviously not the issue, and then I notice, all of the Hibernate calls are very slow, some taking 1-3 seconds, and some over 5 seconds.

I found the source, Hibernate was running like a dog... but why? I do not use Hibernate much yet, most of our sites are legacy, and we're not in the ORM world yet, so this makes sense why this is the only site running slow, its the only site using Hibernate. Since Hibernate is out of my area of expertise, I decided to hit up a couple of friends on Twitter, and quick as a fiddle, Brad Wood was there to help out. He admits he is not a Hibernate expert either, but he would he happy to have a look, and see where the issue is. He hadn't heard of any ContentBox sites with this issue, but most he knew of were running MSSQL, so I gave him a login to FusionReactor, and he jumped in.

After confirming my findings, he jumped into the stacktrace for the Hibernate request. This is a very cool feature, being able to see that from inside FusionReactor, it really helps you dig into the request more... and from that, he noticed a couple of things out of place.

java.lang.Throwable.getStackTraceElement([Native Method] java.lang.Throwable.getOurStackTrace( - locked <0x17e57191> (a java.lang.Exception) java.lang.Throwable.getStackTrace( railo.runtime.debug.DebuggerImpl.addImplicitAccess( railo.runtime.type.scope.UndefinedImpl.debugCascadedAccess( railo.runtime.type.scope.UndefinedImpl.debugCascadedAccess( railo.runtime.type.scope.UndefinedImpl.getCollection( system.aop.matcher_cfc$cf._1(/home/www/ system.aop.matcher_cfc$cf.udfCall(/home/www/ railo.runtime.type.UDFImpl.implementation( railo.runtime.type.UDFImpl._call( railo.runtime.util.VariableUtilImpl.callFunctionWithoutNamedValues( railo.runtime.PageContextImpl.getFunction( system.aop.matcher_cfc$cf._1(/home/www/ system.aop.matcher_cfc$cf.udfCall(/home/www/ railo.runtime.type.UDFImpl.implementation( railo.runtime.type.UDFImpl._call( railo.runtime.ComponentImpl._call( railo.runtime.ComponentImpl._call( railo.runtime.util.VariableUtilImpl.callFunctionWithoutNamedValues( railo.runtime.PageContextImpl.getFunction(

It seemed to get stuck on a couple of lines, which looking at the ContentBox code was a simple if statement.

if( len(instance.annotation) AND structKeyExists(arguments.metadata, instance.annotation)){

Looking at the stack trace, he wondered what all of the UDFImpl calls were. Being I am using Railo, he jumped into the source code, its really handy in these types of situations when you have the source code available... and in a minute or two (he has a local clone of the source) he had a lot more information. 

All over that Java file, was a bunch of these calls, and they were the slow point

if(debug) debugCascadedAccess(pc,scopes[i].getTypeAsString(),key);

Now I think to myself, oh damn it, did someone leave Debugging mode on? Its a production server, it shouldn't be on anyways right... but it was, and it was left on. I've had a pretty good week for doing stupid things... and this is just another one on the list. 

debug=pc.getConfig().debug() && ((ConfigImpl)pc.getConfig()).hasDebugOptions(ConfigImpl.DEBUG_IMPLICIT_ACCESS);

This bit of code was really slow, and it mentioned one of Railo's cool debugging features (when not used in production LOL)... Implicit Access... which allows you to identify which variables are being called without their scopes. The only downside is, its really really slow to do so. 

I turned off Implicit Access, and all Debugging, and within seconds, the site was lightning fast, like it should be.

So lessons learned?

FusionReactor, is an amazing product, its hard to not see the value in the product, in the few hours I was playing with it, I am sold. I know Railo is releasing a similar tool, specific for Railo, which will get you deeper into their server, but its hard to compete with such a solid, enterprise tool like FusionReactor. I will probably love it more when I learn more of what it can do.

Implicit Access Debugging is awesome, just NEVER use it on Production.
Debugging in General should not be used in Production. 
Next time something is running slow, I'm going to make sure Debugging is turned OFF.

Brad Wood is a good guy, and was really helpful, and I owe him a few dinners at least, at cfObjective, or In The Box Pre-Conference

ContentBox is not slow, all the slow issues related to my blog had nothing to do with ContentBox, but all about me and my server being in Debug mode. That was the only negative so far with my blog, I'm really happy with ContentBox, now I really have to theme it, and develop a few modules. Maybe those will be blog posts you'll see on here soon.
Same can be said of Hibernate, It looks pretty guilty for a while, until we dug into the source

Having the Source good available for the server you are working on, is "Really Helpful". Railo is a great product, and having the source code is just another plus in their column.

Another lesson, you should come back and read more of my blog posts, because I'm worthy of being laughed at... and I'll make a lot of mistakes, so there might be a lot of good things to learn from me :)

Thanks for reading,


December 2013

Gavin Pickin

Deals and Steals - Books and Training - Packt Publishing $5 Ebook Special

Books and Training, Steals and Deals

Its Christmas time, and its all about shopping right? Well, maybe not, but there are sometimes a few good deals to be found, and today is one of those days. Packt Publishing, one pretty reputable book company that deals with books for IT Professionals, Administrators and Users, is having an EBook Bonanza… where every single Ebook they have, which is almost 2000 books, are all going for $5. They support multiple formats, and yes, they are only $5 each. This special lasts until January 3rd, so jump on it, and soon.

If you want a paperback copy of course, Amazon is always awesome, and you can check all of Packt Publishing books listed here on Amazon. Note the Kindle Edition Prices on Amazon are 14-25 dollars, just skimming down the page. So this is a great deal, but more importantly, are these books that you want really want? I have a couple already, in paperback, and I have my eyes on several others, and I'll tell you why I'm going to snap them up.

Railo 3 Beginner's Guide

Not this is not to be mistaken for a CFML Server Book. Its actually a guide to getting beginning with CFML itself, but obviously you're using Railo and not ColdFusion. It has a lot of good information for a beginner, and has a few bits and pieces I didn't know about the server too. Amazon has Look Inside available if you want a sneak peak. Pretty Good Book
Packt Link - Amazon Link 

PhoneGap Mobile Application Development Cookbook

Not using PhoneGap before, this was a good book to just get the basic concepts and how to apply them with PhoneGap. It didn't go into a lot of detail, but Matt Gifford (producer and sometimes host on CF Hour) did a great job with the book. It might not be too detailed, but its a simple beginning cookbook. I found it very interesting, and good reading. I just wish I had my laptop next to me while I read it, so I could play along. Family trip, had to behave, books good, laptops, not so much :)
Packt LinkAmazon Link 

Ok, next is a series of books I am going to buy, and their aren't bought yet just because I have to fill up my cart before I check out, so far, I've picked about 7 or 8 books to buy on this special, and here they are.

Object-Oriented Programming in ColdFusion

This is another written by Matt Gifford, and this is supposed to be a must read for ColdFusion developers. It has some good reviews on Amazon 4.1 out of 5, and it has been recommended to me several times, so now at $5, I have to get it.
Packt Link -  Amazon Link 

Mastering Web Application Development with AngularJS

Angular is a hot topic, and I know several developers choosing AngularJS over EmberJS so its worth investigating more. It has 4.3 out of 5 on Amazon, and looks like a good read.
Packt Link - Amazon Link 

Learning jQuery - Fourth Edition

jQuery is hard to avoid these days, and although I feel comfortable with it, there is still a lot I am sure I need to learn. It has 5 out of 5 for this version, albeit only 5 votes, but previous versions have been popular, so worth a read.
Packt Link - Amazon Link 

Responsive Web Design with HTML 5 and CSS3

Being a full stack developer my whole career (I guess you could call it a career) I have always dealt with the front and the back, and this focuses on the right things for front end moving forward. With 4.3 out of 5 on Amazon with 46 reviews, it sounds pretty solid.
Packt Link - Amazon Link

Object-Oriented JavaScript - Second Edition

I've heard some good things about this book on podcasts and around the place, with 4.3 out of 5 on Amazon with 41 reviewers, it did enough to get on the list.
Packt Link - Amazon Link

CentOS 6 Linux Server Cookbook

Doing a lot more Server side work with Centos lately, I think this is a must have for me. I like the Cookbook style, 5 out of 5 for the 5 reviews on Amazon, easy choice.
Packt Link - Amazon Link

Linux Shell Scripting Cookbook, Second Edition

Only 3 reviews, but 5 out of 5 on Amazon, Cookbook style again sold me. Shell scripting is something i need to do more with, automation and server side technologies are one of the many things on my list to improve on.

Packt Link - Amazon Link 

I had thought about this one, but not sure

Apache Tomcat 7 Essentials

With Railo and ColdFusion using Tomcat these days, I'd like to know a little more about the beast behind the servers. This book doesn't have the best reviews… so might have to do a little research, although, for $5… might be better to just buy it and read it for myself.
Packt Link - Amazon Link


There are a lot of other great topics, Node, Express, surprisingly a lack of EmberJS, also some good Clojure, Ruby, Python, Drupal, Wordpress, Android, IOS… pretty much anything you're thinking about (except EmberJS) is there.

Well, worth the look for $5. 
If there are any good ones I have missed, that you think I should reconsider, please, let me and the readers know.
Happy Holidays, and get something good to read (instead of talking to family lol)



December 2013

Gavin Pickin

Techie Gotcha - CFML Server - Coldfusion 9 WSConfig vs JNDI - Web Server Connector Issues

CFML Server, Techie Gotchas

After installing ColdFusion as many times as I have, usually, you can plod through it, and there isn't too many really weird things that pop up? until this week. Yes, this is another bang your head on the desk story. One of our developers is stilling using Windows 7, and we're setting up ColdFusion, Railo, and Apache to round it off. We get ColdFusion Installed, get Railo and Apache installed, and its time to connect using the WSConfig tool, and ta-da, a big fat error.

Could not connect to any JRun/ColdFusion servers on host localhost.
Possible causes:
o Server not running
-Start Macromedia JRun4 or ColdFusion MX server
o Server running
-JNDI listen port in blocked by TCP/IP filtering or firewall on server
?-host restriction in blocking communication with server


A summary of whats going on here, under the covers is, when ColdFusion is running, a special service is transmitting that is running by listening on a given port. That port has changed with different ColdFusion server versions over the years, and that was the confusing part, most of these issues, are all documented in regards to CF 7, not 9.

Ok, so first, we rule out the Server not running cause? because its running, just fine on its own Webserver? we're handling requests, no problem there. Its running, just the wsconfig tool doesn't know its running.

Next, we look at the JNDI listening port? listed in
We turn off all firewalls, we even turn off Antivirus and AntiMalware and AntiAntiAnti Tools.
Still no go? so we run a command

netstat -an

We scroll down through all of the Protocols and ports, and the ports from out file is listed.

Next we look at the Host restriction in, blocking communications with the server.
Nothing special there either? just a Subnet mask

Someone mentioned looking through your hosts file, because if you have hosts records with IPs that don't resolve, that can affect it too? but nothing there either.

We decided to uninstall CF, and try a couple of other completely useless tasks, and waste a lot of time.


Then, we decided to look through the logs and see if we saw anything fishy. and we found a really weird IP address.
It seems our Router gave us 10.0.1.* ips? which translates to subnet mask.

So in, it is blocking our subnet mask, because they don't match. 
The weird part was, why when browsing locally would our wifi ip be used, and not since we were working with localhost.

So we turned off wifi, restarted the wsconfig tool, and suddenly, the tool could see that ColdFusion was indeed running.
We got it hooked up, and away we went.

Related Links

Russ Michaels - CFMX7 Installation and Web Server Configuration Tool fails with JNDI ports blocked

Adobe Forums - CF9 Web Server configuration tool not finding Coldfusion

Interesting, because with all my searching, I didn't see our own ip, and subnet mask affecting the configuration.
Hopefully someone finds that interesting, or helpful, if not, you can all just laugh at me :)



December 2013

Gavin Pickin

Techie Gotcha - CFML Server - Follow up to Upgrading your Java JRE / JVM - Do Not Forget

CFML Server, Techie Gotchas

After posting my last post... about wiping the dust off your JRE and updating it, for your CFML Server, I thought, there are a couple more things I better highlight. One of the issues you might find when updating (there aren't many really) is that all your java settings that the JRE stored in the old folder, are no longer in the new folder, the most important one I think, is the Java certificate keystore.

Certain tags, like CFHTTP cannot communicate over SSL unless the cert is in the keystore... so you (or a co-worker) might have had to add the certificates to the keystore. When you upgrade JRE / JVM, these changes do not go with you, so you need to make sure you export them all and import them into the new keystore.

You can obviously use the command line, and while the command line should be your friend, Open Source should be too. CertMan is a great little CF Administrator extension, that works in CF8 / 9 / 10, and allows you to use a nice user interface to manage the certs. You can visit CertMan on RIA Forge here

If you are using CertMan, you obviously can only interact with the JVM that started ColdFusion. So, if you need to roll the JVM update back, you can do so, use the CertMan to export all the certs you need, and then update the JVM Path again, and then import all the Certs back in. You can use the command line to do this, but its much easier using CertMan, since you can see the certs, their expiration dates, common names, all in a simple html table layout. 

This is the only real issue I have seen with updating the JVM, and its more common than some of the other issues that might arise.
Hopefully CertMan helps, and if you can, export the Cert Keys before you update the JVM, to save yourself a couple of headaches.

If anyone else has come across other JRE / JVM upgrade issues, please share your experiences in the comments below.



December 2013

Gavin Pickin

Techie Gotcha - CFML Server - Wipe the dust off your JRE and Trade it in for a New One

CFML Server, Techie Gotchas

Everyone is all excited about ColdFusion 11 coming out soon, the public beta must be getting very very close to being available now. CF Summit raved about all the cool new things that Adobe is aiming to put into ColdFusion 12 (here is Adam Cameron's blog Entry where Micha from Railo discusses some of Coldfusion 12's new features ), most people are using ColdFusion 10, or migrating to 10 from 9... right?

So what am I doing? I'm upgrading a box still running ColdFusion 8. Yup, its EOL… well, Jrun which is it running on is EOL, and Adobe no longer support it with Security Updates etc, but I have to support it still… if only for just a little bit longer. So, I decided I should probably update the JVM, its been a while, and looking at some blog entries, there are a lot of good reasons to update JVMs, so thats what I am doing... and as usual, I have a couple of lessons to share, so you don't make the mistakes I do. 

The JVM can be a little scary, because if you get a setting wrong, ColdFusion won't start, and you have to figure out how to get to the jvm settings, because you normally change those settings in the ColdFusion administrator. Don't worry, its not that scary, and this article and a few links I included for more information, will make sure if you have to upgrade your JVM, which you probably need to do, or should do, it will be a pretty easy task.

Adobe has one article here, letting you know what Java updates are supported, here, at the time of writing, 1.6.0_35 was current, but any 1.6.0_n update would be supported.

Charlie Arehart has a good one here, talking about some of the serious bugs not fixed if you are running anything under Java 1.6.0_24.

If you are like me and you just browse over Charlie's post, there might be a couple of things you miss… so I'll highlight those Gotchas here, so you don't do the same thing as me. I recommend you read Charlie's post in full actually, some interesting stuff, but finish reading mine first, ok.

This entry has some good information… but the key thing to see here, even though you point the Java Home directory in the jvm.config file to your JRE folder… you cannot download the JRE version.

Why you ask? ColdFusion requires the hotspot server files, and that is not included in the JRE. Ok… so reading this, you go to, find the 1.6 JDK version you want, JDK 45 is the latest and greatest, and CF8, is not certied for Java 7, since CF 8 EOL'ed before Java 7 was verified for any version of CF. You accept the terms, and go to download the file, and up POPS Oracles single sign on login screen. 

I guess you don't need to create an account and sign in to get Java 7, or even 8, yes, Java7u45 is out, and Java8 is out too. Anyways, since Java6 is considered old, you'll have to sign up an account, and sign in.

Once you download the file, you can install the JDK.
You can change the install directory for both the JDK and the JRE.

Once it installs, you go to CF Administrator, and paste in the new path, to the JRE right?

Wrong… that is still the normal JRE.

Inside the installation folder of the JDK, there is a JRE as well, and that is the one with the server folder in the bin that you need for Coldfusion.
So you update the JVM setting to the path of the JDK/JRE folder, and now you are good to go.

What if you made a mistake the first time, and chose the wrong JRE location, like me?

Well, you can go and restore the backup file. jvm.backup to jvm.config, which in a single server is in 

Adobe's article I mentioned earlier has the location of the jvm.config file for CF9 and Mutli Server Setups here.

Or you can update the jvm.config file directly.

Note… you can use forward slashes, in your paths, but on windows, you can use forward or back. If you paste backslashes into the java-home line like the following, it will error


You have to use forward slashes like 


Or escape the backslashes, like this


Note, if you use the CF Administrator, and paste in C:\ColdFusion8\runtime\jre it will escape them for you.

Ok, again, nothing too complicated here, but I installed Java 1.6.0_45 today, and it worked a treat.
Just make sure you don't make these Rookie mistakes, especially in production, as you might be frantically trying to find the runtime/bin folder to get to your jvm.config file to make the changes to get it back up and running while you figure out what you did wrong.

UPDATE: After I posted this, I forgot about the Java settings that might get lost when you upgrade, most significantly, the Java Certificate Keystore. Read this follow up. Techie Gotcha - CFML Server - Follow up to Upgrading your Java JRE / JVM - Do Not Forget

You think this was fun, wait until I tell you about the JNDI issues I had with the wsconfig installing CF9 on a windows machine for a developer. I've installed it literally 20-30 times, maybe more, and never come across this, until this week. Fun times.

Happy Holidays, thanks for reading,


December 2013

Gavin Pickin

Techie Gotcha - All Hell Breaks Loose, at the End of the Line

FusionReactor, Techie Gotchas

The blog posts halted for a couple of days there, I apologize. The good news, my slackness will pay off… because its been a few days where I have been banging my head on the desk, and although I didn't make time to get the blog posts out, I've learned a few things, and that means I'll share them with you.

First thing on the list, all hell breaks loose, at the end of the line. This is a interesting story, with lots of Christmas Characters. Well, maybe not Christmas Characters, but big CFML community characters all the same. We visited the world of Twitter, Google Groups, and then finally, the light went on, and I felt like a complete idiot, because, it was not the first time, this caught me.

Ok, so one foggy almost Christmas morning, Gavin decided to install Fusion Reactor trial on one of his servers, to see if it was cool enough to put on his Santa list this year. Thanks to valuable information from Charlie  Arehart, the ColdFusion Consulting and Training Fairy informed Gavin that Fusion Reactor didn't exist, its FusionReactor, without a space, like ColdFusion. 

Now gleaming with Christmas-y CFML knowledge, Gavin went to download FusionReactor (so space age is has no space), and realized, that with sad and sorry Centos box was unable to do so, because there are no direct links from (which has no space, but has a dasher, I mean dash). So, quicker than Santa on Christmas Eve, Gavin pops open a browser or two, the first one to open without crashing won, and Gavin clicked the magical link, popping a modal window, that gave me a Trial License key, and downloaded the file to my Sad Old mid 2010 Mac Book Pro… Santa, 16gb ram with 1tb Flash Drive Retina wouldn't go a miss.

Before the Reindeer are finished FTP-ing on the lawn… the file is on the server, and Basher, I mean bash, bash'ed it into an executable, and proceed to follow the very solid installation instructions, found here. 

So I run the puppy, with the -c console setting, and start my sleigh ride to a Merry Christmas… but, before I go anywhere, the console plops out a pile of Christmas Coal, all over my parade. 

$ sh ./ -c
: command not line 2: 
: command not line 7: 
: command not line 8: 
: command not line 11: 
./ line 12: syntax error near unexpected token '{
'/ line 12: `read_db_entry() {


I try without the sh in front, incase I'm not as versed with Linux as I thought, I am probably at the I don't know I don't know stage, honestly.

So I google, this, google that, and look at the first few lines, I tried to do my due diligence, before heading out to Twitter-town… and asking the cool cats.

I grab my pile of Coal, and head to Twitter-town, and throw it out there. Brad Wood 'be online all day long" was quick to answer, and gave me some solid advice, or friendly jab, and summoned the ColdFusion Consulting and Training Fairy, Charlie Arehart into it, and we started to discuss stupid questions versus stupid people. Link at the bottom of this stocking, I mean story.

After both the good fairy (I mean that in a good way Charlie), and the Online Zombie (not sure if that can be taken in a good way Brad) both say that their helpfulness ended with the jabs, and recommend heading to the FusionReactor Google Group.

Then Charlie and Brad jump on the Google Group, to jab me a little more, and recommend the manual install. Of course, I deny that option, because it should install, and if it doesn't, there has to be a reason, and I hate not knowing the reason for stuff… I guess thats the reason why I'm on here doing this, again.

David Stockton, a mean of the Fusion Team, which lost its Reactor in a fatal RainDear incident some time ago I imagine (sleep deprivation makes you imagine a lot of stuff), suggested it might be a corrupt file, or drop the SH at the start.

I think to myself, I did do that, and it didn't work, BUT it did give me another error message. So I google that, and dumb ditty dumb dumb… I found the solution.

./ -c
bash: ./ /bin/sh^M: bad interpreter: No such file or directory

So the mighty Google said "This is a sign of a Dos / Windows line ending apparently"

Actually, Google lead me to Stack Overflow, which as much as everyone hates it, has great SEO, and usually, between the antics and closed questions, you will find some great information.

Here is the Stack Overflow Link:

Long weird story, short of it is.

When you download files to other systems, sometimes, the files are adjusted for the system you are using. CR-LF was used so teletype machines would move the print head and move to the next line. Apparently *nix guys decided it didn't need to be in the document, but in the device drivers, for stuff that actually needed it.

There is an issue with this though… I downloaded it, to Max OSX, which uses LF, FTPed it to Centos which uses LF… so where did all the CR-LFs come from?
That puzzled me for a bit, then I remembered… I have had this issue before. 

When I have downloaded zip files, from windows machines, over ftp, sometimes they get corrupted… why, because the transfer mode wasn't set to Binary… it defaulted to ascii for some reason.

So this is what happened, when I uploaded the file, from my mac… the FTP client saw the file extension, and Auto decided it should be ascii, not binary… so FTP's protocol is very strict on what it should and shouldn't do… and on text files, it basically messes with your file… and then the other side is supposed to de-mess it, depending where you are going. 

A lot of people complain about PHP files being converted to single lines, which messes up their file, because of single line comments commenting out the remainder of the file, not the line. ( I would reference it, but I forgot the source now, I apologize Stack Overflow source). 

The lesson? If you upload something, and it screwed up, check your FTP client, to see if the file type is one of the file types determined to use ascii when the mode is Auto.

Or, if you want to stop it from happening, change it to binary for that session, or if you really just don't want to think about it ever again… set it to BINARY always… but you'll lose some of the benefits of ascii for files that really should have it.

Uploaded the file again, followed the beautiful, but almost irrelevant instructions, since the install is pretty smooth, and intuitive, and now I am a happy geek, watching loads of cool graphs, and checking out some interesting stats.

I'm cleaning up my slow requests, and optimizing some ugly queries ( baby did it, i mean, Santa Baby did it - I would never write queries that bad - lol, I'm getting query coal for Christmas). 

Its fun… I'm really digging the spaceless FusionReactor tool, so Santa, add it to my Christmas List.

Speaking of Queries and optimization… I got into an interesting discussion, argument, mild war about cfqueryparams, so I'm going to look into that more… so keep an eye out for that. Add it to the million things on my todo list.

Thanks again to Charlie, Brad and David, sorry I wasted your time, with something that should have been obvious, and in the end was… hopefully, someone will learn something from my own stupidity.

Thanks for reading, hopefully you learned something, even if you had to wade through all the Christmas Crap / Coal above it. 

Here are the links, for those who care.

Twitter Feed

FusionReactor Google Group!forum/fusionreactor

My FusionReactor Google Group Question!topic/fusionreactor/tcXEEDokSug

Have a good one,


December 2013

Gavin Pickin

cfObjective - Back for Round Two - I got the Email - I am a 2014 Speaker


cfObjective 2013 was my first cfObjective conference, and I absolutely loved it. It was great to get out and meet so many people that I had been following for years via blogs, lately, twitter… and immerse myself in the world of Coldfusion for a few days. It was an action packed week, as I took advantage of the time and location with some great Pre Conference training, ColdBox Bootcamp from Ortus Solutions, and when I left there, I was inspired, and counting down the days to the next trip out to the Radisson Blu, in Bloomington MN. 

After leaving cfObjective, I decided that next year, I might submit a couple of topics, and share in the experience even more. When the call for speakers came around, I thought of 3 topics that I would have loved to have seen before starting our recent Server Migration and Restructure, and submitted them to Trello
This weekend, I got the Email, one of my topics was accepted, and I'm speaking at cfObjective 2014, I am super excited.

The topics I submitted were

Thanks again for everyone who voted for me, all of my topics were well received according to the votes, so that definitely helped my confidence, as this will be the first time speaking at a live conference. I did speak at this years Coldbox Developer Week, a free online weeklong developer conference, and with that going so well, it was easier for me to submit my topics to cfObjective… and it has paid off.

The Content Advisory Board (CAB), using the voting as one dimension of their selection process, selected my topic on 

Setting up your multi-engine environment - Apache, Railo and Coldfusion… play nice kids

Its going to be a lot of fun at cfObjective, there was lots of great content submitted using the Trello board, I can't wait until they announce the list of the other speakers selected in the first wave. 

I guess I know what I'll be doing for Christmas Break now, knocking out some content, preparing for my session. I'll be picking your brains as I work on it, because you, the potential viewer can help me decide what are more important points to focus on... to get the most out of the session. 
No spoilers though :

Thanks again for your support.
Hope to see you all there.



Blog Search