ColdFusion true is not a Java boolean

None of these ColdFusion constructs strictly equate to a true-valued Java boolean (or Boolean):

true
"true"
1
YES

But this does:

JavaCast("java.lang.Boolean", true);

Makes me wonder what ColdFusion’s literal true (no quotes) actually is. Probably just a string.

Edit prompted by Todd:
Definitely just a string. And definitely not a boolean. Also not particularly suprising but something I’d never thought about is the fact that ColdFusion “is” is not the same as Java “equals”.


a = true;
b = CreateObject("java","java.lang.Boolean").init("true");
c = "true";



	a = true;
b = CreateObject("java","java.lang.Boolean").init("true");
c = "true";



b.equals(a) #b.equals(a)#
a.equals(b) #a.equals(b)#
b.equals(JavaCast("boolean",a)) #b.equals(JavaCast("boolean",a))#
b is a #b is a#
a is b #a is b#

a.equals(c) #a.equals(c)#
c.equals(a) #c.equals(a)#
a is c #a is c#
c is a #c is a#

b.equals(c) #b.equals(c)#
c.equals(b) #c.equals(b)#
b is c #b is c#
c is b #c is b#

gives this:

a = true;
b = CreateObject("java","java.lang.Boolean").init("true");
c = "true";

java.lang.String

b.equals(a) NO
a.equals(b) NO
b.equals(JavaCast("boolean",a)) YES
b is a YES
a is b YES

a.equals(c) YES
c.equals(a) YES
a is c YES
c is a YES

b.equals(c) NO
c.equals(b) NO
b is c YES
c is b YES

Multiple datasources

It’s been stated that a weakness of CF9 ORM is that it only allows one ORM datasource. You can use other datasources via cfquery. It’s worth understanding why this is so. It certainly wasn’t left out arbitrarily.

In a nutshell, default CF9 ORM only allows one datasource because it wraps each request in a transaction. Generally speaking, this is a good idea, but it’s a characteristic of standard database transactions that each is tied to a single database connection. This is generally true, not just specific to ColdFusion datasources. It’s also why cftransaction only allows queries from one datasource within the transaction body.

I gave myself a couple of escape hatches in the preceding paragraph – I said “default” CF9 ORM and “standard” database transactions. Does that mean non-default CF9 ORM with non-standard transactions does allow multiple datasources? Why, yes it does! But be aware that this is a non-standard usage model. Not only do you need to delve into the underlying Hibernate configuration to make it work, many scenarios are not even standard practice within the Hibernate world.

I’m not going to write a how-to on CF9 ORM with multiple datasources, but I will provide some pointers to how this might be done.

  1. Delve into the underlying Hibernate and turn off the transactions. Non-transactional code is fairly common in plain CFML apps. This sort of thing is a large part of why “scripting” language developers are regarded as cowboys by “serious” (read Java) developers, but it can be a valid solution in some circumstances.
  2. Use XA datasources with a JTA transaction manager for true distributed transactions. There’s a succinct example for this in Java here. This is common practice in the J2EE world, but pretty outre for CF. For a start, you’ll have to find XA datasources for your database and replace ColdFusion’s built-in datasources. You may also need to configure your database server to participate in distributed transactions.
  3. Roll your own transaction manager in Java and plug it into Hibernate. There are any number of people out there in the Java world with strange use cases attempting just this. Google “hibernate multiple datasources” for some interesting and somewhat desperate reading. Or not 🙂
  4. Use CF9 ORM in its default transactional mode for your main datasource with non-transactional access (e.g. cfquery) to secondary datasources. You don’t have to completely give up on data integrity, though. Schedule a task to check data integrity and issue compensating transactions where necessary.

There are some other possibilities, but that should be enough to get my basic points across. Firstly, this isn’t really a CF9 or even a Hibernate issue. And secondly, you really only have a choice between either relaxing your transactional guarantees (options 1 and 4), or doing a lot more work (options 2 and 3).

Transactions – optional?

No. Transactions are not optional.

One of the things that irked me in learning Hibernate was the amount of time spent worrying about transactions. Indeed, when I speak about Spring/Hibernate implementation models to ColdFusion developers, I get the same reaction that I initially had myself – “Why do you keep talking about transactions? We know what they are, it’s kind of interesting, but this is hardly a central concern.”

Coldfusion database connections are in autocommit mode by default. The Hibernate guys wrote an excellent article on autocommit. Essentially it means you automatically get a transaction per <cfquery>.

This is a good thing. The CF server can’t possibly decide on a transaction strategy for you, so it can only do one of two things:

  • Turn on autocommit so you can get coding
  • Turn off autocommit so you must implement a transaction strategy before you can run a single query. Alternatively, you can work out how to turn autocommit back on.

Given ColdFusion’s RAD focus, which do you think CF is going to choose? It’s going to let you get coding.

Unfortunately, many of us take that as permission to put off thinking about a transaction strategy indefinitely. Can you actually put your hand on your heart and say “No, data consistency is not important to my application”? Probably not. But if you’re like me, you might be able to let your application slide across the line from prototype to production without really addressing this issue.

Hibernate, which is much more interested in being right than being RAD, starts from the other position. Work out your transaction strategy. Then we’ll talk. Autocommit mode is available if you really need it, but is off by default and is considered a non-standard usage model.

So no, transactions aren’t optional. Hibernate smacks you over the head with this fact, so if you’ve been letting this aspect of your applications slide, you’ve got some catching up to do.

Note: CF9 ORM in its default configuration does in fact choose the transaction-per-page-request strategy for you. This is a bit of a philosophical departure from the default cfquery behaviour, but I think it manages to walk the line between CF RAD culture and Hibernate “serious software engineering” culture.

