Compound Theory

v2.0

Categories

  1. Transfer
  2. ColdFusion
  3. Java
  4. ColdSpring
  5. Conduit
  6. JavaLoader
  7. ColdDoc
  8. AsyncHTTP
  9. OO Analysis and Design
  10. Flex
  11. Railo
  12. Hibernate
  13. ColdFusion Builder
  14. XML / XSL
  15. XHTML / CSS
  16. Ubuntu
  17. Eclipse
  18. Oracle Database
  19. Git
  20. Usability / UI Design
  21. cf.Objective()
  22. webDU
  23. cf.Objective(ANZ)
  24. Captcha
  25. MAX
  26. Melbourne CFUG
  27. Martial Arts
  28. Random Things

Recent Posts

Projects

Instant Message

Instantly grab my attention...

Recent Comments

08 September 2010 06:50 AM 8 Comments

Trying the CFML Plug-in on IntelliJ

For a long time I’ve been meaning to try out the the IntelliJ CFML plug-in for two reasons. One of which, I’ve always heard really good things about the IntelliJ platform for editing Java, Groovy and Flex, and also because as a Linux based ColdFusion developer, my CFML IDE options are limited.

So I decided I was going to get some work done on JavaLoader, to move it into a 1.0 Final, and I was going to do it all in IntelliJ with the CFML plugin, and use that as a way of seeing how the CFML plugin was going.

Installation
Installation was the biggest hurdle for me, as I ran into a lot of issues getting the plug-in installed and running.

From what I could see, IntelliJ makes no mention that you need to set a JDK_HOME variable in your environment. Except when you first run it and get an error message. Once that was done however, it fired up with no problems at all.

For whatever reason, after running IntelliJ, the CFML plug-in didn’t show up in the plug-in list.  If it had, I’m sure things may have gone a lot smoother for me.

I then browsed to the plugin page, to download the plug-in manually.  Two things went wrong at this point.
  1. As far as I could see, IntelliJ does not describe anywhere how to install a plug-in manually. This is the only documentation I could find on installing a plug-in, and it was via the plug-in manager (see above), so it was not very helpful. It is very simple, you just unzip it and put it in the /plugins folder.
  2. I downloaded the wrong plug-in for my version on IntelliJ. I downloaded 9.03 Ultimate edition, or if you look in the build.txt file that comes with IntelliJ, that’s Build IU-95.429.  Unbeknownst to me it’s that build number that is used on the plug-in download page (See Since build and Until build ) that define what a plug-in is compatible with. Honestly I am confused as to why they don’t just use the IntelliJ product number, but maybe there is a good reason.
(Apparently this has since been fixed, and you can now install from the plug-in manager again)

Appearance
My first thought when opening IntelliJ was “Wow, this is ugly”. I’m used to working in Eclipse, and the Linux build of Eclipse takes the Ubuntu theme that is currently set very nicely. So much so that people at conferences often ask me how I get my Eclipse to look the way it does.  In IntelliJ, the text wasn’t even anti-aliased.

I quickly found an Appearance setting, and switch the theme over to GTK+, which I expect made IntelliJ use Ubuntu native GTK rendering engine, and suddenly IntelliJ matched my Ubuntu theme, and was much more pleasant to look at.  Eclipse still looks more polished, but maybe that’s just because I’m used to it.

Documentation
This is where things fall down, unfortunately rather hard.  The only documentation for the CFML plug-in is a blog that can be found here and a google group .  This project is in desperate need of a website/wiki/Google doc/anything that has some sort of structure. Skipping through blog posts and searching the google group in an attempt to find that one piece of knowledge you need is frustrating, to say the least.

Creating a Project
I go to create a project, and... there is no ColdFusion Project. Uh oh.  Fire off an email to the group and ask “What do I do now?”. (Update, I just got told to create a Java project. Weird, but it works).

In the mean time, I switch tacks, and import an existing Eclipse Project.  IntelliJ asks me for a JDK, but is happy enough when I skip over it, figuring I wouldn’t need one for a CFML project.  That worked quite well, and I’m now on my way to editing ColdFusion.

Editing Files
Code completion for variables and functions inside a CFM and/or CFC is one of the biggest priorities for me, and in the plug-in, I have to say, this feature works very well.

That being said, one thing that is missing for variable completion for me, is completion for variables such as arguments , application , server , CGI , etc, for which there are already bugs for.  That and CFC resolution is missing, which Builder does for things like createObject() etc, (somewhat).

Interestingly enough there is no “New CFM” or “New CFC”, there is only “New File”, which I didn’t find myself missing, except for when creating CFCs.  The new CFC dialogue in builder is great, and if you’ve ever worked with interfaces, having Builder generate the method stubs for you is pretty cool as well.

Overall, the responsiveness is very snappy, and code completion comes up almost instantly, which is very nice. I prefer the function hinting in IntelliJ to Builder, as it give you the hint per parameter as you are inside the method, where as Builder only tends to give you the tooltip when you first write the method.

While I didn’t get to play with it, there is also support for code completion of Java objects , including when being used with JavaLoader , which is not something ColdFusion Builder can do.

Live Templates
This is more of a IntelliJ thing, but Live Templates blow CF Builder/Eclipse Snippets out of the water. Wow.  I love being able to define a $FOO$ variable in my snippet and declaring that $FOO$ variable to complete(). IntelliJ then intelligently provides all the code completion that would normally show up if I hit ctrl+space at that point. I think I’m only just scratching the surface of what is possible with Live Templates, but this feature is fantastic.

Learning Curve
IntelliJ does some things differently to Eclipse, which takes a little while to get used to.  That being said, you can switch the keyboard commands to Eclipse style with a menu change (I did some extra tweaking above and beyond that), so that is nice.

Price

The CFML plug-in only works on the commercial version of Intellij. Licences for personal use carries a price tag that is fairly similar to ColdFusion Builder. Corporate licences cost a fair amount more.  For the functionality provided by the CFML plug-in at this stage , I would recommend that if you are on Mac/Win, stick with Builder. You will get more bang for your buck.  If you are on Linux, and refuse to move OS’s (like I am), IntelliJ is well worth an evaluation, as the price tag is very reasonable, and if you are looking to do Groovy, Flex or Java work, IntelliJ already has that functionality bundled in.

Overall
I have to say, once I got over the initial hurdles of installation, and documentation, and became more comfortable with IntelliJ as a whole, it because a really nice IDE to work in.  There are plenty of rough spots around the edges, but I think with a few more revisions, this plug-in could easily be a decent contender for ColdFusion Builder (especially if it gets a debugger).

If you are looking to purchase an IDE, I would still say stick with ColdFusion Builder for now if you are on Mac/Windows, but if you are on Linux, and don’t want to move, IntelliJ looks like a dark horse to watch in the ColdFusion IDE space.

Learning More
If this has piqued your interest, the best place to really learn about this plug-in is the google group, so sign up there. The blog is also good for information about new releases and what new features are available.

01 August 2010 04:53 AM 0 Comments

cf.Objective(ANZ) Student Ticket Giveaway

Our wonderful sponsor Fasthit has kindly provided us, not only with a ticket to give away to a student living in Australia or New Zealand, but is also paying for flights and accommodation as well for the lucky winner.

The rules are simple:
  1. You must be an Australian or New Zealand Resident
  2. You have to have a valid student identification.
  3. You must be under 25 years of age.
  4. You need to send an email to contest@cfobjective.com.au, with no more than 200 words stating why you would be the best person to win this competition.
...and that is really about it.

The winner with the best entry will be announced on the 1st of September.

If you are a student, make sure you enter for a chance to win! If you aren't a student, but know someone that is, make sure to pass on the message.

For more details, have a look at this news post.
29 July 2010 11:58 AM 0 Comments

cf.Objective(ANZ) 2010 in Full Swing

There has been so much going on with cf.Objective(ANZ), that I haven't even had time to blog about it!

In case you missed the announcements, the pricing is now online, with the early bird price being lower than last years, at $749.00 including GST, valid until the 31st of August.

There are a series of 1 day workshops the day before the conference as well, covering ColdFusion Performance tuning, Flex 4 and ColdFusion, and Arduino hardware with ColdFusion.  Charlie Arehart, Kai Koenig, and Justin McLean are running these workshops respectively, and you couldn't ask for better instructors.

While each track of the 2 day conference has yet to be finalised, almost all of the sessions that will be available are now online , and we have some fantastic content again this year, with some speakers that I am very excited about.  The usual slew of amazing ANZ dignitaries will be joining us, also with international speakers such as Gert Franz, Mark Drew, Mark Blair, Mike Brunt and Tim Buntel (Or maybe 'semi-international' would be a better fit? Mark Blair moved to San Francisco and then came back, Tim Buntel now lives in Sydney... ;o) ).

I'm really happy with the way this conference is coming together this year, and providing some really unique ColdFusion content for the ANZ region.  We've got some great training, some great speakers, some great sessions, it's looking like it's going to be a fantastic time all around.
13 July 2010 01:15 PM 0 Comments

Adobe MAX Pre-Conference - Getting Started with ColdFusion 9 ORM

Bob Silverberg and I are back at it again, with a one day pre-conference lab at Adobe MAX this year covering an introduction to Object Relational Mapping in ColdFusion 9.

As the description states:
Learn about one of the most compelling new features in Adobe ColdFusion 9 from two seasoned ColdFusion veterans. This release includes the integration of Hibernate, an enterprise-class, Java based ORM. Join us to hear how to get started using ColdFusion 9 ORM features in your next project. Through interactive learning and hands-on labs, we'll start with the basics and work together to add features to an application that takes advantage of the ORM. Then we'll discuss best practices and potential pitfalls, making this an ideal combination of introductory material and tips and tricks.
If you are interested in getting your feet wet with ColdFusion 9 ORM, you can get more information on the MAX pre-conference page .

Hope to see you there!
25 June 2010 01:06 PM 0 Comments

Dzone RefCard - Leveraging ColdFusion 9 Exposed Services from Java

In ColdFusion 9, several Web Services come pre-built with the product, allowing greater interoperability between different technologies and ColdFusion.

The other day saw the release of my Dzone RefCard outlining how you could take advantage of these Web Services from Java, and use ColdFusion's

If you are doing Java development, and are looking to integrate some of ColdFusion's capabilities into your application, you can download the RefCard from here .  It will step you through setting up the Services, generating the required Java code to run the Web Services, and also provides examples of usage to help you get started.

You can also read more about ColdFusion Web Services here .
18 May 2010 08:30 PM 1 Comment

Presenting ColdSpring 2.0 on CFMeetup.com

On 6pm US ET, Wednesday May 19 I will be presenting Dependency Injection Redefined - ColdSpring 2.0 to the CFMeetup Crowd.

For those of us in more southern parts of the world, that is 8:00am, the 20th of May, Australia.

This is the same talk I recently gave at cf.Objective() and WebDU .

Synopsis:
ColdSpring 2.0, codename Narwhal, is a complete rewrite of ColdSpring aiming is to provide a far more extensible architecture and many more features above and beyond what is currently provided with ColdSpring to date. These new features will give developers the capabilities to build and manipulate this Inversion of Control framework in fascinating and very powerful ways, thus saving them even more time when managing their dependencies and utilising functionality such as Aspect Oriented Programming.

In this presentation we will look at the new features of ColdSpring 2.0, both complete and envisioned, including functionality such as extensible schema support, events for bean life-cycles, enhanced AOP support, annotation support, and much more.

More details and rsvp can be found here .

Look forward to seeing you there!
13 May 2010 12:48 PM 8 Comments

Some arguments against "Linux users don't pay for software"

As many people probably know, I'm a huge proponent of Linux operating systems, most specifically Ubuntu, not only because its open source, and free, but mostly because I honestly believe it's the best operating system I've ever come across.

For obvious reasons, I spend a bit of time trying to convince a variety of people that Adobe should take a serious look at bringing Adobe products to Linux, the most notable being ColdFusion Builder.

One argument (and there are a few) against this, I hear over and over is this idea that "Linux Users don't pay for software".

Up until now, the only evidence to the contrary has been anecdotal - i.e. I personally have paid for CrossOver Office, Vmware Workstation, CrashPlan, World of Goo and Caster.  That being said, anecdotal evidence doesn't tend to be very convincing.

Recently, however, the "Humble Indie Bundle", was put up for sale, in which 5 cross platform games (Win, Mac, Linux) were sold together as a group. The real time data for sales and the operating system splits has been shared, providing us with a wonderful aggregate data about the difference between Win, Mac and Linux users, how much they are willing to pay for software, and if they are willing to pay at all.

The fun part of this experiment was that the customer could choose how much they paid for the bundle, which could be as little, or as much as people liked.  It also could be split any way between the developers, charity, or charity and the developers.

Some interesting stats to note (Taken from the real time stats as of this moment):

1) Current intake across Win, Mac, and Linux - $1,173,536 (which is just cool in and of itself)
2) Windows has the largest market share (no surprise there), with 86670 purchases.
3) Linux is the smallest number of purchases, with 21873 purchases, but that is only 8153 purchases, less than the Mac platform - 30026
4) The big news here is that Linux people paid more on average than either Mac, or Windows users.
Win: $8.06,Mac: $10.23, Linux: $14.53
So much so, that the total income from Linux users, outstrips that of Mac, even though Mac had more purchases (Mac: $307172.75, Linux: $317846.61)

I don't think you can ask for a better experiment than this.  If Linux users wouldn't pay for software, then they would be at the bottom of the list in terms of amount paid. Instead that's where Windows users sit.

Details of the Humble Indie Bundle can be seen here:
http://www.wolfire.com/humble

Their realtime JSON feed can be found here as well:
http://www.wolfire.com/humble/stats

(And they are some cool games as well)

On another note, Valve have announced that they are releasing their Steam Source Code client to Linux. This is a huge boon to the Linux community, and while there are no dates yet, obviously Valve thinks there are people in the Linux community who will pay for software, otherwise they wouldn't be putting in the time and effort.

Therefore, you can quite clearly see that Linux users will, and do pay for software, and in fact put a higher cost on software than any other OS's user base.

I claim this myth well and truly busted.
03 May 2010 05:33 PM 2 Comments

ColdSpring Framework on Twitter

Just a note to let everyone know I set up a twitter account for ColdSpring.

It has automated updates for Git commits, and ticket events. It should be a good resource for helping people keep up to date with the going-on's of ColdSpring, and especially ColdSpring 2.0.

Follow coldspring_fw on Twitter!

29 April 2010 11:59 AM 0 Comments

ColdSpring 2.0 - Now On SourceForge

Up until recently, the goings-on of what has been happening in ColdSpring 2.0 has been fairly limited to my twitter account.

