Adam Howitt's Blog

Mar 02
2005

Eclipse uncovers ColdFusion's Secret Powers

If you have ever seen a tech tip about ColdFusion leveraging the built in hidden methods of Java and wondered "how the heck do they know this stuff?", Eclipse can help you see the wizard behind the curtain.

Yesterday I was doofing around trying to discover a way to access the SQL statement passed by cfquery and cfstoredproc so I could log it on my production server without duplicating the code block. I figured, if CF knows what the parsed statement is, why can't I access it after the statement executes as, say, cfquery.parsedSqlStatement. I know it exists because if my code errors, I see it in the resulting error dump.

I started out looking for posts that utilize some of these hidden Java methods and came across Sam's post on "Handling file uploads without CFFILE". The important snippet was
cls = s.getClass();
stringCLass = cls.forName("java.lang.String");
Armed with this info I started to experiment by dumping out the stringClass variable to see the list of methods.

Next I threw a DB error deliberately and expanded the stack trace to get a list of CFClasses which were involved in the error. I constructed this little test:

<cfquery datasource="ll_site" name="qTest">
select * from object_tb
</cfquery>
<cfset cls = qTest.getClass()>
<cfdump var="#cls.getName()#">
<cfset stringClass = cls.forName("coldfusion.sql.QueryTable")>
<cfdump var="#stringCLass#">

Unfortunately my research stopped there because there just wasn't much to see. No properties or methods easily listed to help me on my quest. This was when I had a brainwave. Eclipse is a Java development tool, ColdFusion comes as a deployable ear file and has a list of classes: maybe Eclipse can see more than just a .ear file!

So I opened Eclipse, created a new Java project and set the location of my EAR file as the directory under "Create project at external location". Create a name for the project and hit Finish. Eclipse then prompted me to switch to the Java perspective (from CFEclipse which is my default) and to my amazement, I see a list of jar files and packages! I click to expand cfusion.jar and it expands to show me a list of coldfusion packages. I click to expand coldfusion.sql and I see a list of classes and properties. I expand SqlImpl.class and see methods and properties which I may be able to leverage.

So I'm still no closer to getting the exact SqlStatement because I'm still unsure as to how to access the property I need. If anyone following these steps is able to point this out I would greatly appreciate it.

Now THAT is something Homesite and Dreamweaver can't do ;-)

Comments (Comment Moderation is enabled. Your comment will not appear until approved.)
[Add Comment] [Subscribe to Comments]
  1. I don't remember the variable off hand, but if you turn on debugging, you can access the parsed SQL. If you look at the default debugging template, the referenced var is there.

    Also, in CF 7, the SQL is now returned as part of the cfquery object.

  2. I'm gonna repost this little blurb from a cfcdev discussion about cfquery:

    ">>> lists@midn.co.uk 2/23/2005 10:25:55 AM >>> the "hidden" features are actually java? so it doesnt matter if CF changes, only if the java implementation changes? raising the possibility that the undocumented features could be more stable than the documented ones? :)"

    I replied:

    "well, in a way, yes. Since coldfusion.sql.QueryTable implements javax.sql.rowSet (a subinterface of java.sql.ResultSet), methods defined in that interface *should* always work on cf query objects. That's not to say that MM can't provide a new implementation under the hood that DOESN'T implement java.sql.ResultSet, but does satisfy the requirements of CFQUERY. My reccomendation is "use sparingly" (aka, when you MUST have that functionality)."

    I think it's important that people know:

    a) Why undocumented methods work: because everything in CF is a java object under the hood.

    b) Why using them is a bad idea (in most situations): because MM can change the underlying implementation without breaking the "published" functionality of CFML.

  3. Don't forget that in CFMX7, you get access to the SQL info automatically now in the "result" variable. Ie, cfquery name="foo" datasource='goo" result="moo", the moo structure will contain it. Y

  4. Oops, I totally missed Rob's second paragraph.

  5. There is a thread about it on Ben Forta's blog http://www.forta.com/blog/index.cfm?mode=e&entry=1520

    Cheers/pim

[Add Comment]