Non-standard usage model

You’re the chief technologist of Webz R Us. You’ve been around, used a few different languages. You think in the abstract and can adapt to the specific implementation. You can make ColdFusion sing and dance. Now you’ve given yourself the task of getting Spring and Hibernate up and running with your ColdFusion web apps. You’re not using CF9 ORM – you’re going to roll your own for ultimate control.

It’s natural to think that you can take your accumulated wisdom and cherished practices and tweak them a bit for this new implementation technology. If you’re a JEE web app developer, that might be true. If you’re a ColdFusion developer, it almost certainly is not.

So after a train-wreck or two, you jump onto the forums – this is open-source software with a vibrant community, right? – and explain your cherished practices, why they’re so great, and ask for help on that one little API that you need to make everything fall into place. It’s so obvious to you that this should work. You’ve been doing it for years in ColdFusion. In Java, with all these great frameworks, your cool approach should be even better supported and easier to do.

And what you’re told is:

That’s a non-standard usage model

Let me translate that for you:

  • What a dumb idea
  • Even if it works, nobody cares
  • Go read the documentation
  • You n00b

OK, I’m being a bit harsh here. Let me try another translation:

  • 99% of successful projects don’t use your technique
  • Maybe you should think about why that is so
  • You really do have an edge case? Time to man up and earn those big bucks. Good luck.

I love the quote below. The guy who wrote this really had put in the hard yards to understand the questioner’s use case – this was by no means a brush-off:

How about you just trust what Hibernate is doing, because it always has very good reasons for its very sophisticated caching behavior, and the people who designed this stuff have spent a lot, lot more time thinking about caching and transactions than you have.

I didn’t post this just to be amusing. I’ll be referring to this post a lot in the coming months. You won’t believe how many non-standard usages I’ve been able to come up with. Stay tuned…

Coldfusion datasources

A CF datasource is basically a connection pool that will hand you a database connection preconfigured with the datasource’s parameters (username, password, default database, URL, etc.) whenever you ask for it.

There’s no guarantee that consecutive cfquery tags with the same datasource will get the same connection. This matters a lot if you’re using temporary tables, which are specific to a connection. For example, with the following SQL Server code you may get a “table not found” error on the second query:


	select *
	from users
	into ##tempusers



	select *
	from ##tempusers

This may or may not work. It’s luck of the draw, and it’s dependant on load.

Temporary tables are dropped when the connection is closed. As you can configure ColdFusion to keep connections open, you may find yourself inheriting connections with some other request’s dirty laundry flapping around. Not a good look.

This picture changes if you are using <cftransaction>. Normally *, transactions are intrinsically tied to database connections. This is a characteristic of relational databases, not specific to ColdFusion or JDBC. For a <cftransaction> block to work at all, ColdFusion has to guarantee that you get the same connection for all queries within that block. You can safely use temporary tables within a transaction – just make sure you drop them when you’ve finished.

This isn’t really a post about temporary tables. They’re just a good way to demonstrate what’s going on with datasources. The relationship between datasources, connections and transactions has some important consequences for how and when you can use multiple datasources within a page.

Note:
Normally – unless you are using distributed transactions. This is definitely not normal in the ColdFusion world, and is the subject of another post.

cfobjective(ANZ) demo code

I’ve made the demo code from my cfobjective presentation available here:

http://lagod.id.au/downloads/cfobjective_codedemo.zip

There are two folders in the zip. One is the eclipse project, the other is the eclipse workspace. You should just be able to import the project into your own workspace, but just in case I’ve given you the workspace I used.

If you just want to look at the code, read no further. If you want to run stuff, you’ll need to tweak some things, and there are some caveats. I made these assumptions:

  • the project is at /home/owner/cfobjective/springhibcfdemo
  • the coldfusion install is at /home/owner/coldfusion8
  • it’s a standard ColdFusion 8 install, NOT multiserver
  • you’re running the built-in webserver – not critical, if not you’ll have to set up your own virtual directories

If you search the project for “/home/owner” you’ll find everything that might need to be changed.

Now the caveat:

THE BUILD SCRIPT WILL OVERWRITE YOUR COLDFUSION CONFIGURATION

Don’t be afraid – just don’t run the build script if you’re not cool with that. I’d recommend you run up a throwaway ColdFusion dev install and point the build script at that.

The build script will create virtual directories for the JRun webserver. Have a look at jrun-web.xml for details.

That’s about it. You don’t need a database, all the necessary jar files are included, and the CF built-in webserver should be OK for these purposes.

cfobjective(ANZ) presentation

If you haven’t heard yet, cfobjective (ANZ) was awesome. It was an honor to be included among the speakers. Full credit to Jim, Mark and the rest. Last I saw they were cracking open a well earned bottle of champagne.

I think I scared a few people with my java integration horror stories. It really wasn’t meant to give people nightmares, but I think having a list of gotchas can really help when you hit a wall. To that end, I’ve made my preso available at:

http://lagod.id.au/downloads/CFObjective_Jmetcher3.pdf

There is an error in this preso, which I haven’t corrected but I’ll tell you about here. I said that classes on the java class path (i.e. coldfusion/runtime/lib) aren’t visible to CreateObject(). That’s not correct in general. It only holds true for specific packages, and really won’t be a concern for your own domain models.

Tom Jordahl talks about this tangentially in this post about Apache CXF. Make sure you check out the comments at the end, and for extra credit have a look at cfmx_bootstrap.jar, which you’ll find in coldfusion8/wwwroot/WEB-INF/lib.

In practice I never instantiate any domain object within ColdFusion, which is why I was a bit fuzzy (well, wrong actually) on this point.