At cf.Objective(), I did a presentation entitled Dependency Injection Redefined - ColdSpring 2.0 Narwhal where I outlined what work had been done on ColdSpring 2.0, what was planned for the future, and where you could go for more information. (I'll also be doing this presentation at WebDU in a about a weeks as well).

The first thing to note, is that the code name for this project is Narwhal. Why Narwhal? Basically because they are awesome. They roam the ocean with a huge spike attached to their head, which can be used to impale, seals, penguins, and apparently also koalas. See - awesome. (Who really has reasons for code names?)

The next most interesting thing to note, is that much of ColdSpring's infrastructure is now hosted on Sourceforge, as it provides a large feature set for us to leverage. Here you can find the project page, which gives you access to the Git repository that contains the code for ColdSpring 2.0.  Sourceforge also provides hosting for the Trac install that is being used to host our documentation and tickets and milestones.  We are currently investigating options for integration with the current ColdSpring website.

I'm not going to go into new features in Narwhal, of which there are more than a few (I have to have some incentive for people to come to my my WebDu Talk!), but documentation has started on the Wiki, and will be expanding quickly in the future (If anyone wants to help with that, the more the merrier!).

You may also note that much of the documentation is also being generated automatically, in an attempt to alleviate some of the burden of authoring.  Now that there are XMLschemas being used, HTML documentation is being generated from them, and ColdDoc is also being used to generate API documentation for the underlying architecture.

It's still very early days for ColdSpring 2.0, but a Alpha1 does loom on the horizon. That being said, the Git repository is public, so feel free to pull it down, have a look at what is happening in the Unit Tests, what documentation is available, and feel free to discuss it on the mailing lists.  Just beware - this is still pre-Alpha, so the sand may shift under your feet as new code gets produced, bugs get quashed and new features get developed.  You have been warned!

More details coming soon!

Back from cf.Objective() 2010

I'm back home again from what I would like to say was, one of the best cf.Objective()'s I have ever been to, including the fact that I was incredibly ill for the last day of the conference. I only managed to catch two sessions in the afternoon, and otherwise was holed up in my hotel room either fast asleep, or feeling particularly sorry for myself.

There are many things I would like to prescribe the incredibly high quality of the conference to, but the the high calibre of the session presentations really stands out at the main contributor.  I believe that when the session quality of a conference is so high, the attendees are excited and motivated by new ideas, which directly translates into fantastic and thought inspiring hallway conversations, and everything continues to flow from there.

To make a few particular references to presentations I particularly enjoyed -

Easy and Flexible Validations for Objects - Bob Silverberg
I had not previously taken the time to look at Bob's ValidateThis framework, but let me just say this: It is slick!  I was very impressed by what was possible with very little configuration, and the the flexibility that was available. My hat is off to Bob for his work with this validation framework.

Continuous Integration with MXUnit, Ant and Hudson - Marc Esher
Marc is always a very entertaining presenter, and this presentation was no exception.  I've used Hudson with MXUnit before, but it was still fantastic to see Marc explain this technology in a very clear and easy to understand manner.  He also gets points in my book for using the Hudson Chuck Norris plugin.

Polyglot Programming - Barney Boisvert
If anyone has read Barney's blog, they should already know that he's a super smart fellow.  This presentation only solidified this fact, in which Barney dug deep into the very compelling reasons a developer should potentially look into developing with multiple languages at a time (something as web developers we are doing already).  Barney covered some really interesting points about language design, the intent of programming code and qualifying return on investment in regards to polyglot programming. All great stuff!

Running ColdFusion on the Amazon EC2 Cloud - Chris Peterson
This was a session I really wanted to attend, but unfortunately I slept through due to illness.  I wanted to make note of it, as I was told that Chris had a completely filled room, and I've been told it was a really interesting presentation all around.

Building Advanced Workflows with ColdSpring - Dan Skaggs
I don't believe I have had the opportunity to see Dan speak before this, but this presentation was an eye opener!  I came to this presentation with my 'ColdSpring Lead Developer' hat on to see what interesting things people were doing with ColdSpring, and came away with a new found respect for the framework itself, and the ingenuity that Dan was displaying in his use of it.  Dan walked us through how his company was using ColdSpring to dynamically configure application workflow and processing - which enables it to be both incredibly flexible in its implementation and amazingly easy to maintain. 


Bob Silverberg and I also did a two day Hands on ColdFusion 9 ORM Training before the conference.  Thanks to all our students who attended - we had a great time teaching the program, and we hope you guys got a lot out of it.  If anyone else is ever interested in taking the training course, please provide your contact details on the website so we can contact you at a later date.

All in all, a great conference all around.  See you all again next year!
07 April 2010 09:58 AM 1 Comment

ColdFusion ORM Training + Java Persistance with Hibernate = Awesome!

Like Tyra Banks giving away Vaseline to her entire audience, the attendees of Bob Silverberg's and I's ColdFusion 9 ORM Training, that we are running at cf.Objective(), ever student who attends our training will also get a copy of:

Java Persistence with Hibernate!

You get a book! You get a book! You get a book! Yoouuuuuu get a Booooooooook!!!!

While this is a Java book, and hey, we all write ColdFusion, it is one of the books to read on utilising Hibernate within your applications. Reading this book will give you a huge insight into what ColdFusion is doing under the covers, which will help out a great deal when building applications with ColdFusion 9.

So not only do you get some great training from Bob and I, you also get a fantastic reference to take home with you as well!

If that doesn't push you over the edge to come join us, I don't know what will.

(Ordering now does not provide you with a free set of steak knives, but it will make Bob and I very happy)
23 March 2010 10:12 AM 4 Comments

No more Linux scripts for ColdFusion Builder

A few people have asked me about the ColdFusion Builder scripts for Linux for the new 1.0.

I'm sorry to say that I won't be doing a script for ColdFusion Builder on Linux for the 1.0 release.

I tried this morning to run my usual scripts to get a plugin install out of ColdFusion builder, which ran fine, but after installing and attempting to run it, I was met with a dreaded:

!ENTRY com.adobe.ide.editor.cfml 4 0 2010-03-23 09:39:50.110
!MESSAGE

Whenever I opened a CFML file (which doesn't tell me much about what is going on where).

There is obviously something native built into ColdFusion Builder 1.0, that wasn't present in Beta 3 (I can see some .dll's etc), which is causing this error to occur.  Adobe have also done the right thing, and removed all the debugging so that would be hackers have a hard time working out what is going on where.

If you want to get involved in evangelising ColdFusion Builder on Linux, there are some things you can do:

  1. Vote for the bug!
  2. Vote for the Flash Builder bug too (if they do one, they will have to do the other!)
  3. Bug your evangelists! (But do it in a nice way)  Conference season is coming up, so have a chat with them when you see them around, and let them know that you would buy a copy for Linux.
  4. Run it in VMWare / VirtualBox
  5. Change your OS of choice (ECH!)

At the end of the day, I'm only upset about there being no Linux version, because I think ColdFusion Builder is a great product, and I want it to have as much exposure as it can.  We need to convince Adobe that the Linux market is a viable one, and will have a good return on investment.

If I hear of any changes in the Linux landscape for ColdFusion Builder, I'll be sure to let you know.

cf.Objective() ColdFusion 9 ORM Training

I believe it is time for some shameless self promotion!

If you were looking for more information on the ColdFusion 9 Object Relational Mapping Training that the venerable Bob Silverberg and I are putting on at cf.Objective() next April, we have just fleshed out the content section of our site to include a detailed outline of the topics that we will be covering during the training program.

You'll know Bob from his blogging at http://www.silverwareconsulting.com/, on a variety of all too clever stuff, including CF9 ORM, Git, Unit Testing, and ValidateThis - his own open source validation framework.  He's also an all-around nice guy

You'll see that we cover a variety of topics with ColdFusion 9 ORM that will allow you to hit the ground running once you have completed our training, and it will be taught in a clear, step by step manner that will leave you wondering why you ever thought the term "Object Relational Mapper" sounded so scary and complicated.

So if you are keen on expanding your skill-set with ColdFusion 9, and specifically with its integrated ORM, we think this is the course for you, and we hope to see you at cf.Objective()!

cf.Objective() Preconference Classes
02 March 2010 12:42 PM 1 Comment

ColdDoc 1.0 Alpha Released

When ColdDoc was first born, the original idea was to just output a port of Javadoc.  Looking into it further, I realised that the mechanics where there to generate any sort of documentation, not just a static HTML version of the API.

To that effect, ColdDoc has been refactored so that it is possible to generate documentation based on an arbitrary Template Strategy.  ColdDoc now ships with both a strategy that generates the port of JavaDoc and a strategy that generates UML via the UML2 Tools plugin in Eclipse, and plans are in the works to generate a PDF document strategy as well.

I won't take you through implementation details (there is new documentation for that), but you can still generate the static HTML API documentation based on JavaDoc, for which you can see an example here, but now it is done through the HTMLAPIStrategy. This also includes support for new ColdDoc based annotations, in which, for example, you can specify generic types for return/arguments types like array, struct etc, so you can finally answer that question in your documentation of "Yes, but what does that array contain?".

When working on the ColdSpring 2.0 rewrite (wow, that is long overdue for a blog post), I also really needed a way to generate UML diagrams from the code I was writing, as a basic attempt to be able to roundtrip from UML->CFC and then back again.  Also included within ColdDoc is a strategy to generate the XML that the Eclipse UML2 Tools Plugin uses to create UML diagrams from.  You can see a screenshot of a Class Diagram here that has been created with this combination of tools.

This is very useful, as it becomes very useful for collaboration and software design sessions, even when you have started with UML diagrams, as software designs can shift during implementation phases, and diagrams and documentation often fall by the wayside during these rapid change cycles.

If you are interested in more, or possibly developing your own documentation generation strategies, download a copy of ColdDoc, read the new documentation, and join the conversation on the google group.

Happy automation of documentation!
28 January 2010 08:32 AM 15 Comments

ColdFusion 9 ORM and Transactions - It Does Not Mean What You Think it Means.

In one of my favourite lines from the Princess Bride -

[Vizzini has just cut the rope The Dread Pirate Roberts is climbing up]
Vizzini: HE DIDN'T FALL? INCONCEIVABLE.
Inigo Montoya: You keep using that word. I do not think it means what you think it means.


..and when using Transaction support with ColdFusion 9 ORM and Hibernate Sessions...It did not do what I thought it did. It did something else.

To give some back story: As we have discussed previously, a Hibernate Session is meant to flush at the end of a Hibernate marked Transaction.

So if we are talking to Hibernate natively (for example set up with JavaLoader), and had the following code:
mySession = sessionFactory.openSession();

foo = mySession.get("Foo", 1);
foo.setBar("fooBar");

trans = mySession.beginTransaction();

mySession.save(foo);

trans.commit();

mySession.close();
Which then translates to the following:
  1. Start a Hibernate Session
  2. Retrieve Entity 'Foo', with a key of 1, and assign it to a variable foo
  3. set the property 'Bar' on foo
  4. Start a Hibernate Transaction, which is tied to the Hibernate Session
  5. Tell the Hibernate Session to save() our Entity foo
  6. Commit our Hibernate Transaction, which will flush the Hibernate Session
  7. Close the Hibernate Session

If we attempt to do the same thing in ColdFusion, it may look something like this:

foo = EntityLoad("Foo", 1, true);
foo.setBar("fooBar");

transation {
    EntitySave(foo);
}

Which you would think would work exactly the same as above. Except or one small thing - It Doesn't.

If you read the ColdFusion Documentation on ORM Transactions, it states:

When <cftransaction> begins, any existing ORM session is flushed and closed, and a new ORM session is created. The <cftransaction> can be committed or rolled back using appropriate ColdFusion tags in <cftransaction>. When the transaction ends and has not been committed or rolled back explicitly, it is automatically committed and the ORM session is closed. If there is any error inside the transaction, without any exception handling, the transaction is rolled back.


This means that the above ColdFusion code, will actually perform like so:
  1. Start a Hibernate Session with the ColdFusion Request
  2. Retrieve Entity 'Foo', with a key of 1, and assign it to a variable foo
  3. set the property 'Bar' on foo
  4. Hit the start of the Transaction, flush the current Hibernate Session, close it, and then start another one.  At this point, foo has been persisted to the database, and is now detached (and remember detached is generally bad)
  5. Call EntitySave() on the now detached object foo
  6. Commit the Hibernate Transaction, and flush the Hibernate Session
  7. Flush the Hibernate Session, when the ColdFusion Request Ends

Or if you want to look at it another way, it would be the equivalent of doing the following native communication with Hibernate:
mySession = sessionFactory.openSession();

foo = mySession.get("Foo", 1);
foo.setBar("fooBar");

//foo actually gets persisted to the DB at this point
mySession.flush();
mySession.close();
mySession = sessionFactory.openSession();

trans = mySession.beginTransaction();

//foo is now detached
mySession.save(foo);

trans.commit();

mySession.flush();
mySession.close();

The big question at this point, is of course - Well, why does ColdFusion do it this way then?

There is actually a very good reason, although that reason (imho) is based on a few assumptions. 

The first assumption, is that you are going to write your ORM interactions inside your transaction block, like so:

transation {
    foo = EntityLoad("Foo", 1, true);
    foo.setBar("fooBar");

    EntitySave(foo);
}

The second  assumption is that, as a developer you will leave the ORM setting flushatrequestend set to its default of true, and therefore a split between the Hibernate Sessions is required.

For example, if we had the following code:

transation {
    foo = EntityLoad("Foo", 1, true);
    foo.setBar("fooBar");

    myMethodHereThrowsAnException();

    EntitySave(foo);
}

If we didn't have separate Hibernate Sessions, or at least clearing of the Session after Hibernate Transaction rollback, , the following would occur:
  1. Start a Hibernate Session with the ColdFusion Request
  2. Start the Hibernate Transaction
  3. Retrieve Entity 'Foo', with a key of 1, and assign it to a variable foo
  4. set the property 'Bar' on foo
  5. Throw an exception, which causes the Transaction to rollback
  6. The request ends, the Hibernate Session is flushed, and foo gets saved back to the database, since it is still available in the Hibernate Session.
Which is very much against the nature of a rolled-back transaction.

Instead, what actually happens is:
  1. Start a Hibernate Session with the ColdFusion Request
  2. Start the Hibernate Transaction, which closed the above Session, and starts a new one
  3. Retrieve Entity 'Foo', with a key of 1, and assign it to a variable foo
  4. set the property 'Bar' on foo
  5. Throw an exception, which causes the Transaction to rollback
  6. The Transaction end closes the current Hibernate Session, and creates a new one
  7. The request ends, the Hibernate Session is flushed, and nothing gets saved to the database, as there is nothing in the current Hibernate Session
Given the above assumptions, this is much better, since we want to have the Transaction actually rollback.

That all being said, what happens to those of us that want to work, or have an architecture that inclined towards our previous example:

foo = EntityLoad("Foo", 1, true);
foo.setBar("fooBar");

transation {
    EntitySave(foo);
}

I.e. We want to have our Transaction interact with the current Hibernate Transaction, and not flush at the end of the ColdFusion request, which, I find to be the solution I prefer for when building applications with Hibernate.

What can we do then?

There are two things that need to be done, if we want to do this kinda of approach. The first is, to set the ORM setting flushatrequestend to false.  This means that the Hibernate session won't flush at the end of the ColdFusion request, and we have complete control over when it does flush.

To make sure the Transaction interacts with the current request, we can't use <cftransaction> or a transaction {} block, we have to natively interact with the Hibernate Session directly, which is quite straight forward.

foo = EntityLoad("Foo", 1, true);
foo.setBar("fooBar");

trans = getORMSession().beginTransaction();

try
{
    EntitySave(foo);

    trans.commit();
}
catch(Any exc)
{
    trans.rollback();
    rethrow;
}

We have to do the extra work to manage the commit and/or rollback of the Transaction manually, but this something that could be implemented with a UDF or using Aspect Oriented Programming for reuse.

Now I can use Transactions to demarcate when I want the Hibernate Session to be flushed, and I'm not tied to wrapping my entire Entity operations inside a <cftransaction> block.

This is something I really like about how Adobe implemented the ORM integration.  If I don't particularly like the way an individual aspect has been implemented, I have direct access to the underlying engine, and can therefore interact with it in whatever way that suits the way I develop and thearchitecture of my application.

Now Transactions mean what I think they mean.
 
UPDATE 28/10/01:
I just wanted to add a small conclusion to this post, that sums what I am trying to get across simply.
 
Basically what this all boils down to is: If you are using <cftransaction> or a transaction{} block, make sure you are wrapping them around the entire operation, not just the EntitySave() portion at the end, as otherwise bad things can happen.

If you want to just wrap transactions around the EntitySave() part of your code, you will need to use native Hibernate Transactions like I have done above.
 
Hopefully that boils the large post above into a nice tasty nugget of knowledge that is far easier to swallow.

Presenting and Teaching at cf.Objective() 2010

I'm a little behind the times on this blog post - but I am presenting and also teaching a course at cf.Objective() this year.

I will be presenting 2 sessions at the conference:

Dependency Injection Redefined - ColdSpring 2.0: Narwhal

ColdSpring 2.0, codenamed 'Narwhal', is a project that has been going on a little 'behind the scenes', except for the occasional tweet from either myself, or Chris Scott.

In this presentation, we'll look at some of the motivations behind the complete rewrite of ColdSpring for the 2.0 version, and some of the new features that will be available that should make dependency injection easier, and way more flexible than ever before.

I've had in my to-do list a reminder to write a long blog post on what is going on with Narwhal, which I should write at some point soon, so you have a good idea what to look out for.  That being said, Narwhal is taking shape nicely, and I think is going to be a very powerful addition to the ColdFusion framework landscape.

Advanced Java & ColdFusion Integration with JavaLoader 1.0

This talk will focus on the new features of JavaLoader 1.0, and how you can use them to integrate Java with your ColdFusion platform in some new and exciting ways.  If you are interested in JavaLoader 1.0, check out this previous blog post, it gives you a good run down on the new features it brings to the table.

We will also be investigating some of more common 'gotchas' with Java and ColdFusion integration, especially around ClassLoader issues, which should be useful for all involved.


Bob Silverberg and I are also going to be a teaching a 2 day training course, just before cf.Objective():

Hands-On ColdFusion ORM Training

This will be as very hands on session, where Bob and I will be going through building an application using ColdFuson 9's Object Relational Mapper from beginning to end.  This will include many best practices, discussions as well as theory about how the underlying Hibernate engine works with ColdFusion.  No ORM/Hibernate experience necessary.

More detail on the course can be found on our website, and also on the preconference page, where you can also check out all the other fantastic training content.

Don't forget that the early bird pricing for both conference tickets, and training finishes on the 29th of January, which is coming up soon!

cf.Objective() is looking to be a great conference. Hope to see you there!
20 January 2010 11:48 AM 1 Comment

JavaLoader 1.0 Beta 2 Released

This release of JavaLoader 1.0 includes the following fixes and enhancements:
If you aren't aware of the new functionality in JavaLoader 1.0, you can have a look at my previous blog post , the documentation and/or the presentation I did at MAX for more information.

Credit and thanks to Fred Roeber for his contributions to the NetworkClassLoader in JavaLoader.

If you are interested in hearing more about ColdFusion and Java integration please come to cf.Objective(), where I will be presenting on Advanced Java & ColdFusion with JavaLoader 1.0.

In the mean time, download JavaLoader, and please report any bugs that you find.
18 December 2009 09:56 AM 6 Comments

ColdFusion Builder Beta 3 on Linux

ColdFusion Builder 3 is up on Labs , and available for download, so it's now time to update my scripts for getting it up and running on Linux.

The procedure is as following:
  1. Download the intermediate build *for MAC* (very important! The Windows Adobe Licensing will prevent you from using the Windows version any more, as it uses .dll files, and those don’t work on Linux, but the Mac version works on Linux!)
  2. Download coldfusion_builder_b3.zip .
  3. Unzip coldfusion_builder_b3.zip into a directory
  4. Unzip coldfusionbuilder_b3_install_mac_121709.zip
  5. Unzip /cfbuilder_install.app/Contents/Resources/cfbuilder_install.app/Contents/Resources/Java/Disk1/InstData/Resource1.zip (may be easier to do that into another folder)
  6. From the unzipping of Resource1.zip grab /Z_/dist/_macos_87b1877cbdff_zg_ia_sf.jar and put it in the same folder as where you unzipped coldfusion_builder_b3.zip
  7. Run ’./Rip.py’ from the folder you unzipped it to.
  8. You should now have a ’plugins’ and ’features’ folder with just the bits you need to install into Eclipse.
  9. Enjoy CF Builder in Linux :D

Enjoy!

My Interview on Dzone - ColdFusion and Java Integration

The interview I did with Dzone at the Adobe MAX conference is now online!

In the interview we talk about a variety of topics, mainly centred about how and why to integrate ColdFusion and Java together, but also touching on things like Object Relational Mappers, including ColdFusion 9's integration with Hibernate.

Hope you like it, and please give it a nice 'up' on Dzone.

Code Samples for Rapid OO Development with ColdFusion Frameworks

You can download the full code samples I used in my Rapid OO talk that I gave most recently at cf.Objective(ANZ) , and previously at cf.Objective() .

Before people ask, I don't tend to post slides, as they are generally only pictures, and tend to have no context without me talking next to them.

That being said, I'll have a chat with the CFMeetup crew, and see if they would like me to give the presentation there, so there is a recording for posterities sake, and for those who couldn't make those conferences.

One Week Until cf.Objective(ANZ)

I can't believe it was well over a year ago I was sitting around with the steering committee of cf.Objective() , and the conversation turned to 'What do you think of the idea of doing this conference in Australia?', it feels just like yesterday.

Now we're only one week away from cf.Objective(ANZ)!!!

If you haven't already registered , there are still spots available, so make sure you grab them quick! You don't want to miss out on hanging out with super-top-programmers like Justin McLean , Andrew Muller , Dan Wilson ... oh, and did we mention Ben Forta and Terry Ryan are coming? (like anyone missed that!).

See you all in a week!
26 October 2009 11:11 AM 0 Comments

JavaLoader 1.0 Beta Released

JavaLoader 1.0 is moving from Alpha to Beta with only a few small bug fixes and enhancements.

If you are not familiar with JavaLoader 1.0's functionality, you can have a look at my previous blog post , the documentation and/or the presentation I did at MAX for more information.

The was a logic bug in the way that dynamic compilation was occuring across multiple source directories that has now been resolved, and should also ensure that compilation is much faster than it was in the Alpha.

The other enhancement was to allow for relative paths in the Spring integration.  To explain, in the Alpha, you would often end up having to input your beans similar to this:

<coldfusion:cfc id="message"
        script-source="file://${root.path}/model/Message.cfc"
        script-interfaces="com.IMessage"
        />


Which can be a bit of a pain, as injecting a dynamic value for ${root.path} is not as easy in Spring as it is in ColdSpring.

Now, by default, 'script-source' attributes are relative to the calling page, so you can do your bean definitions like this:

<coldfusion:cfc id="message"
        script-source="file:///model/Message.cfc"
        script-interfaces="com.IMessage"
        />


and the path will be worked out for /model/Message.cfc relative to your application path.

Oh, and don't forget - if you are into integrating Java and ColdFusion development, make sure you sign up for the Google Group !

JavaLoader 1.0 Beta can be downloaded here .

22 October 2009 02:48 PM 5 Comments

MAX Presentation Recording: ColdFusion for Java Developers

I had the wonderful opportunity to present and attend MAX for the first time ever this year, and I can honestly say, it was a fantastic time all around.

MAX is completely unlike any other conference I've ever attended, both in terms of its sheer size, and also in terms of the wide gamut of Adobe community members that are in attendance.  I managed to meet a variety of people that I would never have talk to in my regular travels both in term of physical locations and also technological disciplines.

I also had the pleasure of presenting the last session on the last day, so I was very happy when I had a fairly reasonable turn out for my ColdFusion for Java Developers presentation.  The presentation took the perspective that the attendees were/are already doing Java development, but want to port those tools and codebases that they are already using to a ColdFusion environment, so they could take advantage of ColdFusion services and language.  From there we look at the variety of techniques that you can use to enable ColdFusion->Java communication, as well as Java->ColdFusion.  This includes a aan overview of a lot of the JavaLoader 1.0 feature set in the process.

If you are one of these people, and/or you are doing development in both ColdFusion and Java, you can watch the recording of my presentation on Adobe TV .  You may want to skip the first 5 minutes, as for some reason the recording has me doing all my set-up before I start speaking.
21 October 2009 05:54 PM 8 Comments

ColdFusion Builder Beta 2 on Linux

For those of you who have been running ColdFusion Builder on Linux, you may have noticed that the installer structure has changed since the last public beta, which means that my previous instructions will no longer work.

This means we have to jump through some different hoops to get things to work this time around.

The steps are now the following:

As new versions of ColdFusion Builder become public, I will attempt to keep this script up to date.

 

07 October 2009 02:52 AM 0 Comments

Ben Forta is Coming to cf.Objective(ANZ)!

In case you missed the tweets, I am very pleased to announce that Ben Forta will be joining us in Melbourne, Australia for cf.Objective(ANZ) !

Ben will be joining ColdFusion Evangelist Terry Ryan to represent Adobe ColdFusion here in Australia, and the two of them will be around to chat to all attendees about ColdFusion and the Adobe ecosystem.

Don't forget that the early bird price comes to a close on the 12th of October, which is fast approaching, so please make sure you get yourself registered so you can take advantage of it.

See you all when I get back from MAX.
07 September 2009 09:58 AM 2 Comments

Talking Java and ColdFusion Integration on CFPanel this week!

At a very ANZ friendly time of Wednesday, 10am Melbourne time, I'm going to be joining super-smart guys Brian Kotek and Barney Boisvert on CFPanel to talk about Java Integration with ColdFusion in the CFPanel Connect Room.

This is obviously a topic that is quite near and dear to my heart, but it is also one that I think often doesn't get its 'surface scratched' (so to speak).  In my experience I often see the information presented is more on the 'how to get set up' side, and less on the deeper details on what can actually be done.

I'm really looking forward to getting a chance to share experience with the other CFPanel members, and really get deeper into some interesting Java and ColdFusion integration, in regards to how people are using it, what benefits they are reaping, and also what problems they have encountered.

For more details, and and all the other time zones, check out the CFPanel post.

Hope to see you in the Connect room!
07 September 2009 09:01 AM 0 Comments

Registration Opens for cf.Objective(ANZ)

It's been a bit of a bumpy road getting here, but registration for cf.Objective(ANZ), being held in Melbourne Australia on the 12th and 13th of November is finally open!

The program is full with a stack of really interesting presentations, ranging from JVM Tuning and Optimisation, to ModelGlue 3: Gesture, all the way to Connecting hardware up to ColdFusion!

We have an international cast of speakers, including notable luminaries such as Dan Wilson and Mike Brunt, as well as many talented speakers from the Australia and New Zealand Regions, including Geoff Bowers, Robin Hilliard, Kai Koenig and many, many more.

Helping organising a conference over international borders has been quite the learning experience, however I am very proud to be part of the steering committee that is bringing cf.Objective(ANZ) to the Pacific Region.

If you are looking to learn about enterprise development, and hang out and talk to a slew of like minded developers for two days, register for the conference, and come on down!  It's going to be a great time!
31 August 2009 12:43 PM 3 Comments

JavaLoader 1.0 Alpha is Released!

JavaLoader 1.0 is a project I've been talking about off and on for the past 6 months or so, and I'm very happy to announce that a release version is now complete.

There are several key new features to JavaLoader 1.0,

Dynamic Compilation

Now if you are working with JavaLoader, you don't have to bundle your Java code into a jar to load.  You can simply specify to JavaLoader which directories are your source directories, and JavaLoader will compile and load them on the fly for you!  JavaLoader will also check to see if your source code has changed, and re-compile it as necessary! 

For example, if I wanted to compile and load a HelloWorld.java (that has a simple 'Hello World' method) in my ./src directory, I could do:

javaloader = createObject("component", "javaloader.JavaLoader").init(sourceDirectories=[expandPath('./src')]);

And then create my HelloWord object as per normal:

<cfset helloWorld = javaloader.create("HelloWorld").init()>
<cfoutput>#helloWorld.hello()#</cfoutput>

No more ANT tasks, no more export to .jars, JavaLoader handles the compilation and deployment of your Java code for you.

ColdFusion Component Dynamic Proxy

For those of you who are not aware of what a Dynamic Proxy in Java is, it is essentially an Object that can mimic an object that implements a given set of Interfaces.  The method invocations against that object are intercepted, and you can essentially do whatever you like with them.

In JavaLoader 1.0, I've written a Dynamic Proxy that you are able to wrap around a CFC, and thereby make Java Objects think they are interacting with a native Java object, but are in fact, talking to your CFC.  When a Java Object calls a method on the Dynamic Proxy, it is passed through and invoke directly on the CFC transparent to your Java layer.

For example, the java.lang.Thread Java object can take an instance of the interface java.lang.Runnable in its constructor argument.  Using JavaLoader's Dynamic Proxy, we can pass it what it thinks is an instance of the Runnable Interface, but is in actuality a ColdFusion Component like so:

//give us access to the CFCDynamicProxy
CFCDynamicProxy = javaloaderloader.create("com.compoundtheory.coldfusion.cfc.CFCDynamicProxy");

//create my Runner CFC
myRunner = createObject("component", "MyRunner").init();

//wrap it in a Dynamic Proxy, that implements Runnable
runnerProxy = CFCDynamicProxy.createInstance(myRunner, ["java.lang.Runnable"]);

//pass it to the Thread and call run()
thread = createObject("java", "java.lang.Thread").init(runnerProxy);
thread.run();

...and suddenly we have true seamless communication from Java to ColdFusion components.

This is actually something I wish I had written three years ago.  It would have radically altered how I would have written a lot of software.

Spring Integration

A natural progression from the Dynamic Proxy, was to implement a Custom Schema in Spring, so that you could instantiate and dependency inject your ColdFusion components with your Java Objects inside Spring itself.

Initialising Spring with JavaLoader is covered in the documentation, but to give you a quick taste, once we have Spring running, we can include a CFC in our spring.xml with:

<coldfusion:cfc id="message"
        script-source="file://home/www/model/Message.cfc"
        script-interfaces="com.IMessage"
        />


Where script-source is the absolute path to the CFC you want to instantiate, and script-interfaces are the Java interfaces that your dynamic proxy will implement, and your CFC has mirrored inside it.

This Component then gets treated like a normal Spring bean, so it can be autowired, injected, aop'd and all the usual functionality that a Spring bean has access to.

There are some downsides to implementing Components inside Spring, so be sure to check out the documentation for more details.

Read More

For more details, have a read of the extended documentation, and have a look at the examples provided in the download.

Since this has become a far larger project than its original inception, I've done away with the Riaforge Forum, and have started a new javaloader-dev google group for support and discussion of JavaLoader and Java and ColdFusion integration.

While I'm very confident in the code that I have written for JavaLoader 1.0, I decided to call it an Alpha, simply because it has only really been tested by me and my Unit Tests.  Knowing from experience that users of Open Source Software have a tendency to use and abuse libraries far above and beyond what the author had ever originally dreamed led me to decide to call it Alpha until the community has really had a good change to play with it.

Please download JavaLoader 1.0, take it for a spin, sign up for the mailing list, and if you find any problems please do let me know.
26 August 2009 02:46 PM 3 Comments

Getting UTF-8 and MySQL to work with ColdFusion 9 ORM

A question I've seen show up quite often in Hibernate forums is 'How do I get Hibernate to generate UTF-8 Compliant Tables and/or columns when it generates my database tables when using mySQL?'

It's actually, quite easy to do, but often (myself included), people end up looking deep into Hibernate for some mysterious setting.

In reality, it's just a question of setting up your database correctly.  The first thing you need to do is set your database to use UTF-8 character coding as its default, like so, when creating it:

create database my_new_database default CHARACTER SET = utf8 default COLLATE = utf8_general_ci;

This will ensure all tables that are created by ColdFusion's ORM are created with a UTF-8 character set.

That being said, I have seen issues when data is being sent up to MySQL in UTF-8 form getting corrupted.  To ensure the database drivers use the correct character set as well we add useUnicode=true&characterEncoding=UTF-8 to our MySQL connection string in the ColdFusion Admin under the datasource's Advanced Settings.

There you go! UTF-8 support in mySQL with ColdFusion ORM!

17 August 2009 07:03 PM 5 Comments

Overloading ORM Implicit Get and Set Methods

This is something I just ran into with ColdFusion 9's ORM implementation, that thankfully Rupesh got back to me very fast on, otherwise, I probably would have been confused for quite a while.

I needed to overwrite a get and set value in a CFC I was creating.  We will say for arguments sake I was hashing a password on a User object (even though I was doing something completely different), like so:

component output="false" persistent="true"
{
    property name="userid" fieldtype="id" ormtype="int" generator="identity" hint="primary key";
    property name="name" type="string" notnull="true" length="200" hint="The user's name";
    property name="password" type="string" length="200" hint="The user's password";

    public void function setPassword(String password)
    {
        instance.password = hash(arguments.password);
    }

    public String function getPassword()
    {
        return instance.password;
    }
}

This is how I would usually have written my Components, storing my data in variables.instance, so they wouldn't overlap with any of the data stored in my variables scope.

What I couldn't understand was, my password would keep getting stored in my database as NULL, even though I had explicitly set it.

Thankfully Rupesh explained that when the ColdFusion ORM retrieves and populates data in an ORM managed CFC, it directly accesses the variables scope in the CFC.  So in the above instance, the ORM was finding no data for the password, and interpreting that to mean that I wanted to insert that as NULL into my database.

Therefore,  to get my code to work was to store my data in the variables scope, like so:

component output="false" persistent="true"
{
    property name="userid" fieldtype="id" ormtype="int" generator="identity" hint="primary key";
    property name="name" type="string" notnull="true" length="200" hint="The user's name";
    property name="password" type="string" length="200" hint="The user's password";

    public void function setPassword(String password)
    {
        variables.password = hash(arguments.password);
    }

    public String function getPassword()
    {
        return variables.password;
    }
}

This way the ORM can find exactly what it is looking for, and I can manipulate my data the way I want.

The fact that the ORM integration works this way is actually a very good thing, as it means that my password above doesn't get hash'd over and over again, but it is something we all should be aware of when you want to overwrite the implicit get and set functions that get generated by <cfproperty> declarations.

04 August 2009 07:27 AM 12 Comments

ColdFusion 9 ORM - Explaining Hibernate Object State

In the previous two articles, we started the discussion of Hibernate Sessions and how they related to the ColdFusion 9 ORM.  We noted the fact that a Hibernate Session keeps track of what objects it loads, and can therefore update it when it realises that the object has changed.  The question then posses itself - if a Hibernate Session has closed, which happens at the end of every ColdFusion request, what happens to the objects that it was managing?

Going forward, I'm going to reuse the Musician model I used in the Introducing ORM in Adobe ColdFusion 9 beta Adobe DevNet article, for which the updated code samples can be found here.

The very short version for those who don't wish to look at the code, is a model in which we have a Musician, who has a name, and an age, and he/she also has a many-to-many relationship to an array of Instruments, which they can play.

As far as Hibernate is concerned, there are three different states for any Object that it interacts with.

Transient

An Object/Entity (you could use either word) is Transient, if it has just been created with a createObject() or new operator, but has yet to be saved with the EntitySave() method.

Obviously, if transient objects are not persisted via EntitySave(), then they never get stored in the database, and will eventually be garbage collected.

For example, our musician john below is a transient object:

 

<cfscript>
    import com.*;
   
    >//this is transient
    john = new Musician("Transient John");
</cfscript>

Since john is never saved, it will always be transient.

Persistent

A Persistent object is one that has either come from, or has been saved in the database, within the scope of the current Hibernate Session (which is an important point to note).

For example, we can make our musician john below persistent, by:

<cfscript>
    import com.*;
   
    //join is transient
    john = new Musician("Transient John");
    
    john.setAge(47);

    //john is now persistent   
    EntitySave(john);
</cfscript>

Therefore, since john was inserted into the database, he is persistet.

By the same token, if we retrieve an object through the ORM, it is also persistent:

<cfscript>
    >//larry's ID is 2

    //larry is also persistent
    larry = EntityLoad("Musician", 2, true);
    
    //As larry is persistent, we can change his age, which will be reflected in the database
    larry.setAge(19);
</cfscript>

Since larry was retrieved from the database, he is also persistent.

Detached

Detached objects are ones that used to be persistent, but the Hibernate Session has closed. Detached objects were one of the biggest things for me to wrap my head around when starting with Hibernate, and can cause a few really tricky errors to occur.

To explain detached a little better, we can go through a scenario that will causes them, as I think this is something that a lot of ColdFusion developers are going to end up running in to.

Let's have a new musician, called Tim, and time is going to have 2 instruments that he plays, the Flute and Piano.

We are going to grab Tim out of the database, and then put him in our ColdFusion Session scope, so we can keep track of him from request to request.

<cfscript>
    tim = EntityLoad("Musician", 2, true);
    
    session.musician = tim;    
</cfscript>

For this request, Tim will be persistent, however, on the next request, Tim is now detached, as the Hibernate Session will have closed at the end of the previous request.

Therefore, if I do this:

<cfscript>
    instruments = session.musician.getInstruments();    
</cfscript>

<cfdump var="#instruments#">

You will see the following (not well written) error:

failed to lazily initialize a collection of role: Musician.instruments, no session or session was closed

If you are running ColdFusion via the console, you will also see something similar to:

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: Musician.instruments, no session or session was closed


What does this error even mean? 

First of all, we should remember that the collection of Instruments our Musician can play are lazy loaded. This means they aren't actually loaded from the database into the object until you actually request them.

The important thing to note here, is that lazy loading with Hibernate can only occur if the Hibernate Session that the object was originally loaded from is still open.  To put it another way, if the Hibernate Session has closed, then Hibernate has no record of what the object was doing, and therefore can't do any lazy loading.

In the above example, since the previous ColdFusion request ended, the Hibernate Session has closed, and if you attempt to access a relationship that is set to lazy load, and has yet to be loaded, this error occurs.

Its should be noted that singular properties are not lazy loaded - therefore, if you are just grabbing a property on an object that is detached, no error will be thrown.

What can we do to mitigate this issue? There are a few options, one of which is, to simply retrieve the object all over again, like so:

<cfscript>
    session.musician = EntityLoad("Musician", session.musician.getMusicianID(), true);

    instruments = session.musician.getInstruments();    
</cfscript>

<cfdump var="#instruments#">
Or, like so:
<cfscript>
    session.musician = entityLoadByExample(session.musician, true);

    instruments = session.musician.getInstruments();    
</cfscript>

<cfdump var="#instruments#">

As then the object we are dealing with is considered persistent, as it is attached to the currently open Hibernate Session.  This tends to be the easiest of the options when dealing with detached objects.

Another interesting way of making our detached object persistent is like so:

<cfscript>
    EntitySave(session.musician);

    instruments = session.musician.getInstruments();    
</cfscript>

<cfdump var="#instruments#">

This may look strange, but what is actually happening when you call EntitySave(), is that it calls the Hibernate method saveOrUpdate()

A quick version of what saveOrUpdate() does is -

  • If the object being passed in is transient, INSERT it to the database.
  • If the object is already persistent in the current Hibernate Session, do nothing.
  • If there is already an object that represents the same Entity data persistent in the Session, throw an exception
  • Otherwise, update the database with the information in the passed in object, and set its state to persistent.
Therefore in the example above, the data stored in session.musician will be saved again to the database, and since session.musician is now deemed persistent, we can successfully do lazy loading of the instruments.

However, if a situation like this would occur:

<cfscript>
    musicianTwo = EntityLoad("Musician", session.musician.getMusicianID(), true);

    EntitySave(session.musician);
</cfscript>

We get the following error:

a different object with the same identifier value was already associated with the session: [Musician#2]

Since Hibernate deems the persistent object that is currently connected to the Hibernate Session much more important than the detached object, which makes sense, as the persistent object has the most up to date version of the data stored in the database.

Generally speaking, if you at all can, try and avoid having detached objects in your application, as this is generally a Good Thing™, and will allow you to avoid some pretty decent headaches as you develop with CF9 ORM.  Strategies such as storing IDs in the ColdFusion Session and having an API to return a new Object by that ID on request is often a good way to go, rather than storing the Entity itself in the ColdFusion Session.  That being said, if your architecture means that you have to have detached objects this series should be enough to give you a basic grounding the concepts of object state, and how to manage it.

If you want to learn more about managing Hibernate Object States (and there is far more to it than I have written here), you can read more about this in the Hibernate documentation, but this should hopefully have given you a decent enough overview to avoid some possible pitfalls when handling persistence with ColdFusion 9's ORM integration.
31 July 2009 08:10 AM 0 Comments

Speaking at MAX this year - ColdFusion for Java Devlopers

This year it is going to be my absolute pleasure to be attending and presenting for the first time ever at the Adobe MAX conference.

My presentation is entitled ColdFusion For Java Developers and is scheduled for Wednesday, 5:00pm.

Primarily aimed at Java developers, it is going to cover a myriad of ways that you can integrate your already existing Java code base into a ColdFusion application, and also get your Java model talking seamlessly to your ColdFusion code base.

The official synopsis is:
Ever since ColdFusion was re-implemented as a J2EE application, the benefits of combining Java and ColdFusion application development have been easy to see, and widely used across the ColdFusion landscape.

This talk will look at some of the ways we can already take advantage of common Java libraries in ColdFusion, and enable Java developers to leverage the libraries and frameworks that they are already using. We will also be looking at how Java developers can seamlessly leverage the dynamic scripting language of ColdFusion, within their Java code, to easily enable them to take advantage of some of the RAD features that come bundled with ColdFusion.

That being said, if you are a ColdFusion developer who likes to also work with Java, you may wish to come along, as there will be several techniques demonstrated that will be provided by the forthcoming JavaLoader 1.0 release that should (hopefully) interest you greatly.

I look forward to seeing you all at MAX, and also at the ColdFusion Unconference!
28 July 2009 08:41 AM 7 Comments

Updated Sample Code for Introduction to CF9 ORM DevNet Article

My apologies if this is a little belated, but here is an update to the sample code that was posted with my DevNet article Introducing ORM in Adobe ColdFusion 9 beta.

Unfortunately several things changed in CF9 between the time that I wrote the article and when the public beta came out.

The major differences between the sample on Adobe.com and this one are:

  • The datatype attribute on cfproperty was changed to ormtype.
  • Disable Implicit UDF Registration is now turned on by default, so any implicit setter/getter inside a CFC has to be prefixed by 'this.' for them to function.

I will endeavour to keep this download up to date as new versions of ColdFusion 9 are release.

coldfusion9_orm_sample.zip

 

21 July 2009 08:32 AM 15 Comments

ColdFusion 9 ORM - More on Flushing Hibernate Sessions

Hopefully with my previous article, I've got you understanding how Hibernate Sessions work behind the scenes of ColdFusion.  However, there is one statement I made that requires further clarification before we go any further.

I wrote:
"This means that changes to your objects will also not be persisted to your database, until the end of your ColdFusion request, as that is when the Hibernate Session is closed."

Technically this isn't exactly true, but it was a concept that confused me a lot when first starting with Hibernate, so I wanted to get people thinking in the right direction without complicating things too much.

The Problem

For example, a situation like this made me scratch my head for a long time when I first started working with Hibernate:

We have 5 Musicians in our database, and we want to delete one, and then re-list all of them again.

<cfdump var="#ormExecuteQuery('from Musician')#" label="query">

<p>We are now deleting!</p>
<cfset musician = entityLoad("Musician", 3, true)>
<cfset EntityDelete(musician)>

<cfdump var="#ormExecuteQuery('from Musician')#" label="query">

And we would see a result like:

Tom, Jerry, Ben, Bob, Richard

We are now deleting!

Tom, Jerry, Ben, Bob, Richard

This shows me exactly the same data we before and after my EntityDelete().  Wait... what? Didn't I delete Musician Number 3?

The fact of the matter is, yes, we deleted Musician #3, except since the Hibernate Session hasn't been flushed yet, the data hasn't been persisted to the database.  Therefore, when we run out HQL query, we see all the Musicians!

Hibernate Session Flushing

Before we go directly into how to solve this problem, what does the Hibernate documentation say about when Session Flushing actually occurs?

This process, called flush, occurs by default at the following points:
  1. before some query executions

  2. from org.hibernate.Transaction.commit()

  3. from Session.flush() 
So what does that actually mean in terms of ColdFusion?
  1. Before some query executions - So at some arbitrary points during the Hibernate Session life cycle it may flush.  Obviously not something we can rely upon.
  2. At the end of a Transaction. So if we our code in a <cftransaction> block, it should flush at the end of that transaction, and therefore the changes to our objects will be persisted in the database.
  3. When we call ORMFlush(), or at the end of a Session when it is called implicitly.

Therefore, if we wrap the relevant code in or Transaction, like so:

<cfdump var="#ormExecuteQuery('from Musician')#" label="query">

<cftransaction>
<p>We are now deleting!</p>
<cfset musician = entityLoad("Musician", 3, true)>
<cfset EntityDelete(musician)>

</cftransaction>
<!--- Session should be flushed now --->

<cfdump var="#ormExecuteQuery('from Musician')#" label="query">

We should get a result of:

Tom, Jerry, Ben, Bob, Richard

We are now deleting!

Tom, Jerry, Bob, Richard

Alternatively, we could also do:

<cfdump var="#ormExecuteQuery('from Musician')#" label="query">

<p>We are now deleting!</p>
<cfset musician = entityLoad("Musician", 3, true)>

<cfset ORMFlush()>
<!--- Session should be flushed now --->

<cfdump var="#ormExecuteQuery('from Musician')#" label="query">

And we would also see the same results.

So as you can see it is not exactly true that your object data will only get persisted at the end of you request, as you actually have a lot of control over exactly when the Session gets flushed.

It is important to note that 9/10 times you probably won't care when the Session gets flushed and the changes to your objects actually get persisted in the database.  However, there will be instances in which you will care, and your code depends upon having your data persisted in your database.  You now have the tools to manage your persistence life cycle and know what is going to happen when.

15 July 2009 11:26 AM 5 Comments

ColdFusion 9 ORM - Explaining Hibernate Sessions

Now that ColdFusion 9 is in public beta, I wanted to write some articles explaining how Hibernate is actually working under the hood of the nice ORM integration we now have.  Like all powerful tools, they can do a great many things - but only if you really understand how they work.  Otherwise, they are potential for disaster if you don't know what you are doing.

Hibernate Sessions

The first thing we need to cover is the concept of Hibernate Sessions, which has been nicely hidden away from ColdFusion developers by the Adobe Engineering team, but is still something that you need to really understand to be able to leverage Hibernate in CF9 properly. (At least IMHO).

First things first - don't confuse this with ColdFusion Sessions, or any sort of browser session.  Hibernate is built as a generic solution to ORM, so it has no specific ties to web state. A Hibernate Session is a lightweight object that is used to delineate when Hibernate is meant to start working, and when it is meant to stop, which is often referred to as a unit of work. This may span several transactions and/or INSERT, UPDATE, DELETE and SELECT statements as the Session gets used.

This is very much like the start and stop of a conversation, we say hello at the beginning, and say goodbye at the end, and whatever we need to discuss goes on in between, except we just tell the Session to open() and close(), rather than "hello" and "goodbye".

Actual Hibernate Java code would look something like this:

//open the session from the SessionFactory (which is where sessions come from)
Session session = sessionFactory.openSession();

//get fred, our caveman
Caveman fred = session.get("Caveman", 2);

//change his age to 32
fred.age(32);

//close the session, which will update fred.
session.close();

I'm not going to get into where the SessionFactory comes from, as all you really need to know is: it's where Hibernate Sessions come from.

So what we are doing here is:
  1. opening a Session, i.e. we tell Hibernate 'Hi', which starts our conversation.
  2. Tell Hibernate to retrieve our Caveman fred, through our session.
  3. We change the age of fred to 32.
  4. We close our session, and say 'GoodBye' to Hibernate for now.
There are several things that happen here that are worth noting at this point, even in this relatively simple piece of code.

The first is, by doing session.get("Caveman", 2), we have effectively told our Session to track this object, and make note of any changes that happen to it. 

We have also cached a copy of fred in the Session itself, so that if we were to attempt to retrieve fred again, we would get the same copy.  This is both for performance, and also so that the Hibernate Session only has to deal with one object that represents the data behind fred, which will be a fairly important concept as we continue in this article series.

Since our Session is tracking fred, any change we make to fred will be persisted to the database when we close our Session.  In that way, Hibernate is quite transparent in the way it implements persistence.

It should also be noted at this point: Unless you specify otherwise, Hibernate will only run INSERT, UPDATE and DELETE when the session is closed, generally as a batch.  This is so that, for example, multiple changes happen to fred during the length of our Session, there only needs to be one UPDATE statement when we are finished.  This is an important thing to note, as it is possible to get confused as to why your changes to your objects aren't appearing in your database during your Session, but do appear afterwards. 

Hibernate Sessions and Web Applications

In web applications, it is usual to manage Hibernate Sessions by opening one up at the beginning of a HTTP request, and then closing at the end of the request.  The length of a single HTTP request is a good size to carry on a nice conversation with Hibernate.

Strangely enough, this is exactly what ColdFusion is doing for you behind the scenes.  It starts a Hibernate Session when your request starts, and ties it to that particular request, and then closes it at the end of the request.  (It is quite likely that the Session actually only gets created when first requested, but for the sake of argument it is easier to explain it as it gets opened at the start of the request)

From there, each of the ORM functions, EntityLoad, EntitySave, EntityDelete, etc, all interact with that Session that exists behind the scenes, for that request.

This means that changes to your objects will also not be persisted to your database, until the end of your ColdFusion request, as that is when the Hibernate Session is closed. In later articles, I'm going to cover some ways this can cause some trouble, and how to work around them.

 

You are actually able to flush the Session, which forces it to persist any changes to the database right then and there, and not wait until the end of the request, which can sometimes be very useful. 
To do this in Java, you could go:

session.flush();

But in ColdFusion you write:

ORMFlush();

UPDATE: You can read more about Session Flushing here, which outlines that there are times in which Hibernate will flush a Session in the middle of Session, however, there is often no guarantee except in specific circumstances.

It's also interesting to note you have direct access to the Hibernate Session if you so desire through ORMGetSession(), which gives you access to that request's Hibernate Session object, so you can interact with it directly.

There is much more to Hibernate Sessions and how they relate to the objects that they manage, but this will give us a good start to build upon for now.

You can read more about ColdFusion and Hibernate Sessions in the documentation Hibernate Session Management.

Installing ColdFusion Builder Beta on Linux

UPDATE (21 October 2009): This will no longer work with Beta 2 of ColdFusion builder. If you are looking for a more up to date technique for installing ColdFusion Builder on Linux, please see this post .



So I’ve managed to hack my way to getting Bolt installed on Linux, and it wasn’t quite as painful as I thought it was going to be.  It is essentially a pure plug-in install, but we have to jump though a few hoops to get the plug-in itself.

I would suggest starting with a clean installation of Eclipse 3.4.2, with a clean workspace, just to make sure there are no major issues.

Here are the steps you need to reproduce:

  • Download ColdFusion Builder for Windows. I used 32 bit, but I don't think it matters.
  • in the terminal run: unzip cfbuilder_{your version}.exe, to extract all the content.
    (Update 16/09/09, as Universal Extractor isn't actually needed, see comments)
  • Install Universal Extractor - http://legroom.net/software/uniextract
    (I installed under CrossOver office, and it worked a treat, should work under Wine)
  • Extract the data from bolt.exe (I extracted to /tmp/bolt), using Universal Extractor
  • Extract /tmp/bolt/InstallerData/Disk1/InstData/Resource1.zip, (I extracted to /tmp/Resource1/)
  • Under /tmp/Resource1/Z_/dist/installer you will find ’installerdist_zg_ia_sf.jar’
    • Unzip this .jar file, you will find the /plugins and /features directories you need for a plugin install on Eclipse.
    • Extract those 2 directories into your Eclipse installation.
  • If you want the CF Builder Extension Samples, you can find them inside /tmp/Resource1/Z_/installer as ’samples_zg_ia_sf.jar’.  Open up that archive and there they are!
  • Fire up Eclipse, and you should now find you have a ColdFusion perspective!
So far, there is only 1 annoying bug I’ve found. 

When using CTRL+J to insert a snippet, it inserts perfectly, however, I find I have to click outside of Eclipse, and then back into Eclipse with my mouse before I can edit again (very weird, I know).  It's annoying, but I can work around it.

Hopefully we can provide enough free testing for ColdFusion Beta on Linux, and prove we have a large enough user base, that we can get supported on Linux.

Make sure any bugs you run into are reported to the ColdFusion Builder Bug Tracker page, so that Adobe is aware of them.
13 July 2009 03:12 PM 2 Comments

ColdFusion 9 Beta Drops, and so does my Devnet ORM Article!

As I'm sure you have all noticed, ColdFusion 9 Public Beta is now available for download.

I am really excited about this release, and think it is going to change the way a lot of people are going to be developing applications going forward.

Some of my favourite new features are:
  • Hibernate ORM
    As we all  well know, I have a special place in my heart of Object Relational Mapping, and the inclusion of Hibernate in ColdFusion gives me some lovely goosebumps.  I've worked with Hibernate before, and it really is a top-notch piece of software, and a great ORM to work with.  I can also honestly say that the engineers at Adobe have done an excellent job of providing it to ColdFusion developers in a way that (a) is quite easy for new users to pick up and use and (b) exposes much of the internals of Hibernate to those who are more experienced, and want to do some more complicated things.

    I wrote an article for Adobe Devnet, called Introducing ORM in Adobe ColdFusion 9 Beta, which I think is a nice introduction to the basics of ORM, and takes you through some simple steps of using Hibernate in Java without getting too complicated.

    Over the next few weeks I plan on writing several more blog posts outlining Hibernate within the ColdFusion context, and giving people more of an idea of what is going on under the hood so they can avoid some 'gotchas' I think people will run into when starting to play with Hibernate.
  • Language Enhancements
    I am really enjoying writing so much more of my application in CFScript.  Coming originally from a Java background, CFScript is a much more natural fit for the way I like to write code, so I am very excited to be able to do so much more of my development using CFScript, rather than being forced to cut between CFScript and CFTags.

    Oh yeah, and let's not forget things like implicit getters and setters, the new and import keywords, and nested transactions (finally!).  So many good things!

  • ColdFusion Builder
    I could go into each and every part of ColdFusion Builder, for which there is a fair amount, but overall I think this is an amazing release for what is essentially a 1.0 IDE.

    My favourite part of CF Builder is quite likely just the code assistance in scripts and tags.  I have a ridiculous ability to misspell/miss-type 'arguments' on a regular basis. Now I just type 'arg', hit ctrl+space, and it enters it for me.  Aaaah, no more misspellings !
So if you haven't already, grab a copy of ColdFusion 9 Beta, and ColdFusion Builder Beta, and enjoy!
09 June 2009 09:18 AM 0 Comments

Melbourne Coldfusion 9 and FLEX 4 Usergroup Tour

I just wanted to make sure that everyone was aware of the Melbourne leg of the ColdFusion 9 and Flex 4 Usergroup Tour, on June 17th.

Adobe ColdFusion 9

The Adobe ColdFusion team is hitting the road to discuss Centaur, the next version of ColdFusion, and Bolt - code name for the highly anticipated first ColdFusion IDE from Adobe.  Learn about exciting new features and discover how Centaur and Bolt will accelerate your ColdFusion application development. Visit the tour calendar http://bit.ly/UGTour09 to find a stop near you!

Flex 4 / Flash Catalyst

Come learn about the newest features in the Flex 4 framework, Flex Builder 4 and the newest Adobe product -- Flash Catalyst. See product feature demos, and learn how the new Flex framework powers both Flash Catalyst and Flex Builder to speed the development and testing of rich Internet applications and content.

More details and RSVP can be found here .

Hope to see you there!

 

ColdSpring News, CFConversations RoundTable and other cf.Objective() tidbits

While I am recovering from the Australian WebDU conference, a few days before that started I got off a plane after the end of the wonderful cf.Objective() conference.

I have to say, this year's cfObjective() was the best organised out of all the years I have been to.  As per usual, the content was stellar, the hotel was lovely, and it was an absolute pleasure to catch up with everyone at the conference.  I have to give a big 'congratulations' to Jared, Steven, Jim and the rest of the cf.Objective() crew for putting together such a smooth and professional conference.

I had the pleasure of doing two sessions, Rapid OO Development with ColdFusion Frameworks, which covered a variety of techniques on how to increase your development speed when building OO models, and I was very happy to see that it seemed to have been very well received.  I had one attendee let me know that 'Now I know why I'm using ColdSpring! I was using it before, but now I know why', which is an amazing thing to hear as a presenter, that you've managed to create an 'Aha!' moment for someone.

I also did my Introduction to Building Applications with Transfer ORM, which was a repeat of the session that I did last year.  Unfortunately Ray Camden couldn't make it to do his Transfer session, so I was called in at the last minute to take his place.

The big news that we announced at cf.Objective(), is that I will now be the lead developer on the ColdSpring project.  Since Chris Scott's major focus these days is the Swiz Flex framework, he decided it was time to pass on the reigns, and since I tend to talk to him regularly about Cold/Spring, have contributed code to ColdSpring , and know about running an Open Source project, he seemed to think I would be a good fit.  I'm pretty excited about the opportunity, and have discussed some great ideas with theColdSpring development group, of which Chris is going to stay on as lead architect.  I expect we will start off by building the infrastructure around the project, e.g. a centralised wiki, ticket tracker etc, and then move on to some more interesting items.

The obvious question there is, of course, what does this mean for Transfer? (I think I need to start writing down how many times I've been asked if it's 'Dead'.  Does anyone actually expect a 'yes' for an answer?), and quite frankly, I don't see this impacting on Transfer much at all, simply because this is going to be code that I would have probably ended up writing on ColdSpring anyway, but it is now a more formalised relationship.  When I run into a feature or a bug on an Open Source project, that I want to be implemented, my first natural reaction is to start looking into the code, and writing the feature.  This was first exemplified by my contribution toColdSpring of annotation based pointcuts.  There are several aspects of ColdSpring I wanted to improve on, so it was just a natural reaction for me to end up writing code for it.

As stated, the content at cf.Objective() was brilliant as per usual, with my own personal highlights being, Advanced ColdFusion Server Administration (Adam Lehman), Advanced ColdFusion 9 ORM (Terry Ryan) and ColdFusion Portlets (Adam Haskell).

Thinking about the content, I have a little confession to make, that I realised on the way back from cf.Objective() this year.  I have a tendency to go to the wrong sessions when at a conference. This may sound like a weird thing, but I realised the last few years I tend to go to sessions that I already know a lot about, just to see if they say something a little bit extra that I can add to my knowledge base.  Quite often I end up walking out feeling like I haven't added much to my repertoire.  Really what I should be doing is going (mostly) to sessions in which I know absolutely nothing about, which means I actually get the best return on the my investment in the conference.  While it may not be specifically applicable to what I'm currently doing, at the very least it will inspire me to do some interesting new things, and may give me some knowledge that I can then apply at some point in the future.  This is a philosophy I plan on applying to all future conferences that I attend.

Finally, I also had the opportunity to be part of a CFConversations round-table on the second night of the conference.  Brian Meloche, Andy Powell, Andy Matthews and I had a really good chat about the conference in general, our thoughts on some of Adobe's upcoming products, various other topics relating to ColdFusion.  It was lots of fun to do, and you can download and/or read more about it here.

Again, thanks to all the cf.Objective() crew, and look forward to seeing many of you again at cf.Objective(ANZ).
06 May 2009 04:14 PM 0 Comments

ColdFusion & Flex Data Transformations with Conduit Filters

Previously I discuss a simple mechanism in Conduit to enable you to apply data transformations on outgoing data from ColdFusion to Flex, using a simple inheritance strategy, to overwrite how the CFC=>Flex VO object translation occurred.

The only issue there is, if you need to be able to do different transformations, you end up having to combine separate code-bases into a single CFDeserialiser or CFSerialiser , which is not very portable, or decoupled.

To solve this problem, Conduit has filters that can be applied at different points in the AMF communication life cycle, and manipulate the data that is being passed through.

So, if we take the example we looked at previously, where we reversed every simple value that was travelling from ColdFusion to Flex, we can convert this into a simple filter, which is much easier to apply, and can be combined with other filters to do fairly complex data manipulation.

An example ReverseFilter looks like this:

<cfcomponent hint="filter that reverses all strings" output="false">

<cffunction name="init" hint="Constructor" access="public" returntype="ReverseFilter" output="false">
    <cfargument name="args" hint="the argument ConfigMap" type="struct" required="Yes">
    <cfscript>
        return this;
    </cfscript>
</cffunction>

<cffunction name="doFilter" hint="does the filtering - reverses strings" access="public" returntype="void" output="false">
    <cfargument name="filterData" hint="the data for the filter" type="struct" required="Yes">
    <cfargument name="filterChain" hint="the filter chain" type="conduit.core.filter.FilterChain" required="Yes">

    <cfscript>
        >//we know there will be a 'result', in the after filter
        if(isSimplevalue(arguments.filterData.result))
        {
            arguments.filterData.result = Reverse(arguments.filterData.result);
        }

        >//push on to the next filter
        arguments.filterChain.next();
    </cfscript>
</cffunction>

</cfcomponent>

The doFilter() method is the method that manipulates the incoming data, in this case, looking at the 'result' argument that is being passed in, and if it's a simple value, reversing it.

The Filter is then passed on to any subsequent filters, by calling the next() method on the filterChain.  If we didn't want filtering to continue, we could simply skip that step.

We then configure this ReverseFilter against the CFSerialiser, to convert outgoing data that is going to Flex, like so:

<destination id="Conduit">
     <channels>
        <channel ref="my-cfamf" />
     </channels>
     <adapter ref="conduit" />
     <properties>
         <source>*</source>
         <cfcs>
             <!--- cfc config --->
         </cfcs>         
         <filters>
            <!-- This is an example filter that reverses strings -->        
            <filter>
                <path>conduit.core.filter.example.ReverseFilter</path>
                <apply-after>serialiser</apply-after>
             </filter>
        </filters>
    </properties>
</destination>

The 'apply-after' section, tells Conduit to fire the ReverseFilter after the processing of the CFSerialiser, rather than before, although in this case, it won't make that much difference.

This is just a simple example for the sort of things that can be done with Conduit Filters, but it should give you a good idea on how with a few simple filters, you can drastically change the way data is sent to and from Flex and ColdFusion.

If you want to read more about Conduit, please have a look at the wiki, and daily builds can be downloaded from the google group.

03 April 2009 08:58 AM 0 Comments

cfObjective(ANZ) - Call for speakers

Several days ago, cf.Objective(ANZ) put out a call for speakers.

For those who have missed the announcements, cf.Objective(ANZ), is bringing the famous cf.Objective() conference to Melbourne Australia. 

To steal some of the copy straight from the website:

Topics we're looking for fit into (but are not limited to) the following major categories:

Architecture and Design:
OOP, Design Patterns, Frameworks, Modeling, Refactoring Legacy Apps, Persistence etc.
RIA:
LC DS and CF, Ajax/Flex with CF, BlazeDS and CF etc.
Process and Methodology:
Agile Development, SOA, Managing large CF architectures, Debugging and Metrics etc.
Integration and Testing:
CF and Java, Build and Deployment processes, Server tuning, Unit Testing etc.

Please let us know by April 24 2009 if you're interested by emailing speakers@cfobjective.com.au with a short blurb about yourself and the topics you'd be interested in presenting on.

cf.Objective(ANZ) will provide speaker accommodation for the night of the 12th to the 13th of November 2009 at the conference venue (Renaissance Hotel in Melbourne). At this stage we unfortunately can't provide any further financial assistance with travel cost or other expenses.

So if you wish to speak, or if you wish to hear about a particular topic, please feel free to send an email to the above address to let people know.

If you want to know more, you can check out the website , sign up to the website, and also follow the twitter feed !

Hope to see you all there!

 

Coming to speak at cf.Objective()!

As per usual, I'm late with my announcement that I will speaking at cf.Objective() again this year.  It is actually really interesting to see the schedule contain so many sessions that cover OO concepts, and specifically, how to use common tools and development practices to make OO development in a web application context so much easier, better and faster.


This is obviously a real trend in the ColdFusion thoughtscape, with sessions like:
  • Introduction to OO Modeling and Design - Brian Kotek
  • Taking Code Reuse to a Higher Level - Jeff Chastian
  • Building an Object Oriented Model - Bob Silverberg
  • RAD OO in Code - Peter Bell
  • Atomic Reactor - Mark Drew
  • Leveraging Basic Object Oriented Concepts and Design Patterns in ColdFusion - Phill Nacelli
  • What to do When OO Fails you in ColdFusion - Brian Meloche
  • The Best of Both Worlds: Java Backends with CFML Frontends - Matt Woodward
  • Object Relational Mapping with ColdFusion - Jason Delmore
  • An Object Oriented Approach to Validations - Bob Silverberg
  • Leveraging Enterprise Open-Source Java in ColdFusion - Joe Rinehart
..and of course, my very own Rapid OO Development with ColdFusion Frameworks.

If you are looking to do, or already are doing Object Oriented development in ColdFusion, this is quite obviously the place to be!

In my Rapid OO talk, we are going to take a completely manually written OO model, including persistence to the database, and slowly strip parts of the code away, replacing them with a combination of ColdFusion Frameworks and custom generic code, to give you some new tools in your 'OO Development tool-belt', that you can then go away and play with, and hopefully include in your day to day development practices.

Look forward to seeing you all there!
17 March 2009 03:44 PM 0 Comments

Speaking at WebDU this year!

I'm a little late in posting this, but I had figured I should at least mention that I am speaking at WebDU this year again.

For those who haven't been before, WebDU is a fantastic Adobe/Web technology focused conference that has been happened in Sydney for quite a while now.  This year I'm particularly excited by a lot of the Flex/RIA content that is being presented.

WebDU Banner

I'll be there this year talking about a Conduit , the ColdFusion adapter for Blaze DS, which allows you to all sorts of weird and wacky things with data transfer to and from Flex and ColdFusion.  I'll be showing off some cute and clever data transformations and interesting techniques for data exposure using Conduit, so it should be a interesting presentation for anyone doing ColdFusion and Flex development.

Look forward to seeing you all at WebDU!

cf.Objective() Comes to Melbourne, Australia: cf.Objective(ANZ) is born!

Last year I got the opportunity to have dinner with the steering committee of cf.Objective() in the United States, and the topic of bringing cf.Objective() over the Australia was brought up.  I was instantly excited by the idea as I had always had such a wonderful time at cf.Objective() in the US, and had found it such a marvelous ColdFusion learning experience that I've been back every year since, and am speaking again this year.

Apparently, I've now been given the title of 'cf.Objective() Vice Instigator - Pacific Operations ', for generally just being that annoying guy in the background going 'so what do we do next?', and harassing people on IM to make sure they show up for teleconferences.

Having a stack of focused, ColdFusion specific, Enterprise software development knowledge coming directly into Melbourne is going to be great for local ColdFusion ecosystem, both for Melbourne, and also for the Australia and New Zealand region. 

Speaking from experience, simply having a lot of smart minds that do enterprise ColdFusion development, in the same place, at the same time, talking ColdFusion, means that all sorts of interesting ideas and opportunities get discussed, developed, and often worked on in the halls of the conference.

The conference dates are the 12th and 13th of November, 2009.

We are still in the process of lining up sponsors and speakers, so if you are interested in either, please check out the website for more details and/or sign up for the mailing list, so you can be appraised of further developments. 

If you are interested in coming to cf.Objective(ANZ), please sign up for the mailing list as well, so you can stay abreast of the latest and greatest news for the conference.

Oh, and the hotel is gorgeous, you should check out the online video!

I look forward to seeing you all there!

28 January 2009 08:07 AM 0 Comments

ColdDoc 0.2 Released

Not a huge amount to report here, this release fixes a bug in which if there is no 'init' method on a CFC, ColdDoc ends up throwing an error.

You can download ColdDoc 0.2 from here .

26 January 2009 01:11 PM 0 Comments

CFUG Melbourne 2009 Survey

We are conducting a survey to try and tailor CFUG Melbourne to best fit the ColdFusion users in Melbourne, and provide you guys with the best CFUG we can.

Please take 10 minutes to fill out this quick survey on Google Docs, we would greatly appreciate it:
http://spreadsheets.google.com/viewform?key=pJCuG-fQNocTuTRAdDmagGg&hl=en

There are also prizes for filling out the survey! If you write your email at the end of the survey, you will be in the running for:

1st prize: An Adobe Backpack
2nd Prize: A copy of the latest Fusion Authority Quarterly Update (Vol III, Issue 1)
3rd Prize: A Metal Adobe Lunchbox

More details on the user group can be found on the Adobe Groups page .

Thanks for taking the time, and look forward to seeing you all at a CFUG meeting this year.

 

14 January 2009 05:03 PM 5 Comments

Improving on ColdFusion Remoting with Conduit

Since I've been working with Conduit, there have been several 'enhancements' to the Flex Remoting that I've implemented, above and beyond what ColdFusion provides out of the box.

These are mostly little things, but since Conduit is Open Source, we are able to incorporate them into how Conduit works, and give us some new tools to use when we set up Remoting.

One of the first enhancements I made, was around the fact that every time Flex invokes a CFC through Remoting, it gets created on every request.  Quite often, this is simply not necessary, as the CFC in question has no state, or maybe you want the CFC to maintain state, but you have to jump through some hoops to get that to happen.

In Conduit, you can now set a:

<cfcomponent remoteScope="application" >...</cfcomponent>

...and the CFC will be stored inside the specified shared scope.

For example, here is a CFC that gets stored in the session scope when invoked, and keeps a simple incrementing number each time its remote method gets called:

<cfcomponent hint="proxy stored in a share scope" output="false" remoteScope="session">

<cfscript>
    instance.value = 1;
</cfscript>

<cffunction name="getIncrementingValue" hint="returns a value, and increments it by 1" access="remote" returntype="numeric" output="false">
    <cfreturn instance.value++ />
</cffunction>

</cfcomponent>


So you can see here how we are able to maintain state between calls, within a single CFC.

The other enhancements I made, revolve around passing null values back and forth from AS3 Objects, and ColdFusion.

As we all know, there is no null as such in ColdFusion, which can make dealing with null values from Flex slightly problematic.

I've added two new enhancements to <cfproperty> for Value Objects to help with this issue - nullvalue and nullmethod.

nullvalue provides a value for a given property to be used when a null value is found in a Flex AS3 object coming down to ColdFusion.  This is particularly applicable when using getter/setters for your properties on your ColdFusion Value Objects.

For example:

<cfcomponent output="false" alias="tests.cfml.cfc.model.Basic">

<cfproperty name="date" type="date" nullvalue="1-1-1900">

<cffunction name="getDate" access="public" returntype="date" output="false">
    <cfreturn instance.date />
</cffunction>

<cffunction name="setDate" access="public" returntype="void" output="false">
    <cfargument name="date" type="date" required="true">
    <cfset instance.date = arguments.date />
</cffunction>

</cfcomponent>

...will set 'Date' to the 1-1-1900 if the AS3 Object's 'date' property is null.  Also, if sending data back up to Flex from CF, the 'date' property is set to null on the Flex side, if the date value is 1-1-1900.  This gives you a type safe way of dealing with null values coming down from Flex.

The nullMethod option for dealing with null values becomes more useful when dealing with object composition in Value Objects.

The nullmethod attribute specifies a method on the CFC to be fired, when encountering a null value for the specified method, e.g.

<cfcomponent output="false" alias="tests.cfml.cfc.model.Basic">

<cfproperty name="simple" type="tests.cfml.cfc.model.Simple" nullmethod="removeSimple">

<cffunction name="setSimple" access="public" returntype="void" output="false">
    <cfargument name="Simple" type="Simple" required="true">
    <cfset instance.Simple = arguments.Simple />
</cffunction>

<cffunction name="removeSimple" hint="remove simple" access="public" returntype="void" output="false">
    <cfset StructDelete(instance, "Simple") />
</cffunction>

</cfcomponent>

So in this case, whenever the property 'Simple' comes back from Flex as null, the method 'removeSimple' is called instead of attempting to set the property.

Now you can start to see what we can do with Conduit, since we can control all aspects of the Remoting process.  So the question is - if you could change any aspect of ColdFusion <=> Flex Remoting, what would it be?  Let me know, and we can see if we can incorporate it into Conduit!

If you want to read more, check out Differences between Conduit and ColdFusion remoting, in the Conduit documentation.
13 January 2009 08:30 AM 9 Comments

Encapsulating Common Exceptions in ColdFusion

When throwing exceptions in ColdFusion, we have the mighty <cfthrow> tag, which allows us to throw exceptions, with given names, and then catch them elsewhere in our application.

For example:

<cftry>
   <cfthrow type="myException" message="This is my custom exception" detail="This is my custom exception detail"/>

   <cfcatch type="myException" />
      <cfset writeOutput("Caught Exception") />
   </cfcatch>
</cftry>

Would output 'Caught Exception' onto the screen, as the cfcatch 'type' matches the name of the Exception being thrown.

This is all very well and good for a 'once off' throwing of an exception, but what happens when an Exception type is used across an code base?  Often I have found myself copy and pasting <cfthrow> statements, just so I can have consistent types, messages and details between Exceptions within a system.

Taking inspiration for the way in which Java has actual Exception objects, which can be implemented and then reused, I came up with the following solution, which I felt was quite elegant, and extensible.

It all starts with a single, lowly Exception.cfc, that looks a little like this:

<cfcomponent name="Exception" hint="Throws a given exception" output="false">

<cffunction name="init" hint="Constructor" access="public" returntype="void" output="false">
    <cfargument name="message" hint="the message to throw" type="string" required="Yes">
    <cfargument name="detail" hint="the detail in which to throw" type="string" required="Yes">

    <cfthrow type="#getMetaData(this).name#" message="#arguments.message#" detail="#detail#">
</cffunction>

</cfcomponent>

..and while this doesn't look like much in and of itself, it becomes quite useful when we start extending it, and using it create our own Exception types, for example, we can rewrite the example above, as myException.cfc:

<cfcomponent name="myException" hint="Throws myException" extends="Exception" output="false">

<cffunction name="init" hint="Constructor" access="public" returntype="void" output="false">
   <cfset super.init("This is my custom exception", "This is my custom exception detail") />
</cffunction>

</cfcomponent>

To then throw myException, I simply do:

<cftry>
  <cfset createObject("component", "myException").init();

   <cfcatch type="myException" />

      <cfset writeOutput("Caught Exception") />
   </cfcatch>
</cftry>


..and the exception will be thrown, with the type 'myException', which comes from the name of the CFC, without me having to write the same message, and detail over and over again.

To get more complicated, and to lift an example directly out of Conduit , this is the exception that gets thrown when Conduit can't find a particular method on a CFC it's making a Flex Remoting call to.

<cfcomponent name="MethodNotFoundException" hint="Exception for method not being found" extends="Exception" output="false">

<cffunction name="init" hint="Constructor" access="public" returntype="void" output="false">
    <cfargument name="component" hint="the component that the method is attempting to be called on" type="any" required="Yes">
    <cfargument name="methodName" hint="the name of the method" type="string" required="Yes">

    <cfscript>
        super.init("The method '#arguments.methodName#' in '#getMetaData(arguments.component).name#' could not be found.",
                    "This method could not be found. Please ensure that it was spelled correctly, and is not private"
                    );
    </cfscript>
</cffunction>

</cfcomponent>


In this case we take a component and a method name as an argument, and can build Exception messages and details, based on those arguments, much like you can with Java Exceptions. However, the actual Exception type in this example will actually end up being 'conduit.exceptions.MethodNotFoundException', as this CFC is found in /conduit/exceptions/MethodNotFoundException.cfc.

Now that your Exceptions are encapsulated inside CFCs, you can use them all over your code base, knowing the Exception type will not change, and you don't have to copy and paste your messages and details every time you want to use them.  There are other ways of doing similar things, but this is one way I found works well for me.
14 December 2008 09:58 AM 6 Comments

Conduit: The ColdFusion Adapter for BlazeDS

This project started with writing the translation layer for doing Transfer to Flex communication, I ran into a pretty nasty bug in ColdFusion's remoting implementation, and then ended up in a place that solves all these problems, and is incredibly flexible and powerful to boot!  Quite the round trip, but well worth it in the end.

Conduit requires that you set up BlazeDS on your machine, as well as install the conduit.jar file, and some CFCs as well.  I'm not going to go into too much details here, as you can read about in the Library Installation section of the documentation.

To configure Conduit, we open up our remoting-config.xml, and we add the Conduit adapter to the <adapters> section:

<adapter-definition id="conduit" class="com.compoundtheory.conduit.adapters.ColdFusionAdapter"/>

And now we continue by adding a new Destination to our remoting-config.xml, which we will then call from Flex via RemoteObject (examples of the configuration are provided in the downloads).

<destination id="Conduit">
    <channels>
        <channel ref="my-cfamf" />
    </channels>
    <adapter ref="conduit" />
    <properties>
        <source>*</source>
        <cfcs>
            <!--
            Whether or not reload the CFCs below on each request.
            Useful for debugging when building new invokers,serialisers
            or deserialisers
            -->

            <reloadcfcs>false</reloadcfcs>
            <!--
            The CFC that invokes the remote method call
             -->

            <invoker>conduit.core.CFCInvoker</invoker>
            <!--
            Translates CF=>AS3
             -->

            <serialiser>conduit.core.CFSerialiser</serialiser>
            <!--
            Translates AS3=>CF
             -->

            <deserialiser>conduit.core.CFDeserialiser</deserialiser>
        </cfcs>
    </properties>
</destination>

The id of the destination can be whatever you like, but we started with 'Conduit', so we would know what we are calling from Flex.

The <adapter> is specified to use the conduit adapter, rather than the default cf-object adapter.

We then set a series of properties, most important of which are setup within the <cfc> section.  This section controls what CFCs are called upon to perform various duties within the ColdFusion <=> Flex communication process.

Just to emphasise this point - this means that the majority of the heavy lifting done by Conduit is done with ColdFusion code.  This makes it really easy to extend, change, manipulate or debug.  It gives you almost complete control over the AS3<=>CF translation process, without you having to know much about Java at all (I will admit there are some Java classes involved).

We can see from there are three CFCs that the Conduit adapter has configured for it.

The <invoker>
This is the CFC that does the actual method calling.  In the instance of the conduit.core.CFCInvoker that comes with Conduit, all it does is create an instance of the CFC that has been requested in the <RemoteObject>'s source attribute, and calls the passed with method name and any parameters that were passed down from Flex.

The code looks something like this (just to show you how simple it is):

<cffunction name="execute" hint="Creates a cfc, and invokes a methodon it" access="public" returntype="any" output="false">
    <cfargument name="source" hint="the cfc source" type="string" required="Yes">
    <cfargument name="methodName" hint="the name of the method" type="string" required="Yes">
    <cfargument name="params" hint="the parameters to pass in" type="any" required="Yes">
    <cfscript>
        var local = {};
        var object = createObject("component", "#arguments.source#");
    </cfscript>

    <cfinvoke component="#object#" method="#arguments.methodName#"argumentcollection="#arguments.params#"returnvariable="local.return">

    <cfif StructKeyExists(local, "return")>
        <cfreturn local.return />
    </cfif>
</cffunction>

Pretty straight forward, no?

The <serialiser>

The job of this CFC is to take whatever is returned from the <invoker> and translate it into whatever you want to return back to Flex.  Since BlazeDS handles the AMF conversion part of it for us, the conduit.core.CFSerialiser only really needs to convert CFCs in Actionscript objects, set all their properties correct, and we are good to go.

The <deserialiser>

The deserialiser CFC's job it to take the incoming parameters that come down from a Flex RemoteObject call, and translate them into something usable for the <serialiser> CFC.

Again, since BlazeDS does a lot of the heavy lifting, the conduit.core.CFDeseriailser's main job, is to convert Actionscript Objects into their appropriate CFCs, and set all their properties correctly.

Changing how things work
 
While there are plans to put some interesting enhancements for Conduit to provide above and beyond what ColdFusion remoting already does, the real power of Conduit comes from being able to write your own custom Invoker, Serialiser or Deserialiser.

Say for example, when we send information from ColdFusion to Flex, we want to reverse every Simple value (String, date, numeric) that we come across.  Don't ask me why you would want to do this ;o), maybe you just like messing with your co-workers.

First thing we need to do is write our own custom CFSerialiser.cfc.  For this example, I'm going to reuse the conduit folder I would have setup, which already has a /conduit ColdFusion mapping pointing to it, and create a new folder called reverse inside it.

So I create a new component, under /conduit/reverse, and call in CFReverseSerialiser.cfc, and make it extend conduit.core.CFSerialiser.

We will now overwrite the translate method, which handles what data gets converted, and how, depending on its data type.

The code would look something like this:

<cfcomponent output="false" extends="conduit.core.CFSeriaiser" hint="Component for serialising CF=>AS3, in reverse">

<cffunction name="translate" hint="translation function for objects,reverses simple values" access="private" returntype="any"output="false">
    <cfargument name="object" hint="the object to serialise" type="any" required="no">
    <cfargument name="cache" hint="local reference cache for cyclic graphs" type="any" required="Yes">
    <cfscript>
        if(isSimpleValue(arguments.object)
        {
            >//if it's simple, then reverse it!
            return reverse(arguments.object);   
        }
        else
        {
            return super.translate(argumentCollection=arguments);
        }
    </cfscript>
</cffunction>
</cfcomponent>

And we can configure a special 'ConduitReverse' destination for anyone who wants reversed Strings in their code:

<destination id="ConduitReverse">
    <channels>
        <channel ref="my-cfamf" />
    </channels>
    <adapter ref="conduit" />
    <properties>
        <source>*</source>
        <cfcs>
            <reloadcfcs>false</reloadcfcs>
            <invoker>conduit.core.CFCInvoker</invoker>
            <serialiser>conduit.reverse.CFReverseSerialiser</serialiser>
            <deserialiser>conduit.core.CFDeserialiser</deserialiser>
        </cfcs>
    </properties>
</destination>


As you can see, we can do almost anything we want to the communication process, simply by extending the core components (or even writing brand new ones) and because its at a low level, its almost completely seamless to those who are writing the ColdFusion and/or Flex code. That being said, its open source, so we can add extra logging and/or debugging as we need.  No more failing silently!

Trying it out

This is still Alpha code, and there is a lot of logging currently in it, but there is enough there for you to start playing.  Code is in SVN, and daily builds are available from the Google Group (saves you having to compile the .jar file).  The documentation is slowly getting fleshed out, but there is enough there to get started.

I am more than happy to get code contributions, and/or ideas for how the to expand on the current ColdFusion remoting feature so send through whatever you have.

I hope you enjoy Conduit!
01 December 2008 08:16 AM 1 Comment

ColdFusion AMF Serialiser inserts 'null' values into a cyclic Object graph... what the?

When writing the Flex <=> Transfer integration, coming across a cyclic object graph is pretty common, as onetomany compositions generate a bi-directional relationship between 2 objects.  I.e. A Parent knows about its children, and children know about their parents.

It is also quite possible for situations to occur, where Object A knows about B, B knows about C, and C knows about A, and therefore having a complete circle.

What confused me no end pretty much all day yesterday, is that when trying to send such an Object data structure up to Flex, theAMF Serialiser, doesn't send it up correctly, instead, it decides to replace one Object value with 'null', in an attempt to break the circle.

To give you an example, I set up a CFC, which had a UUID for identity, and a reference to a child (download the code below to have a look), and an appropriate VO on the Flex side.

I then sent this to Flex, as a cyclic graph of objects, like so:

<cfcomponent output="false">
    <cffunction name="getRecursive" hint="returns a circular CFC structure" access="remote" returntype="flexrecursive.Recursive" output="false">
        <cfscript>
            var a = createObject("component", "flexrecursive.Recursive");
            var b = createObject("component", "flexrecursive.Recursive");
            var c = createObject("component", "flexrecursive.Recursive");

            a.setChild(b);
            b.setChild(c);
            c.setChild(a);

            return a;
        </cfscript>
    </cffunction>
</cfcomponent>

So, like above, A knows about B, B knows about C, and C knows about A.

I then passed this up to Flex, and logged whether or not the children in the collection of Objects was null.

In theory, I should be able to run the following code quite happily, without fear of a NullPointerException:

//rec is the returned objects to Flex
trace(rec.id);
trace(rec.child.id);
trace(rec.child.child.id);
//this should output the same id as the 1st line, as they are the the same object
trace(rec.child.child.child.id);

But what happens when I run my test code is:

* retrieved recursive CFCs, should be 3 items in a recursive graph:
rec.id:
id: F47E1371-C2A7-D498-1F6497AA3F3AEBC8
rec.child.id:
id: F47E1375-A404-D99C-50675EB12C98F9B9
rec.child.child.id:
id: F47E1378-A4AA-57E4-192C2A59D73A9832
rec.child.child.child.id:
This child is null!!!

The Serialiser simply replaces 'null' for the last place in the graph, rather than having a reference to the first Object!

I've run this code through Charles, and have confirmed this is also the structure CF sends in AMF as well.

Looking at the AMF Specification, I read:

'Objects can be sent as a reference to a previously occurring Object by using an index to
the implicit object reference table. Further more, trait information can also be sent as a
reference to a previously occurring set of traits by using an index to the implicit traits
reference table.'


So it should be possibly to handle a cyclic graph of objects, as you could simply insert a reference to a previously serialised object... so what gives ColdFusion? How come this weird and wacky behaviour?

This test was run with ColdFusion 8.01, and Flex 3.2.

If you wish to download my CF and Flex test bed, you can from here.

23 November 2008 06:22 PM 0 Comments

CodexWiki goes open Beta!

For a while now, Luis Majano and I have been working on CodexWiki , a ColdBox , Transfer and ColdSpring powered wiki.

The features in it have come together really nicely, including one of the slickest wiki editors I have ever seen, and it has finally gotten to the point where there was no point in keeping it in private beta any longer.

If you are interested in checking out go to http://www.codexwiki.org , and if you wander over to the ColdBox blog , you can see some great screenshots.

Its been great working with Luis, and we have many more ideas for this wiki in the coming future! Watch out :oD

23 November 2008 01:02 PM 8 Comments

ColdDoc 0.1 Released

ColdDoc 0.1 is finally ready as a release version.

ColdDoc is a port of JavaDoc for ColdFusion, and generates static .html files that display API information for a collection of CFCs.

ColdDoc was initially written to output the API documentation for Transfer, which can be seen here .

The benefits of outputting documentation to static html files, rather than doing it dynamically include:

  • Less processing at run time 
  • Documentation can be linked to, without fear of page names and/or anchors changing
  • The ability to generate API details such as Direct known subclasses and Method Overrides information which would be too expensive to determine at run time.

Currently ColdDoc only supports a single root path, and is missing some JavaDoc implementations, such as a Index page, and Interface documentation, and can only run on ColdFusion 8.

ColdDoc can be downloaded from here .

12 November 2008 10:31 AM 0 Comments

Melbourne CFUG - 20th of November

The last Melbourne CFUG for the year!

Location:
NGA.net, Level 2, 17 Raglan St, South Melbourne
Map: http://link.toolbot.com/google.com/73016

When:
November 20, Meeting starts at 7:00, so get there before hand (doors
open at 6:30).
   
Agenda:
Steve Onnis talks about virtualisation

Steve will be presenting on server virtualisation using VMWare.  VMWare allows you to create
virtual operating systems that run independent of your main operating systems giving you the
flexibility to create development environments for testing.

Demonstrating the setup process and vm tools, you will gain an understanding of what virtualisation
is and an insight into what virtualisation can do for you.

If you are going to attend, please RSVP to mark (dot) mandel (at) gmail.com.

Only those that RSVP are eligible for the door prizes, so make sure you apply!

See the CFUG Melbourne Calendar at:
http://www.cfcentral.com.au/Events/index.cfm

Or add to your Google Calendar - search for 'CFUG Melbourne'.

As per usual, we'll grab pizza during the evening, so we have
something to scoff down!

Look forward to seeing you all there.

09 November 2008 04:33 PM 9 Comments

Transfer Survey, and the Results Are In!

I officially closed the Transfer survey a short time ago, as results had slowed to a crawl.  Overall we had 87 respondents, and it was really, really useful to get the feedback.

I can honestly say the feedback from this survey has changed the road-map for the next two releases of Transfer.

Transfer Experience

This was a really interesting set of questions.  41% of respondents say that they use Transfer every day, which is really exciting. Only 1 person responded with What is Transfer?, which hopefully means I'm doing a decent job of getting at least the name 'Transfer' in people's knowledge sphere.

Most people have been using Transfer for only 1-6 months (30%), while coming second place (26%), 6 months to a year, and third 18% for 1-2 years. Only 2 people have been using it for more than 2 years, but since the project has only been around for 3, and the first year, itwasn't all that stable, I'm very happy with these results.

The version of Transfer that people are using totally shocked me! 73% of people where running either 1.1 (which at the time was RC), or the BER release of Transfer. 36% of people were running 1.0. Only 3 people were running 0.6.3, which is a good thing, as it was a really buggy release.  I'm so pleased to see the adoption rate is so high!

Other ORMs people have used

This was another interesting section, in that Reactor scored the highest at 51%, and Hibernate came in second at 21%.  Interestingly enough, 31% of people had never used an ORM before Transfer.

Transfer Enhancements

Not surprisingly, 58% of people that that Performance improvements were most important.  I wasn't surprised by this, and I expect this won't change no matter how fast I make Transfer.  The annoying thing is being constrained quite severely by how fast ColdFusion can createCFCs, which isn't nearly as fast as I would like.

Several comparisons where made between Hibernate (and other Java/Groovy ORMs) and Transfer, and while it is understood that Java will always be faster, they still want comparative speed out of Transfer.  Not sure how I'm going to get that to happen, but I know I will try my best.

To quote a survey taker: '...the whole thing about not really being able to instantiate collections of associated objects with decent performance - therefore you do your head in constantly switching between object-think and query-think.  This is the #1 reason I'd choose Java over CF for a decent-sized domain layer.'

The fact of the matter is, he is right on what he's saying, and I hope its something that Adobe listens to with future versions of ColdFusion.

Interestingly enough, there were several requests specifically to be able to retrieve arrays of Transfer generated Objects.  I had purposely avoided it due to performance concerns, but I think this may be something that will end up being discussed on the Transfer mailing list further, as there were a few people who were interested in this feature.

Integrated Flex support was another hot topic.  I'm currently in the process of learning Flex at the moment, so expect to hear solutions for this common problem around the corner.

DB introspection was a huge draw card, with multiple comments like '...config file generation without using illudium...' and '...non-generative XML can be burdensome in large applications...', which is all true.  In the next few releases we'll be looking at doing property auto-generation from the database, and also providingDDL support for Transfer to generate your database for you.

Inheritance mapping was also a big feature request (far more so than I had originally ever thought it would be, and this is even before the recent spate of ORM articles), and got me thinking about it a whole lot more.  To that effect, expect to see Inheritance mapping as one of the next big features in the next release of Transfer.

Some other interesting requests that came through were:
  • Annotations in Transfer XML data
  • Railo support
  • Generate methods for setting object properties from a struct
  • Query paging / Query limits
  • Bidirectional M2M compositions.
  • TQL aggregates

Support and Documentation

Support seems to be well received, with 46% of people giving Transfer support a 4, and 30% giving it a 5, where 5 was 'Very useful' and 1 was 'Not Useful'.

That being said, ease of learning could be better, as on a scale of 1 (Easy) to 5 (Really hard), the majority, 43%, sat in the middle at, 3, although 34% gave it a 2.

From reading comments, the big element to help Transfer learning, is examples, examples, and when done, some more examples. Comments include: 'Beginner Tutorials, step-by-step type. Maybe even videos...', 'Lack of tutorial type documentation. Especially for advanced topics.', 'The examples on the site are a bit limited...', 'More examples, and more advanced examples...', so the pathways are pretty clear.  I will be contacting members of the Transfer community and contacting people who participated in the survey to help with this.

Conclusion

I'll be finalising the road-maps for the next 2 releases of Transfer based on this feedback, however, I'm looking at moving to Skweegee from Project Tracker, so once I've made a decision in that area, and how to manage previously completed tickets and milestones, I'll get stuck in.

Thanks to all who participated, it was really useful to get the feedback!
23 October 2008 04:23 AM 7 Comments

Adobe eSeminar tomorrow: Transfer ORM Caching Mechanics

Just a reminder that I'm doing an Adobe eSeminar tomorrow at 2pm on Transfer Caching Mechanisms

One of the most powerful features of Transfer is its highly configurable, in-built caching layer that allows for significant performance gains for a given application when configured correctly.

During this eSeminar we'll discuss caching concepts such as 'caching algorithms' and 'memory sensitive caching', so that as a Transfer Developer, you'll have a better understanding of the intricacies of Transfer.

Click here to register

Click here for World Times

20 October 2008 09:45 AM 3 Comments

Managing Selfish Threads in ColdFusion

As per usual, this is something that came out of my work with Transfer, but is something that applies to any ColdFusion application that exists.

So in the context of ColdFusion, what exactly are we referring to when we say Thread?  Generally the first thing we think of is <cfthread>, which executes some code on its own given Thread.  But, we should also remember that the original page that was executing, is its own Thread as well.  If we run a scheduled task, that is also it's own Thread.

Wikipedia defines a Thread very well:

"A thread in computer science is short for a thread of execution. Threads are a way for a program to split itself into two or more simultaneously (or pseudo-simultaneously) running tasks..."

So when looking at Threads, we can consider:
  • Any Coldfusion page execution,
  • Any remote CFC execution
  • Any Scheduled Task execution
  • Any CFThread execution

To be its own Thread, because, it is!

So what defines a Selfish Thread?

A Selfish Thread is a thread that takes up almost all of the CPU's processing, without allowing any other Thread to be able to utilise the CPU at all.

Some code like this, would be a good example of a Thread being selfish -

<cfscript>
    for(counter = 1; counter <= 10000; counter++)
    {
       writeOutPut(counter & "<br/>");

    }
</cfscript>

It's a very tight loop, and there is no waiting, or pausing, or 'room' for any other processing to do anything else while this loop processes.

Now it should be noted, that a Selfish Thread may not necessarily be a bad thing.  In many instances, we want this loop to completed, without waiting for any other Thread to interrupt it.  But in cases when Thread execution can go on for a long time, this can be highly disruptive to an application, as nothing else can be done during that time.

The common CF solution I often see for this, is the scheduled task that runs at 3:00am, so that it doesn't bother any of the users.  This can work perfectly well for many applications, but what if your application is 24 hours? Or is something that has to run every hour, what do you do then?

Before we get into this too much, I want to make note of something - managing Threads is bit black magic, and a bit trial and error.  Since Threads are managed differently per OS, and there are differences per JVM, some of these techniques will work, and some will not, so make sure you test everything thoroughly so you know that it is affective for your OS and JVM configuration.

The other thing to note, is that any Thread that is running, is an actual instance of th Java object java.lang.Thread.  If at any point and time we want access to the actual Thread object that the given process is running we can run:

currentThread = createObject("java", "java.lang.Thread").currentThread();

Will return a reference to the currently executing Thread object, which will be very handy as we move along.

The first thing we should look at, is <cfthread>.  CFThread has a 'priority' attribute that can be set to 'HIGH', 'NORMAL' or 'LOW', which should  control the level of priority that a Thread has.  For example, a HIGH priority thread should have processing precedence over a LOW priority thread.

For example:

<cfthread action="run" name="foo1" priority="LOW">
<!--- do some processing --->
</cfthread>


In reality, I've not seen this actually do much (in my tests), and it does not seem to actually effect a Thread's Thread.getPriority(), which we will talk about later.  That being said, there may be some other mechanism under the hood, and its not going to hurt anything if you choose to use it.

From here, we can look at setting a Threads priority, which can be applied to any CF based Thread (i.e. pages, scheduled tasks, cfthread etc).  A Threads priority goes from 1 to 10, where 1 is the lowest priority, and 10 is the highest.  5 is usually considered 'Normal'.

In theory, a lower priority Thread should give way to a high priority Thread whenever the higher priority Thread requires CPU processing time.  As stated earlier, depending onJVM and OS, this may, or may not happen.

To set the Thread's priority, all you need to do is grab the current thread, like we did above and call:

currentThread.setPriority(2); //set it to a lower priority.
//do some processing...

Since ColdFusion tends to pool Thread (i.e. stores them for reuse), we should reset the Thread's priority after we are done with it, so that it doesn't stay that when it gets used to execute another piece of code. e.g.

priority = currentThread.getPriority();

currentThread.setPriority(2); //set it to a lower priority.

//do some expensive, long running processing...

currentThread.setPriority(priority); //reset it

This way, when the Thread get re-used, the Priority is not set to something that is inappropriate for the processing it is doing.

There are also mechanisms in Java that allow you tell the JVM when a good time is for the current thread to yield to other threads that need to do some processing.

This simply hints to the JVM that 'hey! now would be a really good time for me to pause for a second, if you wanted to do something else'.  The JVM can totally ignore this if it chooses, and depending on OS and JVM, it may well do.

To do this, we call the static method yield(), on java.lang.Thread, like so:

createObject("java", "java.lang.Thread").yield();

So we can now take our very selfish loop above, and do something similar to:

<cfscript>
    for(counter = 1; counter <= 10000; counter++)
    {
       writeOutPut(counter & "<br/>");
       createObject("java", "java.lang.Thread").yield(); //here is a good place to pause
    }
</cfscript>


This is actually a very poor use of yield(), simply because in a display, we would never want the server to pause when displaying some data, but it displays how it works reasonably well.

The interesting thing is, yield() automatically resolves what the current thread it is processing on, and works that way, rather than the setPriority() method we saw above, which required us to use a specific Thread.

Quite probably the least useful, but the most consistent way of managing selfish threads, is by putting the thread to sleep, which will allow other Threads access to the CPU while that thread is asleep.

This is the least useful, as no matter what, the Thread will pause.  Nothing else may be happening on the server, but the Thread will pause anyway, which can mean wasted cycles for whatever it is you are doing.

That being said, this will always work, no matter what JVM or OS you are on, so there is a trade off.

There are three ways we can make the current thread sleep in ColdFusion,

In cfscript:

<cfscript>
    sleep(1000);
</cfscript>


via a Tag

<cfthread action="sleep" duration="1000" />

And via Java,

currentThread = createObject("java", "java.lang.Thread").currentThread();
currentThread.sleep(1000);

Either way, in the above example, the current thread will pause for 1000 milliseconds.

In a real world example, there is no reason we can't combine these techniques.  If we had some processing we wanted to happen asynchronously, but we knew it was going to take a while to complete, we could do something like the following:

<cfthread action="run" name="foo1" priority="LOW">
    c
urrentThread = createObject("java", "java.lang.Thread").currentThread();

    priority = currentThread.getPriority();

    currentThread.setPriority(3); //set it to a lower priority.

    for(counter = 1; counter <= 10000; counter++)
    {
       doSomethingExpensive();
       createObject("java", "java.lang.Thread").yield(); //could pause here
    }

    currentThread.setPriority(priority); //reset it
</cfthread>


Which gives us multiple ways in which to tell Java to make sure that other Threads are able to access the CPU.

Next time you are looking at a long running, expensive process, you now have multiple options about how you want to manage it.

17 October 2008 06:17 AM 2 Comments

Transfer 1.1 Final Released

After a few minor delays, Transfer 1.1 Final is ready for final release.

A few bugs and fixes occured during the release candidate period, so make sure you upgrade to the final release if you are running the release candidate.

For those of you not familiar with the new features of 1.1, some of the highlights of 1.1 are:

Huge Performance Enhancements!

During Testing (on my machine), a 500 Object load has been reduced from an average of 8 seconds down to an average of 6 seconds.   This is a speed increase of around 25%!.  I've even seen Object loads of 500 objects as small at 2 seconds.

Even for the performance alone, it is worth upgrading!

Transfer Object Proxies

This of this like Lazy Loading, but on steroids!

With a simple new setting 'proxied' on onetomany, manytoone and manytomany elements like so:

<onetomany lazy="true" proxied="true">
...
<onetomany>

Objects in the collection will be loaded as Proxies of the real object, and their underlying data will be loaded on an individual basis upon request.

A very handy feature when dealing with large collections.

New Discard Algorithm

Before, if you had a configuration when A -manytoone->B, and B was discarded from the cache, both A and B would have been discarded.

Now in the new algorithm, if B gets discarded, A simply unloads its many to one, and stays resident in the cache.  This ensures there is less unnecessary too-and-fro between the database and Transfer's cache.

Cache Monitoring and Reporting

While there is a new CachMonitor component that allows you to get fine grained reporting on what the cache is doing, to get a re-built cache report, it is as simple as:

<cfimport prefix="report" taglib="/transfer/tags/reports">
<---  Basic Report --->
<report:cacheReport monitor="#application.transferFactory.getTransfer().getCacheMonitor()#">

<---  Detailed Report --->
<report:cacheReport monitor="#application.transferFactory.getTransfer().getCacheMonitor()#" mode="detail" chartsize="300">

TQL Custom Tags

Big thanks to Elliot Sprehn for contributing these TQL custom tags, that make it super easy to do TQL queries, in a <cfquery> style!

For example:

<cfimport prefix="t" taglib="/transfer/tags">

<---  Do list operations --->
<t:query name="result" transfer="#getTransfer()#">
        select
                u.firstName, u.lastName
        from
                user.User as u
        where
                u.email like <t:queryparam value="%example.com" type="string">
</t:query>

<---  Do read operations --->
<---  Get a single record as a TransferObject --->
<t:query name="user" action="read" class="user.User" transfer="#getTransfer()#">
        from
                user.User as u
        where
                u.email = <t:queryparam value="user@foo.com" type="string">
</t:query>

Lots of bug fixes

The usual slew of bug fixes, improvements, and other various adjustments.

If you want more information on what got included in this release, and why to upgrade, I would highly recommend the 'What's new in Transfer 1.0 (and 1.1) ' presentation recordings, and also make sure you check out the Release Notes .

Transfer 1.1 download .

13 October 2008 08:27 AM 0 Comments

Transfer Survey, now open!

I've put together a short Google Forms survey on Transfer to get some consolidated feedback from the community at large on what people are doing with Transfer, what features they want in the future, and what can be done to improve it overall.

It isn't limited to just people who are using Transfer.  If you are not, I also want to hear your reasons why, as hopefully it is something that can be improved upon in the future.

It shouldn't take you much longer than around fifteen minutes to complete, and I would really appreciate the feedback.

Transfer Survey

 

08 October 2008 10:11 AM 2 Comments

Melbourne CFUG - 16th of October

All,

This Month's CFUG is lined up!

Location:
NGA.net, Level 2, 17 Raglan St, South Melbourne
Map: http://link.toolbot.com/google.com/73016

When:
16th of October, Meeting starts at 7:00, so get there before hand (doors
open at 6:30).

Agenda:
Recorded Presentation by Dan Wilson

Refactoring in ColdFusion

If you would like to know how to migrate an existing procedurally programmed application into an object oriented one, grab a chair and sit for a while. We'll discuss some sensible guidelines designed to help you make incremental changes towards OO nirvana. We'll also look at lots of code samples, we all like code samples, right?

If you are going to attend, please RSVP to mark (dot) mandel (at) gmail.com.

Only those that RSVP are eligible for the door prizes, so make sure you apply!

See the CFUG Melbourne Calendar at:
http://www.cfcentral.com.au/Events/index.cfm

Or add to your Google Calendar - search for 'CFUG Melbourne'.

As per usual, we'll grab pizza during the evening, so we have
something to scoff down!

Look forward to seeing you all there.
04 October 2008 12:10 PM 0 Comments

Not been blogging much, where have I been?

I came to the realisation the other day, that my blog has really become almost totally announcement based.  A series of presentation announcements, eSeminars, ColdFusion User Groups, Code Releases and various other 'hey! this is what is going on' posts.

It used to be chock full of weird and interesting things you could do with ColdFusion, and combining with the Java layer that sits underneath it to do even weirder and even more interesting things with that.  Sadly, I've been super busy over the past <insert long time frame>, and I've let things slip.

That being said, I plan on returning to the original theme of this blog, and start publishing some of the new things I've found out about ColdFusion, and what can be done with it.  I've got some interesting ideas on article on ColdFusion and Threading, and also some more on onMissingMethod and method injection and manipulation, so be prepared!

So what has kept me so busy? Quite a lot actually. In no particular order...

Consulting full time.
This has been one of the biggest changes, and adjustments for me to make over the past 6 months or so.  That being said, it is going very well, and I am keeping myself very busy (Almost too busy!).  I love working from home, and love the flexibility working for myself gives me.

I also find it is a really rewarding experience. Working for yourself challenges you in a variety of ways, as you only have yourself to rely on, and you are solely responsible to make it or break it.

While mostly I've been doing Transfer related work, I've also been doing some mentoring and memory leak analysis, all of which have been really interesting.  Coming from a background in which I have tended to work on single projects for months/years at a time, having a variety of undertakings going at once is a nice change.

Speaking at webDU
I didn't even blog about this, which was very remiss of me!  But I went to webDU, which was great fun.  I gave a presentation on TQL, and although I had some projector issues, it seemed to go quite well.

Writing Transfer code
I also got very busy writing Transfer 1.2 in my spare (?) time.  I'm really getting excited about Transfer all over again, and I think I have some really interesting ideas for the future. The next version is almost mapped out in my head... but I will wait until after the Transfer Survey before setting it in stone.

Writing DevNet Frameworks Article
Writing articles always take far longer than you expect them to, but when they finally get published, it feels really great.  From the feedback I've received the Introduction to ColdFusion Frameworks has been well received, and given some people new to frameworks some perspective over the landscape.

Something Super Cool Special
Been spending some time doing something really, really cool, but I can't really talk about it yet...

Don't you hate it when people say that? ;o)

Technical Editing for FAQU
I've also started technical editing for the Fusion Authority Quarterly Update, which one was one of those random opportunities that show up during a conversation I was having with Judith Dinowitz.  Editing other people's articles in an interesting endeavour, but (I find) much easier than writing them in the first place ;o)

Went on Holiday
I actually hadn't had a proper holiday in several years, and it has made a huge difference!  Taking a solid break for a few weeks has meant I've come back with a new passion for writing code, and a variety of other things in my life.  I always forget how much change a holiday can bring.
So that's my life at the moment in a nut shell.  Figured I would let people know what was going on.

An introduction to ColdFusion frameworks - now on Adobe Devnet!

I'm feeling pretty excited, because my first article for Adobe DevNet has finally been published.

An introduction to ColdFusion frameworks

It covers the differences between Model-View-Controller, Dependency Injection, and Persistence frameworks, and also gives a general overview of some of the most popular offerings that are available in ColdFusion right now.

There was a bit of a rush towards the end, and some pieces of it are not as perfect as I would have liked, but I hope that it serves as a way for people to enter into the ColdFusion framework world, gives them enough information so that they understand the differences between framework types, and also allow them to make an informed decision on which one to use based on their personal preferences and needs.

18 September 2008 01:55 PM 0 Comments

CFMEETUP: What's New in Transfer 1.0 (and 1.1)? - Tomorrow!

I'm doing a repeat of the What's new in Transfer 1.0 (and 1.1) Talk at cfmeetup.com tomorrow!

WHEN

Thursday, September 18, 6:00pm US EDT (UTC/GMT-4) (What time is that for you? See http://www.timeanddat... which shows the time as US EDT and you can choose your city from the list offered to see what time that is in your own timezone.)

AGENDA

After a long wait, the Transfer 1.0 release is finally here! This release comes bundled with lots of brand new features, bug fixes and performance improvements.

This presentation will give you a good overview of new functionality the 1.0 release brings to your developer tool kit, providing you with even more ways to implement your ColdFusion applications faster than ever before.

We will also have a sneak peak at some of the 1.1 features, that are currently in release candidate 2.

In case you missed the first talk, you can now catch it again!

23 August 2008 04:25 PM 0 Comments

Transfer 1.1 Release Candidate 2

Release Candidate 2 of Transfer 1.1 is now available for download.

It has several critical bug fixes from the previous Release Candidate.

While I did promise several blog posts about the new features, I simply haven't had time, as I'm been incredibly busy with client work, and working on Transfer.

That being said, the documentation for all the new features has been written in the wiki, and you can also view the latest presentation recording that I did, which covers many of the new features found in Transfer 1.1.

Transfer 1.1 Release Candidate 2 can be downloaded from here.
22 August 2008 06:57 AM 0 Comments

eSeminar Recording: What's new in Transfer 1.0 (and 1.1?)

Just to let you guys know, the recording for the recent eSeminar, What's new in Transfer 1.0 (and 1.1) is available .

You will also find the code examples available to download along with it.

It was a fun presentation to do, so I hope you enjoy it.

21 August 2008 07:02 AM 0 Comments

TransferSync for Transfer Clustering

Tom de Manincor Released yesterday TransferSync , a nice tool that works with Transfer to enable it to be used across a cluster of servers, and maintain its cache.

It's really a nice little piece of software, a huge thanks goes out to Tom for putting this together.  He's expanded on some of the ideas that Sean Corfield had in his original clustering implementation,  and has expanded them nicely.

For more details on TransferSync, check out Tom's blog posts !

18 August 2008 12:15 PM 0 Comments

Melbourne CFUG - 21st of August

Sorry about the late blog post on this! I just realised I hadn't put one up!

Location:
NGA.net, Level 2, 17 Raglan St, South Melbourne
Map:  http://link.toolbot.com/google.com/73016

When:
21st of August, Meeting starts at 7:00, so get there before hand (doors open
at 6:30).

Agenda:
Dale Fraser

Dale Fraser is the Chief Technical Officer at CogState Limited. Working on
varied projects using ColdFusion, Flex and C++, CogState develop Cognitive
Testing Software use mostly in Clinical Trials.

Report Builder (The Hidden Gem)

People may or may not realise that a report builder is included with
ColdFusion since version 7. Along with this report design tool, comes some
additional ColdFusion tags to allow you to incorporate full featured
reporting into your application without additional expense. While Report
Builder is not as rich featured as Crystal Reports or similar, it provides
all the necessary components to create reports, and being part of ColdFusion
the code and syntax used within reports is ColdFusion code that will
familiar to you all.

So if you either don't know about the Report Builder or have never has a
chance to play with it, this introduction will get you started. Things
covered will include

1.    Designing a Report (No Code)

2.    General Reporting Concepts, grouping, totalling etc.

3.    Passing a Query into a Report

4.    Generating a Report silently to a PDF

5.    Printing a Report silently to a local printer.

If you are going to attend, please RSVP to mark (dot) mandel (at) gmail
(dot) com.

Only those that RSVP are eligible for the door prizes, so make sure you
apply!

Or add to your Google Calendar - search for 'CFUG Melbourne'.

As per usual, we'll grab pizza during the evening, so we have something to
scoff down!

Look forward to seeing you all there.

14 August 2008 05:27 AM 1 Comment

eSeminar Tomorrow!: What's new in Transfer 1.0 (and 1.1?)

I'm going to be presenting 'What's new in Transfer 1.0' in Adobe's continuing eSeminar series.

Agenda:
Transfer 1.0 is finally here! This release comes bundled with lots of brand new features, bug fixes and performance improvements. In this eSeminar we'll introduce you to the new Transfer functions and provide more ways to implement ColdFusion applications faster than ever before.

We may also look at the new features that are in 1.1 at the same time as well.

Time and Date:
Melbourne, Australia: 2pm, Friday 15th August
USA - PST: 9pm, Thursday 14th of August
USA - EST: 12am, Thursday/Friday, 14th of August
London, UK: 5am, Friday 15th of August

For more times in your timezone, see: http://snipurl.com/3fk87

To register, go to:
http://www.adobeeseminars.com.au/events/register/18103633

Look forward to seeing you guys!
 

04 August 2008 10:52 PM 0 Comments

Transfer 1.1 Release Candidate

Transfer 1.1 Release Candidate

Hot on the heals of Transfer 1.0, is Transfer 1.1, now with added sugar and spice, and all things nice! :oD

This release has been squarely aimed at large Transfer based systems, in order to give them more control over the caching layer, and provide more performance overall.  (Which is not to say this isn't a release for everyone else as well, because there are lots of good things to share all around).

I'm not going to go into huge detail on each of the new features, but instead will be running a series of blog posts, highlighting each of the new main features and how you would use them over the next coming week or so.

The documentation is still mostly forthcoming (have to get that paying work finished!), but expect it to show up on the wiki in the next few days.  If you want a head start, most of the tickets linked in the release notes have a link to the relevant google group post, or the usage details can be found in the tickets themselves.

To give you a taste, of some of the really interesting new features:
  • A performance upgrade of at least 25% in object loading!
  • Introspection and statistics for the caching layer
  • A new cache discard algorithm, that allows granular control over the cache
  • New cache time-out settings
  • The ability to load manytoone, onetomany and manytomany collections as TransferObject Proxies, giving you a way to manage large object collections.
  • Custom tags for TQL (Big Thanks to Elliot Sprehn!)
  • Plus more!
You can read about all the details on these features in the release notes.

Happy Downloading!
07 July 2008 08:25 AM 11 Comments

How do you test CFML against multiple versions of ColdFusion?

'How do I run ColdFusion 8 and 7 side by side on IIS?' or 'How can I run Railo and Adobe ColdFusion side by side, so I can share the same code base?', is a question I see quite regularly on CF lists.

I figured I would write up a blog post about how I go about solving this problem, since I do this a lot with my Transfer development.

The quick answer is - I don't.  Trying to set up two different Application servers (CF7 vs CF8) on the same Web Server (IIS or Apache), is not something I desire to tackle, and seems way more convoluted than I care to trouble myself with.

The problem is usually broken down into:

  • How do I test the same code on different versions of CF?
  • How do I do so without having to move/sync files between machines?
  • How do I set it up so it is easy to switch between versions of testing?

I solve each of these problems with Virtual Machines , and Shared Folders.

I have actually bought VMware's Workstation product, and I use it every day, but there are several free products out there that will do virtualisation for free.

First thing first, where does my actual CFML code sit? This sits on my primary machine, commonly referred to as the host machine, in VM speak.  This is because the host has guest machines, namely of the Virtual Machine variety.

This means my CFML code is always available if I want to get my hands on it, and I can open it in Eclipse on my host machine as well, so I do all my editing and development with tools on my host machine.

I also do this because I can then share this code between virtual machines, using a mechanism called Shared folders.

So, now that I have my ColdFusion code, I create myself a new virtual machine.  In my case, I use Ubuntu Server, because its lightweight, and I can get one up and running in about half an hour, but you could use XP, or anything that runs CF.

I then configure my virtual machine to share my host folder which contains my CFML, which is a setting I am able to configure within VMWare. This then becomes accessible at /mnt/hgfs/wwwroot in my Ubuntu server on my VM.

From here, I can now install ColdFusion 8 on this VM, and point it to /mnt/hgfs/wwwroot folder to serve cfml from.

I can then create extra virtual machines, one for each version of ColdFusion that I need.

When I need to test against a version of ColdFusion, all I need to do is start up the virtual machine in question, and browse to it.  To switch versions of ColdFusion, I simply power the current one down, and start up another one.

I find this a much easier way to test the same code base between different versions of ColdFusion than trying to run them side by side.

03 July 2008 11:59 AM 0 Comments

Melbourne CFUG - 17th of July

We're back to regular CFUG's, after the break for WebDU, and I think we have a pretty interesting presentation lined up!

Location:
NGA.net, Level 2, 17 Raglan St, South Melbourne
Map: http://link.toolbot.com/google.com/73016

When:
17th of July, Meeting starts at 7:00, so get there before hand (doors open at 6:30).

Agenda:
Elliott Sprehn

Elliott is a software engineer at TeraTech, Inc. and the lead developer for the Conferences department. He has worked on a variety
of projects that include network services, realtime messaging systems, survey processors and most commonly web applications. As a strong advocate of web standards and accessibility he volunteers his free time to help new developers learn standards and best practices. He is also proponent of design patterns and draws his vision about application design from experience with many languages that include ColdFusion, Java, ruby and php.

Internals of the Adobe ColdFusion Server
To many CF developers the ColdFusion server is a block box that just works. This presentation takes a look at how the internals of the engine operate. The presentation covers how variables, scopes, functions, cfcs, custom tags, includes and java objects are implemented and how we can use this knowledge to do things not normally possible with the CF functions.


We'll look at how to implement several features in CF6, CF7 and CF8 like:
- Query Caching with the native CF query cache for queries that use
cfqueryparam.
- Create and execute queries that use cfqueryparam from cfscript.
- Create a function like CF8 to get database info for a datasource.
- Add global mappings by appending to a structure like this.mappings in CF8.
- Call functions and component methods and inspect the local scope
after their execution.
- Access the Application.cfc anywhere in an application.
- Allow passing arrays of values in the url scope instead of lists
when there are duplicate keys.

If you are going to attend, please RSVP to mark (dot) mandel (at) gmail (dot) com.

Only those that RSVP are eligible for the door prizes, so make sure you apply!

See the CFUG Melbourne Calendar at:
http://www.cfcentral.com.au/Events/index.cfm

Or add to your Google Calendar - search for 'CFUG Melbourne'.

As per usual, we'll grab pizza during the evening, so we have something to scoff down!

Look forward to seeing you all there.
19 June 2008 05:19 AM 16 Comments

ColdFusion 9 + Hibernate == Transfer Killer?

So I figured I better head this off at the pass, because I'm already getting questions in my inbox about whether this is the end of the road with Transfer , and what I plan to do with it, and OMGZ! TRANSFER IZ DEADZ!!!.

Let it be known, it couldn't be farther from the truth.

Transfer is not dead, development will still continue way into the future, and I can see a healthy life-cycle for its continuance.

A few points for your consideration:

  1. ColdFusion 9 is not even here yet.  Nobody even knows the exact date it will be shipped.  You want ORM? You can have it right now with Transfer! No waiting around, no fussing.  The documentation is written, the example applications are there, and you already have a large community to integrate with. 
  2. Hibernate integration may not even be implemented with ColdFusion 9.  Yes, we've seen some short demo's, but we've seen demo's of functionality in pre-release at keynotes before, and they didn't make it into production before.  Hibernate and ORM is a pretty complex beast, and especially tying that into CFCs, so any number of things could make it ship late, or not at all.
  3. ColdFusion 9 will cost you $$$ to upgrade.  So you're not getting all this for free.  Transfer can be used right now for $0, and will always be $0.  It is only then up to you whether you want to pay for support, or training, consulting or even new features!
  4. The Transfer release cycle will always be faster than ColdFusion's.  If there is a feature you want in CF's ORM support, you'll have to wait ~18 months.  The Transfer release cycle is around the several month mark, and with the sponsored development program, the features you want in your ORM support can generally be developed in the same week you request them in, in fact the last sponsored development I completed I did in 6 hours! (Yet to be blogged, although in SVN).
  5. We don't know how well the ORM integration in ColdFusion 9 will be developed.  While I love the hard work that Adobe does, we can all remember Flash Forms.  Lots of Shiney, not very useful (maybe that was too low a blow? ;) ).  My point is, there is no point in putting the nail in the coffin until we really know what we are dealing with.
  6. There are plenty of businesses and projects out there using Transfer already, and there is no reason they would suddenly stop using it, and switch (although that is a possibility).  As long as people keep using Transfer, I will keep developing it.
  7. Transfer is a proven technology that has undergone a lot of rigorous testing.  While Hibernate can say the same, we have yet to see how the ColdFusion and CFC integration will perform.
  8. There is no reason why Transfer can't take advantage of some of the ORM integration tools.  For example, if a CFC annotation structure is setup for use with Hibernate, there is no reason Transfer couldn't use the same annotations, so using one tool or another is quite seamless.
  9. All in all, competition is a good thing.  Having competition forces everyone involved to strive to become best in breed.  So this will actually be a good thing, both for Transfer and for ColdFusion.

I don't want to be showering doubt over the ColdFusion 9 integration with Hibernate, it makes sense for them to do it, and I can completely see where it is coming from, and there are a lot of smart people behind it.  But, there is still a lot of unknown factors here, and a lot of reasons to still use Transfer, so don't feel like the project, or the business is going to die, because its not.

I'm really excited by some of the announcements I've been seeing with ColdFusion 9, including the ORM integration, and I think the next few years will be an exciting time for the ColdFusion community.

10 June 2008 05:43 AM 0 Comments

CFMeetup Transfer Introduction Recording

This is just to post a link to the recording of the session of Introduction to Building Applications with Transfer ORM that I did recently on cfmeetup!

To view the recording, you can go here .

This one should hopefully not have the sync issues the previous one did.

08 June 2008 12:20 PM 5 Comments

Transfer 1.0 Goes Gold!

Today is the day in which Transfer finally hits its stable, final, and complete 1.0 status.

The release candidate phase is finally over, and it showed up some critical bugs, which have since been fixed.

Things are moving along speedily, with the recent completion of the support contracts, and sponsored development programs.

I just finished writing a day's training program for webDU, which will soon to be available both on-site, and via Connect.

On the next to-do list, is the rebuilding of the Transfer and Compound Theory websites, with alerts for events, training, and a whole lot more!

I'd like to extend a huge thank you to the community that surrounds Transfer, you guys are fantastic, and without you there is no way Transfer could be where it is now.

Keep expecting good things from Transfer!

You can download the 1.0 Release from here.

For more details, check out the Release Notes.
05 June 2008 03:10 AM 1 Comment

Transfer Presentation Tomorrow on Meetup.com

Tomorrow, I will be presenting my Introduction to Building Applications with Transfer ORM presentation, that I gave at cf.Objective() on coldfusion.meetup.com.

This will happen at:

USA EST:  Thursday, June 5, 2008 at 6:00 PM

USA PST:  Thursday, June 5, 2008 at 3:00 PM

Australia: Friday, June 6, 2008 at 8:00 AM

London: Thursday, June 5, 2008 at 11:00 PM

More details can be found at: http://coldfusion.meetup.com/17/calendar/8035918/

See you all there!

22 May 2008 03:34 PM 4 Comments

Transfer Support Contracts and Sponsored Feature Development

Announcing two new developments for the Professional Open Source Software side of Transfer.

Compound Theory is now offering the following new programs:

Transfer Support Contracts

The basic yearly support package provides you with 20 hours of support, covering:
  • Installation
  • Usage
  • Performance
  • Bug Fixes
Contact through several different channels, including:
  • Email
  • Skype
  • Instant Messenger
Extra support hours can be purchased at any time, and rolled over into subsequent years if required.

Sponsored Feature Development

If there is a feature that has yet to be developed for Transfer that your project could really use, either from the extensive enhancement ticket list, or something that you have thought of, it is possible to sponsor its development.

Full or partial sponsorship is available, and will give the feature you desire priority in its development, and/or the ability to specify the schedule it needs to be developed in.

If you are interested in either of these programs, or want more details, please feel free to contact me for more details through the contact form, mark [at] compoundtheory [dot] com, or through Skype through the account mark_mandel.
19 May 2008 11:49 AM 0 Comments

Transfer 1.0 Release Candidate 2

There have been several bug fixes and performance and memory usage improvements since the initial Release Candidate, so here I present to you Release Candidate 2!

Transfer 1.0 Final is slated for the 8th of June, just a few days before webDU is going to start!

webDU 2008
In case people haven't realised yet, but there will be a full day's training for Transfer at webDU, in which we're going to do a lot of hands on coding, so you can get a really good understanding of the Transfer framework.

The Transfer support contracts I blogged previously should be ready this week, we're just finalising some final details, so please contact me, if you have any interest in this area.

Also, just a quick reminder that Transfer based consulting services are also available right now, so feel free to contact me if you have any needs.

The Transfer 1.0 Release Candidate 2 can be download from here.

Release notes can be found here .


15 May 2008 04:59 AM 5 Comments

JavaLoader 0.6 Released

Not a huge amount to report. This release simply re-orders some of the class loading, so it is child first.

This is important in case you load up a newer (or older) version of a library that ColdFusion already has access to, and you want to make sure you get the library you want, not the library loaded by ColdFusion.

That and I fixed a bug in the JavaProxy.cfc that was sent to me a loooong time ago, that will fix an issue with resolving overloaded Java Methods.

JavaLoader can be downloaded from here.
10 May 2008 07:27 AM 0 Comments

Melbourne CFUG - 15th of May

All,

Another CFUG on the way!

(Apologies for the delay in getting this out, I was in the US!)

Location:

NGA.net, Level 2, 17 Raglan St, South Melbourne
Map: http://link.toolbot.com/google.com/73016

When:
15th of May, Meeting starts at 7:00, so get there before hand (doors open at 6:30).

Agenda:

Richard Herbert, CTO of NGA.NET, Australia's leading e-recruitment company, has been working with ColdFusion since 1997 and version 2.0. With a background in the legal and training industries Richard has developed applications for retail, point of sale, aviation, training, manufacturing, government and of course the HR industry. Also Telstra (but who hasn't?)...

Since 2000 Richard has been building NGA.NET's e-recruitment product and delivering solutions to Top 500 companies and federal government, where NGA.NET have 100% market share.  The application has gone through many evolutionary steps, with a brand new version built on mach-ii/ColdSpring/Transfer architecture in beta for 2008. NGA.NET is in the BRW Fast 100 for 2008 - a list of Australia's top 100 fastest growing companies.

And the presentation...

...will be titled 'Usability for Developers - The Ugly Truth'. I will be seeking to provide the audience with an understanding of what the field of usability covers, how to apply usability methods during the development cycle and the surprising results you can achieve.

Depending on time, Mark Mandel will also take us through some of the CF9 discussion that occurred at the cf.Objective() conference, and give us some insight into what could possibly be coming in CF9.

If you are going to attend, please RSVP to mark -dot- mandel -at- gmail -dot- com.

Only those that RSVP are eligible for the door prizes, so make sure you apply!

See the CFUG Melbourne Calendar at:
http://www.cfcentral.com.au/Events/index.cfm

Or add to your Google Calendar - search for 'CFUG Melbourne'.

As per usual, we'll grab pizza during the evening, so we have something to scoff down!

Look forward to seeing you all there.

cf.Objective(), a review from Down Under

Okay, forgive me one Australia joke ;o).

cf.Objective() was an absolutley fanstastic conference all around, and I had an incredible time.  Not only were the presentations top notch, but it's always an incredible pleasure to meet up with the people that I only tend to see once a year, and I always get a huge burst of inspriation just being around clever people and sharing various ideas over a drink or two.

Presentations

I'm not going to go into all of the presentations, but as per usual, they were all of an incredibly high calibre, and I came out of all of them learning something new.

Highlights of the conference for me were:

Model-Glue 3: Back to its Roots - Joe Rinehart
This was a really interesting presentation, to see what MG3, code named Gesture, had in store for its users.  I really like the innovative approach Joe has taken to enable to framework to generate itself as you develop with it.

Selling Professional Development at a Hostile Shop - Terrence Ryan
I now refer to Terrence as 'the master manipulator' ;o).  He outlined a series of personality types that can often occur when working in an organisation that tends to lean against the utilisation of software development practices such as frameworks, unit testing, or version control, and how to encourage them to accept, and even appreciate, these practices when previously they had shunned them.

His use of images to illustrate each of his points was also particularly clever, I never knew that a photo of Bea Arthur wrestling a velociraptor could ever have any sort of context!

Workshop: ColdSpring 1337 - Chris Scott
Honestly, this was probably my favourite session at cf.Objective().  Chris went through some really interesting way you can use AbstractFactories and AOP to really push what is possible to do within ColdSpring.  He used a Flex / ColdSpring / Transfer/ Yahoo Maps mash-up to show this off, incorporating some nice Transfer powered Flex Remoting, implemented with some very nice ColdSpring Remote Proxy AOP work (Before people ask, yes, this will be finished off and released at some point)

Finally, Chris showed off his new Flex framework, Swiz, and while I don't even do much (any?) Flex development, I looked at and just went 'Well, that is a pretty sweet framework'.  I'm looking to do some Flex work in the near future, and I can see me really getting into Swiz.

Workshop: Advanced Techniques with the ColdBox Framework - Luis Majano
While I didn't attend most of this presentation (I think I was balled up on a couch somewhere trying not to drop off to sleep), I dropped in at the end, so that Luis and I could do a quick announcement of the CodexWiki Open Source Wiki, which is currently powering docs.transfer-orm.com.  We are opening a private beta for Codex, before we do a full release. If you are interested in being involved, feel free to drop me an email.

Transfer

One of my favourite things about the conference was running around giving lots of people Transfer stickers.  It gave me a wonderful opportunity to talk to lots of people about Transfer, and I think I actually managed to get it so that about one in every third person had a Transfer sticker on their laptops (Statistics based on no real analysis)! I passed on a stack of stickers to a few people, so if you weren't fortunate to get any at cf.Objective(), or couldn't attend, you may find some people around who still have some to hand out.

I also did two presentations on Transfer, one of of which was a repeat.  While the first time I presented Introduction to Build Applications with Transfer ORM, didn't quite go according to plan (technical difficulties), people still seemed to get a lot out of it, which I was very happy about.  The Transfer ORM Caching Mechanics and the repeat of the Introduction talk went far more smoothly, and got good reviews from the people that I talked to, which is very pleasing.

ColdFusion 9

The ColdFusion 9 keynote, and BOF was another highlight of the conference for me, although, I must admit, I didn't hear any feature requests that really surprised me.

Adobe is further opening up the ColdFusion development process, promising us a Open Bug Tracker, and setting up an Advisory Committee, which is fantastic.

We got a hinting at a ECMAScript (style?) syntax for ColdFusion components, which I know is something that people, myself included, have wanted to a long time.  From that, there seemed to be a big push to be able to write AS3 on the server side.  Considering that a lot of new CF developers seem to be coming from Flex, I think this would be a really smart move on Adobe's part.  Not only does it streamline the training process for Adobe based Rich Internet Applications, it provides a solid, single language for Adobe products, which can then only be expanded.

That being said, it would be very important that the CFML language also be kept intact, both for backward compatibility, and for the fact that a tag based syntax just makes so much sense on the view layer. (Oh, and let's not forget, some people just like writing CFML ;o) )

People

One of the biggest draw cards for cf.Objective() is the people you get to hang out with.  For me personally, it's the only chance I get per year for me to actually see a lot of the people that I speak to day in, day out on-line.

It also gave me a chance to meet and talk to some of the people I've worked remotely with as well, specifically, the Dinowitzs, who run the great Fusion Authority Quarterly Update, and the really cool Alagad crew. 

Let's also not forget that I won the Wii, which was a big surprise!  It was very amusing watching multiple people try and convince me how it wouldn't work in Australia, and that I should just give it to them, because really 'I didn't need it' ;o).  Let it be known, that a new power cable is on its way in the post, and soon theWii will be up and running smoothly.

Oh yeah.. and I don't care what you lot say, it's cay-shing, not caaashing. ;o)  See you all next year!
28 April 2008 05:30 AM 0 Comments

Transfer 1.0 Release Candidate - Out Now!

Wow.  When I started this project back in 2005 I had no idea it would blossom into what it is now, or that it would take me 3 full years to turn it into an actual 1.0 release.

It's been a crazy, interesting, frustrating and incredibly rewarding ride, and I plan on continuing it well into the future.

So here I present to you the release candidate of Transfer 1.0, ready for your download and consumption !

Some of the major new features include:
  • Composite Key Support
  • Transaction Support
  • Binary Data support
  • Configuration includes
  • Cascading operations e.g. cascadeSave(), cascadeDelete()
  • A huge number of performance improvements
  • Public Bug Tracker
  • Public Wiki

Please see the full release notes for more information.

I want to extend a big thanks to all those people who have helped out with Transfer, with code, testing, documentation, or just giving your ear as I try and work out a n-th level nested recursive threading issue, you all are too many to mention, but you know who you are, and you guys rock!

I'm really happy with the way the Transfer community has grown over the past few years, recently passing 320 members, and big kudos to you all for helping me bring Transfer to this 1.0.

In the coming months, the following is the plan for Transfer -

  1. Transfer Support finalised and advertised. 
    The details of this have been worked out, expect a blog post on this either during, or shortly after cf.Objective() 
  2. Infrastructure
    You will notice there is the new Wiki and Bug Tracker.  There will be a complete rebuild of the Transfer site, to integrate the wiki and the tracker, and provide the community with more ways to learn and interact.
  3. Transfer Training
    This is the next big thing for Transfer, and I will be starting to write the curriculum after I get back from cf.Objective()
  4. Transfer Survey
    Expect to a see a survey in the upcoming months, to get a feeling for how the community is using Transfer, and what sort of enhancements they want for the future.
  5. Transfer 1.1
    Yep, I've already started thinking about a 1.1 release! I think I also know what new features will be in it, but I won't ruin the surprise.
  6. Transfer Developer and Training Certification
    I've had some recent interest in this, and it is still on the roadmap.  Once the training curriculem is finalised, this will be also be developed.

Hopefully that will give you guys something to think about while you play with the 1.0 Release candidate!
28 April 2008 04:41 AM 8 Comments

Transfer Introduction eSeminar Recording

The recording for the recent Transfer eSeminar is now available to be viewed at your discretion.

The same code can also be downloaded from here.

There is a small silent part at the beginning due to the fact my Windows VM crashed, but the rest was relatively smooth sailing.

I hope you enjoy!

This is actually the same presentation I will be giving at cf.Objective() , so you may want to hold off on watching it, and catch it live instead ;o)

Big thanks to the Adobe Pacific eSeminar series for allowing this to happen.  It's worth checking it out to see if there is another eSeminar that is going to interest you!

24 April 2008 04:27 AM 6 Comments

Transfer eSeminar - Tomorrow - 25th of April

Just a quick reminder that I will be doing an eSeminar for Adobe tomorrow, 25th of April, at 2:00pm Melbourne, Australia Time.

Agenda
Introduction to Building Applications with Transfer ORM

When developing an Object Oriented web based application, it is normal to have a database with relational tables and a series of objects that represent that data. Often, the amount of time and effort it takes to manually map these objects back and forth from a database is large, and can be very costly.

Object Relational Mappers (ORM) were developed to cut down the amount of time this process takes, and automate the translation between a relational database and an Object Oriented system.

Transfer ORM's main focus is to automate the repetitive tasks of creating the SQL and custom CFCs that are often required when
developing a ColdFusion application. Through a central configuration file Transfer knows how to generate objects, and how to manage them and their relationships back to the database.

This presentation will outline the basics of what an Object Relational Mapper is, the use case for using one within web application
development, as well as taking a code centric, step by step view of how to install, configure and use the basic functionality of Transfer ORM.

Times
For those Aussie folks - yes, this is Anzac day! (Yeah.... I dunno why I was given a public holiday, go figure) ;o)

