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. Usability / UI Design
  20. cf.Objective()
  21. webDU
  22. cf.Objective(ANZ)
  23. Captcha
  24. MAX
  25. Melbourne CFUG
  26. Martial Arts
  27. Random Things

Recent Posts

Projects

Instant Message

Instantly grab my attention...

Recent Comments

10 February 2007 06:34 PM

Issue with cfcatch and JavaLoader

This is an issue I came across yesterday while doing some work on Transfer that affects JavaLoader , and generally anything that uses an URLClassLoader to load any external class/jar files.

The issue lies with catching Java exception with <cfcatch>.  The documentation states, that to catch a thrown Java exception you can specify the type in the 'type' attribute of the <cfcatch> tag.  So if we wanted to catch a java.io.IOException, we would do so this way:

<cftry>
   <!--- do some stuff that may throw an exception --->
    <cfcatch type="java.io.IOException">
        <!--- do something with it --->
    </cfcatch>
</cftry>

Now the issue comes when you are using JavaLoader (or anything that utilises any sort of URLClassLoader) and the loaded Java code throws an exception that hasn't been loaded with ColdFusion at start up -

<cfcatch> can't catch the Java Exception by it's specific type!
 
To show you what I mean, I created a simple test bed.

I create a new Java Exception object, 'com.compoundtheory.test.myException', and a class called 'MyThrower' who's sole job was to throw this exception.

Just to note 'jl' is the JavaLoader instance that has loaded my classes.

My test bed looked like this:

<cftry>
    <cfscript>
        myThrower = jl.create("com.compoundtheory.test.MyThrower").init();

        myThrower.myThrow();
    </cfscript>
    <cfcatch type="com.compoundtheory.test.myException">
        full
        <cfdump var="#cfcatch#">
    </cfcatch>
    <cfcatch type="java.lang.Exception">
        java.lang.Exception
        <cfdump var="#cfcatch#">
    </cfcatch>
    <cfcatch type="any">
        any
        <cfdump var="#cfcatch#">
    </cfcatch>
</cftry>

The result that came from this was that 'java.lang.Exception' was output onto the screen.  This means that the ColdFusion <cfcatch> statement bypassed the 'com.compoundtheory.test.myException' type (which is its real type) and caught it at the 'java.lang.Exception' level, which is what 'myException' extends.

This led me to believe that the ColdFusion <cfcatch> can only catch exceptions that are loaded in its class path on start up.  To this effect I had two more test beds.

The first test was to get my JavaLoader loaded class to throw a 'java.io.IOException' - an exception that is native to Java 1.4, which comes with ColdFusion, and is loaded when ColdFusion starts.

The test bed looked like this:

<cftry>
    <cfscript>
        myThrower = jl.create("com.compoundtheory.test.MyThrower").init();

        myThrower.myThrowIOException();
    </cfscript>
    <cfcatch type="java.io.IOException">
        full
        <cfdump var="#cfcatch#">
    </cfcatch>
    <cfcatch type="java.lang.Exception">
        java.lang.Exception
        <cfdump var="#cfcatch#">
    </cfcatch>
    <cfcatch type="any">
        any
        <cfdump var="#cfcatch#">
    </cfcatch>
</cftry>

In this case, 'full' was output, that meaning that the <cfcatch> was able to the exception with the type 'java.lang.IOException', just as it was meant to do.

The final test was when I moved my created classes into the ColdFusion class path, restarted the server, and ran my tests again.

The test bed now looked like this:

<cftry>
    <cfscript>
        myThrower = createObject("java", "com.compoundtheory.test.MyThrower").init();

        myThrower.myThrow();
    </cfscript>
    <cfcatch type="com.compoundtheory.test.myException">
        full
        <cfdump var="#cfcatch#">
    </cfcatch>
    <cfcatch type="java.lang.Exception">
        java.lang.Exception
        <cfdump var="#cfcatch#">
    </cfcatch>
    <cfcatch type="any">
        any
        <cfdump var="#cfcatch#">
    </cfcatch>
</cftry>

In this case, the output was 'full', that meaning that the <cfcatch> could catch the custom exception, as it had been loaded with the ColdFusion library at start up.

So what does this all mean? Does it mean you can't use libraries with custom exceptions in them? No it does not.  But it does mean you need to handle them in a slightly different way when using JavaLoader.

The solution to this problem is to write code that looks like this:

<cfcatch type="java.lang.Exception">
    <cfswitch expression="#cfcatch.Type#">
    <cfcase value="com.compoundtheory.test.myException">
        <!--- do something with it --->
    </cfcase>
    <cfdefaultcase>
        <cfrethrow>
    </cfdefaultcase>
    </cfswitch>
</cfcatch>

The nice thing is that the 'type' attribute on the cfcatch variable will be set properly to the type of the Java Exception, so we can use it as a sort of 'filter' to weed out the Exceptions we wish to handle, and rethrow the ones that we don't.  It's not the prettiest thing in the world, but it works.

I'm not sure if I classify this as a bug in ColdFusion, but it definitely is an issue if you're not sure how to resolve it.


Comments

Posted by Dipak Parikh on 12 February 2007 06:26 PM

Hi,
I am planning to use Hibernate within ColdFusion.
As hibernate has different versions of commons-logging and log4j, I was thinking if I can use JavaLoader to load Hibernate & related .jar from other location.
Can you tell me, how cfcatch issue would affect in using Hibernate?
Have anyone tried using Hibernate from within ColdFusion with success?

Posted by Mark on 12 February 2007 07:11 PM

Dipak,

Some people have definatley got Hibernate to work with ColdFusion. I've done some testing with JavaLoader and Hibernate, and it worked a treat. You can see the details at the CFHibernate Yahoo group
http://tech.groups.yahoo.com/group/cfhibernate/

As to whether or not this will be an issue for you, depends on how your application is designed. But you use the technique above to make sure that your error handling works correctly.

Posted by Adam Fortuna on 20 February 2008 11:11 PM

Extremely useful article man. Helped me figure out what in world ColdFusion was doing with those errors. Thanks!

Add Comment