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!
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:
-
before some query executions
-
from org.hibernate.Transaction.commit()
-
from Session.flush()
So what does that actually mean in terms of ColdFusion?
- 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.
- 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.
- 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.
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:
- opening a Session, i.e. we tell Hibernate 'Hi', which starts our conversation.
- Tell Hibernate to retrieve our Caveman fred, through our session.
- We change the age of fred to 32.
- 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.
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.
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!