For those not in the AU region, the time conversion is:
USA - EST: 12am, 25-26 of April
USA - PST: 9pm, 25th of April
UK - London: 5am, 25th of April.

If you feel like staying up / getting up early, you are more than welcome to join us.

This is the new Introductory presentation I will be giving at cf.Objective() this year, so you can come by and get a preview of what I will be speaking about.

Registration
http://events.adobe.co.uk/cgi-bin/register.cgi?country=pa&eventid=6503&venueid=6858

23 April 2008 05:45 PM 0 Comments

Transfer Documentation Moves to a Wiki

As you may have picked up the occasional teaser, the Transfer documentation has been officially moved to a new Wiki, which can be found at http://docs.transfer-orm.com.

The old URLs now redirect to this link, and the project page links are also pointing here.

This is one of the new faces of the soon to be released Transfer 1.0, a large part of which is project infrastructure. 

In the next few months, you will see more and more being built, to help build the Transfer community, and provide it with the support it needs to help make Transfer into an even better project than it is now.

As per what is CodexWiki? Well, I guess you'll have to come to cf.Objective() to find out...
07 April 2008 09:36 AM 0 Comments

Melbourne CFUG - 17th of April

Another CFUG Meeting for us all,

Location:

NGA.net, Level 2, 17 Raglan St, South Melbourne
Map: http://link.toolbot.com/google.com/73016

When:
17th of April, Meeting starts at 7:00, so get there before hand (doors open at 6:30).

Agenda:

Dale Fraser will be taking us through....

Flex for ColdFusion Developers

This talk will cover the basics of how to get setup on FlexBuilder to start writing Flex applications that will leverage your existing ColdFusion code.

Topics covered will several of the standard flex components and how to return various types of data from ColdFusion to flex. You will be amazed how easy it is.

Specifically:
Returning Simple Values
Returning Structures
Returning Arrays
Returning Queries

And how to bind these to common components in Flex such as

DataGrid
ComboBox
TextInput

We will also cover dymystifying the install and configuration of Flex to ColdFusion, and a simple way to setup the necessary mappings between the two. This is for anyone who loves ColdFusion and wants to start with Flex and for anyone who is trying to decide between Ajax & Flex.


Dale will also announce the launch of a new website on this night that specifically is aimed at the ColdFusion to Flex developers.

If you are going to attend, please RSVP to mark [dot] mandel [at] gmail [dot] com.

Only those that RSVP are eligible for the door prizes, so make sure you apply!

See the CFUG Melbourne Calendar at:
http://www.cfcentral.com.au/Events/index.cfm

Or add to your Google Calendar - search for 'CFUG Melbourne'.

As per usual, we'll grab pizza during the evening, so we have something to scoff down!

Look forward to seeing you all there.

27 March 2008 07:58 AM 0 Comments

Blatant Plug For This Site's ColdFusion Hosting - NovaHost

I just had a really nice experience with NovaHost today, so I felt like sharing the love.

Novahost sponsors the ColdFusion hosting for CompoundTheory, and also for Transfer-orm, and for that I'm always very, very grateful.

Today, I needed some aspects of this hosting changed, so I jut popped them a quick Instant Message via MSN, and was quickly handled, without any problem at all.  I just love it when Customer Serivice just works!

If you are interested in shared ColdFusion hosting in Australia, click the ad on the right hand side of this post.  They're reliable, easy to deal with, and are run by people who understand ColdFusion (which for me is the big selling point).

Okay, I'll stop being gushy now, but seriously, check them out ;)

10 March 2008 11:40 AM 0 Comments

Transfer: Talking and Training at WebDU

I have to say, I'm very excited about this years webDU, the speakers looks fantastic, and the topics seem to be really great as well!  I'm particularly excited by the fact that two of the ColdFusion engineers will be there, and presenting!

 

webDU

 

On the Transfer side of things, I will be providing a full day workshop on Day 0 of webDU, so for those of you who are keen to gets started with Transfer, but haven't before had the chance, or are simply looking to brush up on your Transfer skills, now is the perfect chance.

Otherwise, I will also be presenting Database Queries the Easy Way using Transfer Query Language where I will cover the hows and why of TQL, and some of the ways it can help you write even less SQL.

26 February 2008 12:46 PM 4 Comments

Transfer Transaction Support in SVN

Yes, I know, I broke my own feature freeze... I'm a very naughty developer.  I had a need for Transaction support in the code base I've been writing for the new Transfer documentation, so I figured that I had to simply write it.  That and I thought it was a super cool idea, so I couldn't let it slide ;o)

The Problem

There are two issues I was trying to solve with Transfer Transaction support, so let's look at a common Transfer Transaction scenario and see what the problems are.

Say we have a TransferObject named 'Foo', and we have a Service, named 'FooService'.  We may have some code that looks like:

<cffunction name="saveFoo" hint="saves Foo, and its children" access="public" returntype="void" output="false">
    <cfargument name="foo" hint="The foo" type="Foo" required="Yes">
    <cfset var children = arguments.foo.getFooChildrenArray() />
    <cfset var child = 0 />

    <cftransaction>
        <cfset getTransfer().save(arguments.foo, false) />
        <cfloop array="#children#" index="child">
            <cfset getTransfer().save(child, false) />
        </cfloop>
    </cftransaction>
</cffunction>


In which we save Foo, and its many FooChildren, and we wrap it in a <cftransaction>, so that if anything goes wrong, the whole set of data gets rolled back.

Now, there are two issues with this scenario that need to be addressed:

Nested Transactions
You can't nest the saveFoo() call inside another Transaction block.  i.e. code that looks like:

<cffunction name="saveFooParent" hint="saving a Foo Parent" access="public" returntype="void" output="false">
    <cfargument name="fooParent" hint="The foo" type="FooParent" required="Yes">
    <cftransaction>
        <cfif arguments.fooParent.hasFoo()>
            <cfset saveFoo(arguments.fooParent.getFoo(), false) />
        </cfif>
        <cfset getTransfer().save(arguments.fooParent, false) />
    <cftransaction>
</cffunction>


This will throw an error, as ColdFusion won't allow you to nest <cftransaction> blocks.  We could write something similar to what Transfer already does, and pass a boolean to the save method to tell it whether or not to use an inner transaction, but this is cumbersome, and depending on your application architecture, you may not be in a position to know if a given method is in a transaction.

Cache Synchronisation
Cache synchronisation is a real problem when database data rolls back, and the Transfer cache stays the same.

i.e. If we look at the saveFoo() method above, if the data on Foo has been updated, but something goes wrong when saving the children, then the data for Foo gets rolled back along with everything else, but the cache stays the same, which can be a very bad thing, as your object data is totally out of sync with your database (and not when you want it to be).

The Solution

So what is the solution? The solution is to use the new Transfer Transaction Object!

The Transaction object provides both:

  1. Nested Transaction support.
    If a Transaction wraps another Transaction, the inner transaction just becomes merged with the outer, as if it was just one big Transaction.
  2. Transfer cache synchronisation
    If anything goes wrong in your Transaction, then Transfer will automatically discard any object whose data was modified during that Transaction.

So let's look at how we can use the Transaction object.  First of all, how do we get it? Very simply, it's available from the TransferFactory, so can now go:

<cfscript>
    transaction = application.transferFactory.getTransaction();
</cfscript>


And get access to the Transaction object.  On a side note, the reason it is accessible from the TransferFactory, and not Transfer, is because it is not specifically tied to Transfer.  You can use this Transaction object with anything that requires a <cftransaction> wrapped around it.

There are three different ways you can use the Transaction object, and will look at them all, in regards to the example we gave above.

Direct Execution
The first one is the simplest:

transaction.execute(component, methodName, [arguments])

This simply executes a given method (even private ones!) on a given component, with an optional struct of arguments.

In the instance of above, we would have to change our code to look something like:

<cffunction name="saveFoo" hint="saves Foo, and its children" access="public" returntype="void" output="false">
    <cfargument name="foo" hint="The foo" type="Foo" required="Yes">
    <cfset getTransaction().execute(this, "_saveFoo", arguments)>
</cffunction>

<cffunction name="_saveFoo" hint="saves Foo, and its children" access="public" returntype="void" output="false">
    <cfargument name="foo" hint="The foo" type="Foo" required="Yes">
    <cfset var children = arguments.foo.getFooChildrenArray() />
    <cfset var child = 0 />

    <cfset getTransfer().save(arguments.foo) />
    <cfloop array="#children#" index="child">
        <cfset getTransfer().save(child) />
    </cfloop>

</cffunction>


So the above code would execute the method _saveFoo, wrapped out in our nesting-safe Transaction.  Pretty cool, but a bit cludgy as we have to implement a second method.

Aspect Oriented Programming

I think we can do better, and in fact we can, using the second method.

transaction.advise(component, function)

For those of you who are familiar with Aspect Oriented Programming (AOP), this method takes the component, and the function itself, and wraps a nesting-safe Transaction advise around the function that has been passed in.

If that was a little high level, to give an example, I could change the FooService to be:

<cffunction name="init" hint="saves Foo, and its children" access="public" returntype="void" output="false">
   <cfargument name="transaction" hint="The transaction object"type="transfer.com.sql.transaction.Transaction" required="Yes">

    <cfset arguments.transaction.advise(this, saveFoo) />
</cffunction>


<cffunction name="saveFoo" hint="saves Foo, and its children" access="public" returntype="void" output="false">
    <cfargument name="foo" hint="The foo" type="Foo" required="Yes">
    <cfset var children = arguments.foo.getFooChildrenArray() />
    <cfset var child = 0 />

    <cfset getTransfer().save(arguments.foo) />
    <cfloop array="#children#" index="child">
        <cfset getTransfer().save(child) />
    </cfloop>
</cffunction>


So what happens at init() time, the original saveFoo() is wrapped up in a nesting-safe transaction, and you don't have to write much extra code, except to remove the old <cftransaction> tags, and tell the Transaction object what methods to advise.  Much better than the first way, and it works on both private and public methods.

So the above, is very nice, however, what happens if we have a lot of functions we want to advise()?  Well, the third way of using the Transaction Object is handy for that!

transaction.advise(component, regex, [debug])

With this approach, we can apply the Transaction advise to all methods, both public and private whose name matches the given regular expression.

For example, if we want to apply Transaction advice to every method that starts with 'save' in our FooService, we would just need to have our FooService written like:

<cffunction name="init" hint="saves Foo, and its children" access="public" returntype="void" output="false">
   <cfargument name="transaction" hint="The transaction object"type="transfer.com.sql.transaction.Transaction" required="Yes">

    <cfset arguments.transaction.advise(this, "^save") />
</cffunction>


<cffunction name="saveFoo" hint="saves Foo, and its children" access="public" returntype="void" output="false">
    <cfargument name="foo" hint="The foo" type="Foo" required="Yes">
    <cfset var children = arguments.foo.getFooChildrenArray() />
    <cfset var child = 0 />

    <cfset getTransfer().save(arguments.foo) />
    <cfloop array="#children#" index="child">
        <cfset getTransfer().save(child) />
    </cfloop>
</cffunction>


And we are done.  If we ever add a method that has 'save' at the beginning of its name, such as the saveFooParent() from before,  then it will automatically be wrapped up in a Transaction, even if the method is private.

If the 'debug' argument is set to true, the Transaction object will <cftrace> all the methods that are advised, so you can see if your method is being wrapped up in a Transaction or not.

I don't often say this (in fact, I avoid it whenever possible), but this is the official best practice for doing Transactions with Transfer ORM.  The usage of the optional 'useTransaction' argument is now officially deprecated.

Now I'll get back to this documentation stuff.... this is the last feature! I swear!

Big thanks to Jared Rypka-Hauer for letting me bounce this idea off him as well!

20 February 2008 06:09 AM 0 Comments

Recently on #coldfusion...

This was too clever to pass up (By the way, 'Neuro', or 'Neurotic' is me):

<DanWilson> Neuro doesn't have kids, he generates them
<jamiejackson> hope they don't inherit behavior
<DanWilson> behaviour is mixed in at runtime

Check out more silliness at #coldfusion on Dalnet irc! 

14 February 2008 06:52 AM 0 Comments

Melbourne CFUG - 21st February

The first CFUG of the new year!

Location:

NGA.net, Level 2, 17 Raglan St, South Melbourne
Map: http://link.toolbot.com/google.com/73016

When:
21st February Meeting starts at 7:00, so get there before hand (doors open at 6:30).

Agenda:

Tonight we will be viewing and discussing Sean Corfield's Presentation on Design Patterns:

Come find out what design patterns are really about and how they can make your life easier. (You're probably already using some design
patterns, although you may not know it.) For this session, we have distilled decades of software engineering experience into a well-documented set of blueprints that can be applied to common problems to ensure clean, maintainable code.

Sean Corfield:
Sean is currently a freelance consultant. He has worked in IT for nearly twenty five years, starting out writing database systems and compilers then moving into mobile telecoms and then finally into web development about nine years ago. Along the way, he worked on the ISO and ANSI C++ Standards committees for eight years. Sean is a staunch advocate of software standards and best practice. He wrote C++ coding guidelines for several companies during the 90's and more recently maintaining the Macromedia ColdFusion MX Coding Guidelines and Mach II Development Guide, which are also published for the ColdFusion community. He has also given several seminar talks, both in- house and publicly, on these subjects. Sean has championed and contributed to a number of ColdFusion frameworks.

If you are going to attend, please RSVP to mark [dot] mandel [at] gmail [dot] com.

Only those that RSVP are eligible for the door prizes, so make sure you apply!

See the CFUG Melbourne Calendar at:
http://www.cfcentral.com.au/Events/index.cfm

Or add to your Google Calendar - search for 'CFUG Melbourne'.

As per usual, we'll grab pizza during the evening, so we have something to scoff down!

Look forward to seeing you all there.
21 January 2008 05:22 PM 4 Comments

Transfer Going POSS, Powered by Compound Theory

From the end of February 2008, Transfer will be become Professional Open Source Software.  This means that Compound Theory will start selling services that are based around Transfer, while still retaining its free, Open Source licence.

The idea behind all this is such that I can do more for Transfer than I am currently doing, both in terms of being able to write code, as well giving me more freedom to present, and travel to conferences to physically talk to people.

Not only will Compound Theory be providing a series of services based on Transfer ORM, it will also be offering project based consulting, training, and mentoring.

To that effect, if you are interested in Compound Theory's services, please feel free to contact me directly.

On the Transfer front, understandably, things are moving forward pretty fast. 

Right now, I'm taking Expressions of Interest in the following areas:

  • Transfer Support
    A subscription and/or per incident model for support as pertaining to Transfer installation, use and/or any overall issues.

  • Transfer Training
    A Transfer curriculum that will come in a series of short courses, as well as single/multiple day training programs, covering both on-line training, and in-person training.

  • Transfer Developer Certification
    Much like ColdFusion Developer Certification,a Developer certification give you a listing on the new Transfer site as certified, as well as a spiffy certificate.

  • Transfer Training Certification
    Again, much like ColdFusion Training Certification, this would give you a listing on the Certified Trainers page on the Transfer ORM site, as well as access to the training materials.

If you are interested in any of the above programs and/or services, please send me an email either on my contact form, or via the Transfer Google Group.  Once we have launched these programs, I will be in contact to let you know of the specific details.

If anyone wants any more information on Professional Open Source Software, 'The Beekeeper' article by Pentaho Commercial Open Source Software is one the best descriptions of POSS I have ever read.

So with all that, what are the specific plans for Transfer in the near future?  Lots of things!

First of all, the SVN version of Transfer is currently in feature freeze.  I'm only fixing bug fixes at this stage, to prepare for a Release Candidate of 0.7.

This release candidate will coincide with the new Wiki that will power and house the extended documentation, both for the new features of Transfer, and expansion on current feature sets.  This Wiki is currently under development, and you should be seeing something on it soon.

The Wiki will be a new part of the new Transfer site that I have been promising for a long time.  The design for this has been done, and it looks fantastic.  This will consolidate things like bug tracking, project and knowledge management into a single space, which will be very useful in the long run.

Once that is all up and running, we're going to be moving as quick as we can towards a Transfer 1.0!

I have revised the road map, and pushed out several pieces to be implemented post 1.0:

Included in the 1.0 Roadmap

  • Binary Data Support
    Currently Transfer doesn't support being able to insert or retrieve binary data from the database.

  • Programmatic setting of the data source details through the Configuration Bean
    This will give a developer the ability to programmatically set the details of the data source, which is particularly useful when the datasource name is dynamically generated.

  • Generated methods all have hints on them, for TransferDoc and/or if displaying the object meta data in any way
    Currently some, but not all methods that are generated have a populated hint="" on their <cffunction> definitions. This will be expanded to include all <cffunctions>, to enhance generated documentation

  • Ensure hashing is unique for all changes to the transfer.xml, by ensuring that changes to any parents, flow through to generating new definitions for children.
    There are currently a few rare occurrences where Transfer .transfer files won't be regenerated when a change is made to the XML file.  These rarities will be fixed.

  • Finalise CLOB support across all DBs.
    CLOB support has a few issues across some DBs, specifically Oracle.  This will be resolved so that it is no longer an issue.

  • Cascading insert, updates, delete and saves
    This is what it says it is.

  • Programmatic reloading of the XML file.
    The ability to be able to programatically reload the XML configuration file from within Transfer, to aid in development.

Pushed out to post 1.0 release

  • Soft Deletes
    I have some more flexible ideas on how to go about this, that will provide soft delete functionality, as well as some other far more extensible possibilities.

  • TQL on conditions
    This will allow you to use TQL on <condition> declarations, however, I'm not sure if <conditions> are  necessary any more, as it may be superseded by some other ideas I have

  • Transaction based caching that discards objects inside a transaction if the transaction fails. 
    The way I wanted to implement this was not actually possible with ColdFusion, but I have some other ideas on how to facilitate at least something similar

From here there is also a strong plan to be releasing on a regular and frequent schedule.  I am fully aware of the fact that it's almost been a year since the last release, but for those of you who haven't followed the SVN version of Transfer, will be pleasantly surprised at how much we've managed to fit into this new release.

The goal is to have the 1.0 of Transfer at least at Release Candidate stage by cf.Objective() this year.  Even though it's going to be a lot of hard work, I think that is is truly possible.

All in all, this is a pretty exciting time for Transfer, so I want to thank all those who have participated up until now, we've developed a great community, and 2008 is looking to be a very fun, and exciting year for all involved.
17 January 2008 12:34 PM 11 Comments

I'm an Adobe Community Expert

I was very excited to find out yesterday that I am now an Adobe Community Expert!

Adobe Community Expert

I'm really happy to be selected for the program, and hopefully I'll get my little 'Adobe Community Expert' sticker up on this site soon, when I have two minutes to breathe... ;o)

17 January 2008 04:40 AM 0 Comments

Flex and AIR User Group Pre-release Tour - Melbourne, 29th January

In case people missed this the CFAUSSIE List: 

Flex 3 and AIR are getting close to launch and in preparation, the dobe Platform Evangelist team is travelling around the world, and to elbourne, to show off the great new features and some brand new
demos.

Flex 3 is a feature-packed release, adding new UI components like the advanced datagrid and improved CSS capabilities; powerful tooling additions like refactoring; and extensive testing tools including
memory and performance profiling, plus the addition of the automated testing framework to Flex Builder.

Adobe AIR is game-changing in so many ways, extending rich applications to the desktop, enabling access to the local file system, system tray, notifications and much more. Now you can write desktop applications using the same skills that you've been already using to create great web apps including both Flex and AJAX.

Don't miss out on the opportunity to see and hear about this highly anticipated release of Flex 3 and AIR during this special pre-release tour.  Plus, in addition to giving away some one of a kind Flex/AIR branded goodies, we will also be raffling off a copy of Flex Builder 3 Professional (pending availability) and a full commercial copy of CS3 Web Premium at this event!

Melbourne event details...

Danny Dura is an Adobe Platform Evangelist at Adobe U.S.A, who will be in Melbourne for a special Flex/AIR evening meeting on Tuesday the 29th of January, 2008.

This will be a joint effort/presentation of the Flash UG and the ColdFusion User Group (CFUG), but the venue is still the same.

Many have expressed interest already, and this event will go ahead, but we would still like to get an idea about how many are coming for catering reasons, please express your interest via, if you have not done so already:

Edit ::: 18-Jan-2008 ::: This event is at (or even over) capacity.  You can still apply for interest, but if you do not get an invite, you cannot attend.  We just have too many people wanting to come! :) (which is not a bad thing)

http://www.techevents.com.au/flex/

This event will be catered for and we will be giving away a copy of Adobe Flex 3 (pending availability), as well as Creative Suite 3 Web Premium, all courtesy of Adobe. Please note you must have expressed interest once via the link above to been in for a chance to win the Adobe software.


Meeting time...

7PM, Pizza and refreshments at 6:30PM, doors open 6PM.

Tuesday the 29th of January, 2008.


Meeting location...

Edit ::: 24th of January ::: Due to unforeseen circumstances, there has been a last minute venue change.  Please check your invite emails for the new address.

About Danny Dura...

Danny Dura is an Adobe Platform Evangelist - His main focus is AIR, Flash Player, ActionScript and Flex.

http://www.danieldura.com/

10 January 2008 11:07 AM 1 Comment

Special Flex Event in Melbourne

In case people missed it via the CFUG list, please put down interest ASAP, so we get everything confirmed. 

We are happy to have some potentially very exciting news for our Cold
Fusion User Group for very early in the new year.

Danny Dura is an Adobe Platform Evangelist at Adobe U.S.A will be in
Melbourne in late January so we are making preliminary enquiries to
see if our members would be interested in attending a special
Flex/AIR night meeting.

The planned date would be the evening of Tuesday the 29th of January,
2008. If you don't know much about Flex or AIR, this will be right up
your alley. If you already know about Flex or AIR, this is a great
opportunity to be brought up to speed with Flex 3 and AIR pending
their release this year.

We realise that many of you will be away, given it's still the
holiday season. However, if you'd be interested in coming, please let
us know by simply clicking on the link below.

http://www.techevents.com.au/flex/

If the event goes ahead, it will be catered for and we will be giving
away a copy of Adobe Flex 3 (delivered after release), as well as
Creative Suite 3 Web Premium, all courtesy of Adobe.

About Danny Dura...

Danny Dura is an Adobe Platform Evangelist - His main focus is AIR,
Flash Player, ActionScript and Flex.

http://www.danieldura.com/

06 January 2008 08:21 AM 2 Comments

Paul Marcotte on the Transfer Event Model

Paul Marcotte at Fancy Bread has written a tutorial on the Transfer event model, based on the User password encryption example I gave during my Advanced Transfer ORM Techniques talk.

He does a really good job of breaking down the code example, and provides some extra information above and beyond what I had originally provided in my presentation, including some tips on integrating with ColdSpring.
21 December 2007 07:51 AM 1 Comment

Speaking at cf.Objective()

Yesterday I got notified that I will be speaking at cf.Objective() next year!  I am very excited about coming over again and speaking.  Last year was an amazing experience, and it will be great to catch up with all the people who I only ever get to see face to face once a year.

I'm going to be doing two presentations on Transfer:

'Introduction to Building Applications with Transfer ORM' - A reworking of my original 'intro' talk, that is going to take a very code centric walkthrough of setting up and using Transfer ORM.

Transfer ORM Caching Mechanics' - Where we will look at some overall caching concepts, and have a strong technical discussion on how the caching in Transfer works, as well as all the configuration options, and cache manipulation methods that are available.

I have to say, the speaker line up this year looks absolutely amazing. I'm actually seriously hoping that my speaking schedule doesn't get in the way of me getting to all the sessions I want to get to!

Big Kudos to Jared, Sean, and everyone else who's been working on the cf.Objective() conference, you guys are doing an incredible job.

10 December 2007 08:57 AM 0 Comments

Melbourne CFUG - 20th December

A quick reminder for the last Melbourne CFUG Meeting of the YEAR!

Location:

NGA.net, Level 2, 17 Raglan St, South Melbourne
Map: http://link.toolbot.com/google.com/73016

When:

20TH of December, Meeting starts at 7:00, so get there before hand (doors
open at 6:30).

Agenda:

Dale Fraser will be presenting on CFAJAX!

ColdFusion 8 includes a lot of Ajax features, and if you think Ajax is
complicated, think again. Ajax will make some of the things you do now
easier, and if you can write ColdFusion code, you can easily use Ajax
with ColdFusion Ajax features. So if you have always wanted to do some
Ajax stuff or you want to learn what Ajax is, then this is for you.

Topics covered include:

  • <CFAJAXPROXY to bind to controls and CFC's
  • <CFGRID a DHTML grid with binding and paging
  • <CFINPUT an autosuggest feature using Ajax binding
  • The ColdFusion. javascript methods that come with ColdFusion 8
  • And more

If you are going to attend, please RSVP to mark [dot] mandel [at] gmail [dot] com

Only those that RSVP are eligible for the door prizes, so make sure you apply!

See the CFUG Melbourne Calendar at:
http://www.cfcentral.com.au/Events/index.cfm

Or add to your Google Calendar - search for 'CFUG Melbourne'.

As per usual, we'll grab pizza during the evening, so we have
something to scoff down!

Look forward to seeing you all there.

06 December 2007 04:14 PM 13 Comments

Huge Performance Gain in Moving ColdFusion 8 to Java 1.5

We have a reasonably large application that we have been building for the past 2 years or so, with MachII, ColdSpring and Transfer, and we moved over to ColdFusion 8, pretty much as soon as the Beta came out, and have been developing with it ever since.

To give you an idea of the size of the project, some metrics for you, we have 1064 CFCs, 329 .cfm pages, 161 configured Transfer Objects, 40 MachII frameworks instances (we started this before modules), and 201 Tables.  This actually results in about 22,000 .class files being generated by ColdFusion behind the scenes.

What we began to experience is extremely long start up times when the server was first started up. For example with no class files saved on the server, we have a start time of around 20 minutes before the application was responsive, and if multiple people hit the site at once, we were looking at around 45 minutes before the application would perform usably.

With class files saved, this dropped down to 9 minutes, but we still ran into huge difficulties with multiple users hitting the site at once.  On top of that, whenever we had to upload a change, clearing the template cache so the change would propagate brought the server to it's knees, so we were forced to restart CF with every deployment of code.

So after much haranguing, and talking to a whole slew of people, both Adobe, and non Adobe (you all know who you are, and thank you very much for the time and effort you all put into helping out on this), it eventually got narrowed down to a bottleneck in Java 6 as described here (as also reported by Sean Corfield )

So for those of you not so familiar with Java, what does all that actually mean?  Well, let's look at what ColdFusion does behind the scenes when you run a .cfm or .cfc page:

  1. Checks to see if it has the Java Classes already in memory to do what you have requested - if not,
    1. CF Reads in the file you are executing
    2. Parses the CFML
    3. Converts the parsed CFML data structure, and converts it into Java code
    4. Compiled that Java code down to actual Java .class files
    5. Loads the resulting .class file into memory
  2. Executes the Java code contained in the .class file as necessary.

So probably nothing too revolutionary in there in terms of our understanding of the ColdFusion process, however, there is a big bottle neck in Java 6 where the loading into memory Java classes is really really really slow (maybe I need another really there), so step 1.5 on the above processes takes a very long time to get through - and the problem only gets worse when there are large numbers of very small classes - which in almost any ColdFusion application, and ours in particular, there are.

There are several places in which this issue can cause serious problems -

  1. At System Start Up
    As discussed previously.

  2. Development.
    Obviously during development, files tend to change quite regularly.  During development of our application, it would not be strange for me to be spending several minutes, to the tens of minutes waiting for a small change in either a .cfm or .cfc to come through. This simply slows down the amount of work that you are able to do in any given time frame.

  3. At Run Time
    Since ColdFusion has a finite limit on the number of cached templates (which are just the .class files mentioned earlier stored in memory), it is quite likely that at some point during an application life cycle, part of what is stored in the template cache will get purged so as to make room for other Java classes that have become active.  We hit the same issue as we hit on step 1.5 as above, as the ColdFusion server slows down as it pulls in the required Java classes into memory.  This can result in random slowdowns in the application, which are hard to reproduce.

    This becomes a larger issue on shared host systems, in which a trusted template cache is impossible, and it is quite likely the ColdFusion server is constantly moving the generated Java code in and out of it's template cache, as multiple systems require different ColdFusion code to be executed.

It wasn't until we had one of those head-slap moments when a co-worker turned around to me and said 'well.. why don't we try Java 1.5?'?

Once installed, suddenly everything started working like we wanted it to, performance wise.

Since everyone loves a pretty graph, here are some metrics on server start up, taking a Selenium script through a series of steps through one part of our application, so you can see the considerable difference between the two Java Versions

Average TIme Taken

Total Time Taken

Not only has this made our production systems run incredibly fast, it also means that we are able to upload code to the production server, clear the template cache, clear the application cache, and we are good to go, there is no need to restart ColdFusion for changes.

This also means I can develop without having to take a coffee break in between code changes, which has upped my productivity as well, in fact, I can now develop happily in Machii with the config mode set to constantly reload, and performance is no problem at all.

As far as I am aware, this issue does not exist in the development snapshots of Java 7, and apparently a fix is in the pipeline for 1.6, but Sun hasn't been forthcoming about the date.

Until that time, I would suggest moving your ColdFusion 8 servers over to Java 1.5, and enjoy the speed improvements!!!

Jared Rypka-Hauer on Named Transactions Feature Request

Jared just did a blog post over at Alagad on a feature request for named transactions.  I have to chime in here and say that I really, really, really, want this feature!

The current restriction of having transactions only within a <cftransaction></cftransaction> block is incredibly limiting from a OO perspective.

Something that I had on the radar for Transfer was to be able to control the Transactions at a database level with your code, as well as automatically clearing from cache the relevant objects if something went wrong.

Essentially it would go something like this:

transaction = getTransfer().getTransaction();

try
{
    transaction.begin();
  
    employee = getTransfer().get("employee", 1);
    employee.setUsername(form.username);
    getTransfer().save(employee);

    manager = getTransfer().get("employee", 4);
    manager.addEmployee(employee);
    getTransfer().save(manager);

    transaction.commit();
}
catch(Any exc)
{
    transaction.rollback();
}

With this code, if we got to the 'transaction.rollback()', not only would it roll the DB data back, but it would also intelligently discard the 'employee' and the 'manager' objects from cache - thus ensuring that there was no dirty data.

Currently, with ColdFusion transactions structured the way they are, it's actually impossible for me to do this, as there is no <cftransaction> block, and I have no hook to pick up when something goes wrong.

With a named Transaction block, I could internally handle how transactions where managed inside my Transaction.cfc, and and I could pick up the rollback() or commit() call as appropriate.

This would be an incredibly handy thing, so count me on a big +1 for this feature!
26 November 2007 02:58 PM 0 Comments

Melbourne CFCAMP Wrapup

Melbourne CFCAMP was last week, and I have to say, I think it went really, really well.

We had an attendance of about 50 people, so it made it a good intimate environment, and everyone asked lots of questions from the presenters, which was great to see.

It was also a great chance to catch up for drinks with the likes of Geoff Bowers, Robin Hilliard, and Peter Bell, who may be local to Australia, but rarely are in the same place at the same time.  (Albeit Peter is new to Australia).

We all went out for a few drinks after the CFCAMP events had finished, and the conversation continued over wine and beer, and we had a pretty good discussion about all sorts of things... including Robin's calculations about the Red Bull challenge (which I don't think were ever fully explained)

I'd like to say a big thanks to Mark Blair, and all the Adobe staff that came down to support the event, it was really appreciated, a good time was had by all, and we even learnt a thing or two.

If anyone is still sitting on the fence on whether or not to go to Perth, I would highly recommend it.
19 November 2007 09:24 AM 2 Comments

Melbourne CFCAMP this Week!

Just reminding everyone that the Melbourne CFCAMP is on this Thursday!!!

The agenda has been locked down, and can be seen at http://cfcamp.pbwiki.com/Agenda:+Melbourne and I have to say, it looks really exciting!

We're going to be seeing coverage of topics ranging from ColdFusion 8 (Obviously), Flex integration, AIR Integration, Farcry, Transfer ORM, LiveCycle Data Services and Code Generation, not to mention its going to be a great opportunity to catch up with all the local developers, and see what is going on in the local development community.

If you have yet to register, I would highly recommend that you do! It's going to be a really good day!  And considering its all free, what have you got to lose?
05 November 2007 12:25 PM 1 Comment

Developing Applications With Transfer ORM Recorded Presentation

I recently did a Connect presentation to the IECFUG group, and it went really well!

I recently moved to a new ISP at a higher speed, so this presentation is missing out on all the audio clipping and dropouts of its predecessors, which I am really happy about.

If you haven't managed to catch this presentation, and want to have a listen, the recording can be found here.
05 November 2007 09:43 AM 0 Comments

Advanced Transfer ORM Techniques at CFFrameworks.com

On the 28th of November, 12pm UK time, I will be presenting via Connect my 'Advanced' Transfer ORM talk, covering some of the functionality of Transfer that is above and beyond the usual CRUD stuff.

This includes things like the caching layer, the observable events, Decorators, and Transfer Query Language, which aren't covered in the introductory talk that I often do.

More details on the talk can be found at the cfframeworks site.

I hope you all enjoy it,as I have yet to do this one online yet! So this will be the first!  Should be good!!!
29 October 2007 05:01 PM 0 Comments

Petitioning for Speakers for Melbourne CFCAMP

Melbourne CFCAMP is looming on the 22nd of November and we're in the need for speakers!

Topics can include anything from case studies, to frameworks, to development techniques, to pretty much anything that is related to ColdFusion!

Speaking time is 30 minutes long (although if you need more time, it can be arranged).

So if you have something you can present, or even an idea of something you can present, please write it up on the WIKI page, and share it with the rest of us.

Remember, CFCAMP is for the CF community, so the more your help out, the more your help your community.

If you aren't going to speak, don't forget to register for the event, it should be a great day, and the venerable Ben Forta will be down to join us well!
08 October 2007 01:49 PM 2 Comments

Melbourne CFUG - 18th of October - ColdBox

All,

A reminder for the upcoming Melbourne CFUG!  Still in our new boardroom! No more
tiny cramped room for us!

Location:

NGA.net, Level 2, 17 Raglan St, South Melbourne
Map: http://link.toolbot.com/google.com/73016

When:

18th of October, Meeting starts at 7:00, so get there before hand (doors
open at 6:30).

Agenda:

Luis Majano himself is going to talk to us over Connect about the
ColdBox Framework.

Luis Majano is a Computer Engineer currently employed at ESRI
(Environmental Systems Research Institute) in sunny Redlands,
California. Please Support GIS!!.  He graduated from Florida
International University and holds an Advanced Coldfusion MX 6,7
Developer Certifications. He has over 7 years experience in software
development, networking and system design.  He is also a freelance
engineer and president of Ortus Solutions, Corp.

Coldbox

ColdBox is a proven event-driven CFC based ColdFusion Framework,
specifically designed for high availability web applications. The
purpose behind ColdBox was to create a fast & stable development
methodology that could be shared among several developers. It makes
use of an MVC (Model View Controller) design pattern implemented via
CFC's. It uses event handler CFC's that hold all the code necessary to
prepare views, call model CFC's or a business layer (Soap/ws/xml/J2EE)
and render views (HTML).

If you are going to attend, please RSVP to: mark [dot] mandel [at] gmail [dot] com

Only those that RSVP are eligible for the door prizes, so make sure you apply!

See the CFUG Melbourne Calendar at:
http://www.cfcentral.com.au/Events/index.cfm

Or add to your Google Calendar - search for 'CFUG Melbourne'.

As per usual, we'll grab pizza during the evening, so we have
something to scoff down!

Look forward to seeing you all there.
08 October 2007 09:22 AM 17 Comments

Should I run ColdFusion 8 on Ubuntu Server on my new VPS?

I've been given the opportunity to have my VPS where I am currently hosting, with the free choice of OS, and pretty much any set up I want.

My initial thought was to set it up on Ubuntu server, simply because, since switching to Ubuntu as my primary OS, I am far more familiar with it as a Linux platform than I ever could be on a RedHat based one.

Now, I know that Ubuntu is not a supported platform, however -

1) I've been running CF8 on Ubuntu for development, and had 0 issues, from installation to use.
2) It's my VPS, so I'm happy to have a bit of an experiment.
3) I really don't feel like learning CentOS (Yeah.. I know.. lazy).

What do you guys reckon?  Anyone been running CF8 on a Debian based distro, and faced any issues? Can anyone think of any issues that could trip me up?
02 October 2007 01:01 PM 7 Comments

Javaloader v0.5 Released

Here is the release of JavaLoader, version 0.5.

It pretty much does exactly the same thing that the previous versions did, however, it now works in ColdFusion 8, when the setting 'Disable access to internal ColdFusion Java components' is turned on, as it uses its own JavaProxy CFC, which may often be turned on on shared hosts.

That's really about it, nothing more interesting than that.

Download JavaLoader v0.5 from here.
24 September 2007 12:57 PM 9 Comments

How to tell if code is being run inside a CFTHREAD tag

One restriction I ran into today when doing some ColdFusion8 specific performance enhancements to Transfer with <cfthread> is that you can't make a child thread within an already created <cfthread>, so something like:

<cfthread action="run" name="a">
    <cfthread action="run" name="b">
    </cfthread>
</cfthread>

Will end up with lots of errors in your logs saying things like:
Error","cfthread-1","09/24/07","12:03:42",,"A: Thread B cannot be created. Child threads are not supported."

Which is probably not what you actually want, as you would most likely like for you code to actually execute.

I'm not a huge fan of this limitation, but I can kind of understand where the engineers are coming from - they don't want us CF developers to shoot ourselves in the foot with ridiculously spawning multi threaded applications.

So, in my current situation, I wasn't too fussed if I had a whole, brand new thread, but where my code was being run, I was so far down the stack of method calls, I have no way of knowing if the original call had come from a standard ColdFusion thread, or if it had come from a <cfthread> create thread, and both of which were highly possible.  However, if the execution wasn't coming from a <cfthread> created thread, I wanted to execute my code inside a <cfthread> statement, as I didn't care what the results where, and it would be faster for the end user just to have the code run asynchronously.

If that just made your head hurt, I basically have a series of method calls that look like:

A()
 - makes a <cfthread> call, and calls C()

B()
- Does some work...
- Calls C() from the current thread.

C()
- makes a <cfthread> call, and then does some work

This is an over simplification of the process (mine is far more levels deep), but gives you an idea of the trouble I was facing - the method call could go through A() or through B(), and at the level of C() I wasn't aware of whether or not I had started on the base ColdFusion thread or not.

I could have done this passing a parameter all the way down the method chain to tell it if it should fire asynchronously, but that seemed like a lot of extra work, and would have put a level of complexity within the whole process, and any other process that was related to this, that it didn't seem like the appropriate course of action.

So I thought to myself - there has to be a way to find out if the current thread is a regular, ColdFusion thread, or if it is a <cfthread> invoked thread, and funnily enough, skipping into some Java, there is!

The first thing we have to do, is get access to the java.lang.Thread object:

Thread = createObject("java", "java.lang.Thread");

Now, the Thread object, has a great method 'currentThread()', which returns the current thread that the executing code is on:

currentThread = Thread.currentThread();

What is good to know, is that Threads in Java can exist in ThreadGroups, which is a handy way of grouping Threads together for common operations, and other clever things.  The nice thing here, is that ThreadGroups have a method called 'getName()' which returns the name of the ThreadGroup.

Strangely enough, <cfthread> created threads live inside the ThreadGroup named 'cfthread'! So now we can compare this against the name of the current Thread's ThreadGroup

if(currentThread.getThreadGroup().getName() eq "cfthread")
{
  //do something...
}

We can also wrap this up nicely into a quick little UDF:

<cffunction name="amInCFThread" hint="returns 'true' if the current thread is a cfthread, returns false otherwise" access="public"returntype="boolean" output="false">
    <cfscript>
        var Thread = createObject("java","java.lang.Thread");

        if(Thread.currentThread().getThreadGroup().getName() eq "cfthread")
        {
            return true;
        }

        return false;
    </cfscript>
</cffunction>

This function returns 'true' if the currently executing code is inside a <cfthread>, and 'false' if it is not.

So now, in my function C() I can have:

C()
if(amInCFThread())
{
   // run code
}
else
{
  // make <cfthread> and run code.
}

And continue on my merry way!

Pretty handy if I'm not sure if my <cfthread>'d code will end up being run by other ColdFusion created threads or not.

Writing my own JavaProxy for ColdFusion 8 using onMissingMethod

First of all, you may be wondering 'what on earth is a JavaProxy?', well, to answer that question, it is the Java class that does all the work behind the scenes in ColdFusion to allow you to be able to write all that Java code in-line in your ColdFusion CFCs and CFM pages by taking the Coldfusion invocations you have implemented, and passed them to the native Java objects that you want to use.

To further your understanding, if you are at all interested, you can also read up on the proxy design pattern here.

Now, what some people may or may not realise, is that inside JavaLoader, I create an instance of the coldfusion.runtime.java.JavaProxy class, so it becomes really easy for developers to create and use instances of Java objects that are loaded from external .jar files within their applications.  I have a good blog post on doing this here.

Now just the other day, I became aware of a new setting in ColdFusion 8 entitled 'Disable Access to internal ColdFusion Java components', that really threw me for a bend.

For people who run shared hosts, they probably think of this as a g-d send, in that it will disable access to coldfusion.runtime.ServiceFactory - and for that, I totally understand, however, it completely locks down access to any Java object that sits under the coldfusion.* package space.

What does this mean? It means that JavaLoader, no longer works, along with any other project that also uses JavaLoader could quite potentially not work on some shared hosts providers that have upgraded to ColdFusion 8!

Why did Adobe decided to do this? Not so sure! However, with the power that we have in ColdFusion 8, we are able to implement our own JavaProxy, that should be able to be seamlessly interchanged with the ColdFusion native JavaProxy!

(Disclaimer: This is the first run at this code, and it works in the given tests I have tried on it.  I will be running it against all the unit tests on Transfer, and when they all work perfectly, and Transfer can run with this CF8 restriction in place, I will release the full code as part of a new version of JavaLoader)

There are two things that allow us to do this -
  1. Nothing stopping us from using Java Reflection to dynamically call methods on a Java Class or Instance.
  2. In CF8 we got 'onMissingMethod()' - so we have a hook into every method that is fired on a CFC, regardless of whether or not it has been implemented.
For those of you who aren't that familiar with the term reflection - it essentially means that we are able to introspect a Java Class or Object, determine what methods and/or properties it has, and dynamically call them at run-time.  If you want to read more, the Java site has a whole tutorial on reflection.

So, first of all, let's look at the few different ways you can instantiate and use ColdFusion Java Objects, we'll use an ArrayList as an example, so that we know what we need to support in our own JavaProxy. 
I will use 'createObject' here, but it could also just as easily be JavaLoader.create(className) to create an instance of the JavaProxy.
  1. array = createObject("java", "java.util.ArrayList").init();
    array.add(obj);

    - This would be the most common, and generally the 'best' way of instantiating a Java Object in CF, as it calls the constructor straight away, with the appropriate arguments, and is the closest you will get, in style, to implementing a real constructor.
  2. array = createObject("java", "java.util.ArrayList");
    array.init();
    array.add(obj);

    - I've seen this sort of code before... to me, it seems a bit weird to split out the constructor, but it works, and you always know that the object has been instantiated.
  3. array = createObject("java", "java.util.ArrayList");
    array.add(obj);

    - This is what I feel is the 'worst' way of using Java objects in CF as the no argument default constructor is called implicitly, which means you really have no control, and it can lead to all sorts of weirdness in your application if you don't track what has been actually instantiated and what hasn't.
  4. Collections = createObject("java", "java.util.Collections");
    sortedArray = Collections.sort(array);

    - This case shows where static methods are called, in which case, there is no constructor.
  5. Color = createObject("java", "java.awt.Color");
    black = Color.black;

    - This is where we want to be able to retrieve a static property.
Okay, so we have our work cut out for us! But all this is very much possible!

So, the first decision to make, is that all of our internal methods on the JavaProxy.cfc are going to start with an underscore.  This is so that any method that we write, doesn't interfere with the onMissingMethod's we want to be able to pick up.  Also as we need to implement a special 'init' method, that isn't the constructor for the JavaProxy, but instead is a constructor for the Java object the JavaProxy represents, so we will have a _init(class) method that instantiates the JavaProxy.

I'm not going to show all the code here, just the relevant parts, but don't worry, you will be able to see it in the next version of JavaLoader.

So the _init method will do the following things -
  1. Take a Java Class as an argument, and store it in state
  2. Store some helpful Java Objects in some setters.
  3. Set the Static Fields of the Class the JavaProxy represents to the this scope
  4. Store all the Method objects of the Class in a struct of arrays for easy lookup (more on this later).
First of all, we'll set the Static Fields to the this scope.  It is actually very straight forward -

<cffunction name="_setStaticFields" hint="loops around all the fields andsets the static one to this scope" access="private" returntype="void"output="false">
    <cfscript>
        var fields = _getClass().getFields();
        var counter = 1;
        var len = ArrayLen(fields);
        var field = 0;

        for(; counter <= len; counter++)
        {
            field =fields[counter];
            if(_getModifier().isStatic(field.getModifiers()))
            {
               this[field.getName()] = field.get(JavaCast("null", 0));
            }
        }
    </cfscript>
</cffunction>

For reference
So what are we doing here? Well, we ask the Class for all of it's Fields, then we look around them, and then interrogate into whether or not they are static.

Once we know they are static, we retrieve their value, using field.get(), and set them to the same place in the this scope as they would have been in the Java Object.

We are able to use 'null' on the field.get() because the values are static, and are not tied to any actual instance of the Class.

So, what would be nice now, is to be actually be able to instantiate an object!  So let's look at implementing our own 'init' method, so that we can instantiate the Java Class that the JavaProxy represents.

<cffunction name="init" hint="create an instance of this object"access="public" returntype="any" output="false">
    <cfscript>
        var constructor = 0;
        var instance = 0;

        //make sure we only ever have one instance
        if(_hasClassInstance())
        {
            return _getClassInstance();
        }

        constructor =_resolveMethodByParams("Constructor", _getClass().getConstructors(), arguments);

        instance =constructor.newInstance(_buildArgumentArray(arguments));

        _setClassInstance(instance);

        return _getClassInstance();
    </cfscript>
</cffunction>

For reference
  • _buildArgumentArray() simply takes the argument struct, and turns it into an actual Java Array of the same objects.
So first off, we check to see if we already have created an instance - because we only want one, otherwise weird stuff could happen.  If we do, just give back the Java instance we already have.

The next line, is a little bit more complicated, so we'll break it down.

The _getClass().getConstructors() returns an array of all the possible Constructors that are available for this given class.

The _resolveMethodByParams() method takes a array of Method/Constructor objects, the arguments that have been passed through to the given method, in this case 'init', and find the best match that it can, and returns it.  We'll go into the details of that in a minute.

Once we have the right Constructor object, to get an instance of the Object that our JavaProxy represents, we call 'newInstance' on it, and pass in an array of the objects that make up the arguments that the Constructor needs.

And Preso! We have an instance of our Class! We set it to the state of the Class Instance, and return the newly created instance back out.

Wait! What? Return the new created instance? Why aren't we returning this, that doesn't make sense?  Well actually, if you think about it, it does.

We really would prefer it if ColdFusion did all the heavy lifting when it comes to the bridge between Java and ColdFusion, not only is it more performant, but it also provides a greater deal of consistency across the code base.

So we have code that is:
obj = JavaProxy.init();
obj is actually an instance of the ColdFusion JavaProxy, and then there is a much more seamless line between the new CFC JavaProxy, and the use of the ColdFusion one, which is a very good thing.

That being said, we need to provide support for all the different types of ways that Java Objects can be used and created, so we have to also cater for the other aspects as well.

So without further ado, let's actually fire off some methods!  This is where onMissingMethod really comes into it's power!

<cffunction name="onMissingMethod" access="public" returntype="any"output="false" hint="wires the coldfusion invocation to the JavaObject">
    <cfargument name="missingMethodName" type="string" required="true" />
    <cfargument name="missingMethodArguments" type="struct" required="true" />
    <cfscript>
        var method = _findMethod(arguments.missingMethodName, arguments.missingMethodArguments);

        if(_getModifier().isStatic(method.getModifiers()))
        {
            return method.invoke(JavaCast("null", 0), _buildArgumentArray(arguments.missingMethodArguments));
        }
        else
        {
            if(NOT _hasClassInstance())
            {
                //run the default constructor, just like in normal CF, if there is no instance
                init();
            }

            return method.invoke(_getClassInstance(), _buildArgumentArray(arguments.missingMethodArguments));
        }
    </cfscript>
</cffunction>

Okay, so this is the code that actually takes the methods that are called on the JavaProxy, and passes them to the Java instance or Class as appropriate.

The _findMethod() method, returns the Method that best matches the name of the method that was called, and the arguments that it has.  I will go into detail on that in just a second.

Once we have the correct Method, if it is static, we can then invoke it against 'null', and return it's value.

If it isn't static, then we check to see if we have a instance of the Java Class yet, if not, we create one using the default Constructor, which is the same way that ColdFusion does it.

From here, we are able to invoke the method against the class instance, and return any results that we may get.

Now we can look at the logic that allows us to work out which method matches what in ColdFusion.

Our first step, is to look at the _findMethod method, which is actually pretty simple:

<cffunction name="_findMethod" hint="finds the method thatclosest matches the signature" access="public" returntype="any"output="false">
    <cfargument name="methodName" hint="the name of the method" type="string" required="Yes">
    <cfargument name="methodArgs" hint="the arguments to look for" type="struct" required="Yes">
    <cfscript>
        var decision = 0;

        if(StructKeyExists(_getMethodCollection(), arguments.methodName))
        {
            decision = StructFind(_getMethodCollection(), arguments.methodName);

            //if there is only one option, try it, it's only going to throw a runtime exception if it doesn't work.
            if(ArrayLen(decision) == 1)
            {
                return decision[1];
            }
            else
            {
                return _resolveMethodByParams(arguments.methodName, decision, arguments.methodArgs);
            }
        }

       throw("JavaProxy.MethodNotFoundException", "Could not find thedesignated method", "Could not find the method '#arguments.methodName#'in the class #_getClass().getName()#");
    </cfscript>
</cffunction>

The first thing to know is, that _getMethodCollection() returns a struct of arrays that was set up in our _init(), the key of which is the name of the methods found in the class.  The arrays contained in the struct have all the Methods that have that name, as there may be more than one.

So, the first thing we do, is check to see if the name of the method we need is in the collection of methods we have, if it is we go and grab the array of methods this invocation could possibly be.

You will notice that I have written code that states 'if you only have one option for the method, just return that'.  You may be wondering why, as the parameters of that method may not match what has been passed in.  Well, if that is the case, we will get a runtime error, which is the same as what we would get otherwise, so there is not a huge difference here to just say 'let's give this a shot, if it doesn't work, no big deal', and we save the performance hit of comparing parameters.

If there are more than one option available, then we have to start comparing parameters, and this is where the _resolveMethodByParams() method that we saw earlier does it's hard work.

<cffunction name="_resolveMethodByParams"hint="resolves the method to use by the parameters provided"access="private" returntype="any" output="false">
    <cfargument name="methodName" hint="the name of the method" type="string" required="Yes">
    <cfargument name="decision" hint="the array of methods to decide from" type="array" required="Yes">
    <cfargument name="methodArgs" hint="the arguments to look for" type="struct" required="Yes">
    <cfscript>
        var decisionLen = ArrayLen(arguments.decision);
        var method = 0;
        var counter = 1;
        var argLen = ArrayLen(arguments.methodArgs);
        var paremeters = 0;
        var paramLen = 0;
        var pCounter = 0;
        var param = 0;
        var class = 0;
        var found = true;

        for(; counter <= decisionLen; counter++)
        {
            method = arguments.decision[counter];
            parameters = method.getParameterTypes();
            paramLen = ArrayLen(parameters);

            found = true;

            if(argLen eq paramLen)
            {
                for(pCounter = 1; pCounter <= paramLen AND found; pCounter++)
                {
                    param = parameters[pCounter];
                    class = _getClassMethod().invoke(arguments.methodArgs[pCounter], JavaCast("null", 0));

                    if(param.isAssignableFrom(class))
                    {
                        found = true;
                    }
                    else if(param.isPrimitive()) //if it's a primitive, it can be mapped to object primtive classes
                    {
                        if(param.getName() eq "boolean" AND class.getName() eq "java.lang.Boolean")
                        {
                            found = true;
                        }
                        else if(param.getName() eq "int" AND class.getName() eq "java.lang.Integer")
                        {
                            found = true;
                        }
                        ...
                        else
                        {
                            throw("Ack", "Cannot match this primitive type", "'#param.getName()#' is just not matching");
                        }
                    }
                    else
                    {
                        found = false;
                    }
                }

                if(found)
                {
                    return method;
                }
            }
        }

       throw("JavaProxy.MethodNotFoundException", "Could not find thedesignated method", "Could not find the method '#arguments.methodName#'in the class #_getClass().getName()#");
    </cfscript>
</cffunction>

Woah! That's a lot of crazy code... well, it's not too bad once you break it down.

What we are doing is looping around all the possible methods we have available in the decision array, and trying to see if they match the parameters that we have in our argument struct.

First test says, 'if the number of parameters is different, well, we can't invoke this method', and simply passes it by.

From there, we need to loop around each of the parameters, and see if it can work with the class that the corresponding argument that matches it's place.

You're probably looking at the line that reads '_getClassMethod().invoke(arguments.methodArgs[pCounter], JavaCast("null", 0));' and thinking... what on earth does that do?  Well, it allows us to get to the Class object of that argument.

This is very similar to doing a obj.getClass(), however, I can't do that in all instances.  If an argument is a CFC, then it will try and resolve the method 'getClasss' against the CFC, and most likely throw me an error.  So I have to use reflection!

the _getClassMethod() (this was setup in our _init()) is the actually Method class that represents the 'getClass()' method aforementioned, what I then do is invoke it on the required argument, and this gives me back the Class Object I need for comparison.

Now, a Class object has a great method called 'isAssignableFrom', basically, this says 'If the object is a the same as this Class, or a subclass, or implements this interface, return true'.  This means that if the argument in the method that have been invoked on the CF side isAssignable to the parameter that is required for this method, then this method can be invoked successfully.

The other thing we need to do is map primitive parameters, such as int, char, boolean, etc back to their Object representations.  The nice thing is that Java will map this back and forth at runtime for us, so as long as the values match up, we're good to go.

Once the parameters have all been resolved, we can return the method we have found that works, otherwise, we throw an exception.

That pretty much covers the JavaProxy.CFC.  As I said before, you will be able to see the code in action once I release the new version of JavaLoader, but feel free to ask any questions you may have, I will be happy to answer them.
27 August 2007 02:10 PM 0 Comments

Scaffolding a Generic Admin: Now with Transfer!

Paul Marcotte has written an interesting series on how he is building his own administration scaffolding using his own MVC framework, Dispatcher, and Transfer.

In his latest post, he adds Transfer into the mix and shows some good examples of what can be done when retrieving the Meta Data from Transfer about the Objects that are defined within it.
17 August 2007 05:34 PM 0 Comments

CFFrameworks presentation - Developing Applications with Transfer ORM

Nick Tong bullied me into doing another online presentation of my Developing Applications with Transfer talk ;o) So it's all lined up and ready to go for the 30th of August.

Full details can be seen here: http://www.cfframeworks.com/blog/index.cfm/2007/8/16/Workshop-Mark-Mandel---Developing-Applications-with-Transfer-ORM

This presentation will show off the branding for Transfer, which those of your not at cf.Objective probably haven't had a chance to see (and also since I haven't done the new Transfer site I've been promising for millennium)

Depending on how time goes, you may even get sneak peeks at the new Composite Key functionality I'm about three quarters of the way through.

It should also be worth noting that the following month, I will be doing my Advanced Transfer ORM Techniques presentation, which has not been seen outside of cf.Objective before!
15 August 2007 01:12 PM 22 Comments

Would you come to Melbourne CFCAMP?

I need to know some numbers for if we can run a CFCAMP in Melbourne, how many people would be likely to attend.

If you would be able to attend, please add a comment to this blog post, along with how many people you would be able to bring along with you.

I'm currently trying to see what option we have in terms of venue to incite Adobe to bring CFCAMP down to Melbourne, but if there isn't any interest, better we know now!

Ideally this would shortly thereafter the other state's CFCAMP, so please keep that in mind (short lead time, I know, but what can you do?).

I hope we get a large response! :oD
30 July 2007 09:37 AM 2 Comments

ColdFusion 8 Launch Party - 8th Aug - Melbourne

All! It's a special CF8 Launch party!!!!

Location:

NGA.net, Level 2, 17 Raglan St, South Melbourne
Map: http://link.toolbot.com/google.com/73016

When:

8th of August, Meeting starts at 6:30, so get there before hand -
** Please note, we are starting a little bit early this time, due to the crossover between states.

Agenda:

This is the official ColdFusion 8 Launch Party!

We will have presentations from Ben Forta via Connect, crossovers between the launch parties at all the other CFUGs across Australia and New Zealand, and prizes from Adobe for those people that attend!

Everyone is welcome, and if you haven't attended a single CFUG meeting yet, now is the time to come down!

If you are going to attend, please RSVP to mark [dot] mandel [at] gmail [dot] com.

See the CFUG Melbourne Calendar at:
http://www.cfcentral.com.au/Events/index.cfm

Or add to your Google Calendar - search for 'CFUG Melbourne'.

As per usual, we'll grab pizza during the evening, so we have
something to scoff down!

Look forward to seeing you all there.
23 July 2007 02:47 PM 0 Comments

How to Ask Questions the Smart Way

This is a FAQ that was first written back in 2004, and has been updated ever since, but outlines what I believe to be the best way to ask questions on technical forums.

I think it's important to post it up, every now and again, so that people remember that it exists for a reason ;o)

How to Ask Questions the Smart Way
18 July 2007 10:23 AM 0 Comments

TQL Lexicons for Fusebox


Nick Tong over at Succor has posted a Fusebox lexicon for using TQL !  Pretty neat stuff!

If you like Fusebox, and you like Transfer, I suggest having a look.

I have to say, it's really cool watching all these framework work together... ;o)

OMG! I've sold out!

Yes, it's true, I've finally succumbed, and put ads on my site, and switched out the wishlist for a PayPal donate button.  I have finally turned to the dark side.

Do not fear! There are reasons for this!

First of all, the Amazon wish list, didn't really work out.  I'm sure people thought 'I'll buy Mark something from the wishlist, he'll like that', and then quickly realised it can be up to $30 to send stuff to Australia, and that whole idea quickly went out the window.

Second of all, I really want to get out to more conferences overseas.  Unfortunately, while living in Australia is wonderful, we are about as far away from anyone as can possibly be.  This means that travelling can be real