ColdFusion 8 + JavaLoader: IsInstanceOf (In this intance, NO)
No?
In a previous entry I mentioned the new POI beta supports ooxml files. I was exploring how to extract metadata from the new file format when I ran into a gotcha with ColdFusion's IsInstanceOf function.Since my code required the latest version of POI, I used the JavaLoader.cfc to create my objects. But whenever I passed those objects into the IsInstanceOf function, it always returned false. At first I thought it was because I was using a different version of POI. But I got the same results when using the POI jar that is built into ColdFusion 8.
After re-checking the documentation, I realized it clearly says java objects must be "created by using the cfobject tag or createObject method". So I took that to mean I could not use it with objects created by the javaLoader.
Now, I do not know how CF's IsInstanceOf function is implemented. But I would assume it is similar to java's instanceof operator and is probably tied to the underlying classloader. As I understand it, createObject and the javaLoader.cfc use different classloaders. So I guess it would make sense that IsInstanceOf would not work with objects created by a different classloader.
Anyway, I just thought I would mention it in case anyone else falls into the same trap.
Are you sure?
Since it seemed I could not use IsInstanceOf, I decided to try java's isInstance method instead. (If you are not familiar with it, it is a method of java.lang.Class) Now, isInstance worked fine for the objects created with the JavaLoader. But I noticed something strange when using it with objects returned by createObject.When I created an object, but did not instantiate it, java's isInstance method returned false. Only when I instantiated the object first did isInstance return true. Take this example. It creates a POI HSSFWorkbook object. Then checks if the object is an instance of HSSFWorkbook. Since I am comparing the object to itself, of course the result should be "yes". But the result is "no", unless the object is instantiated first.
<!---
RETURNS "NO" when the object is NOT instantiated
--->
<cfset wb = createObject("java", "org.apache.poi.hssf.usermodel.HSSFWorkbook") />
<cfoutput>
(NOTE instantiated) isInstance = #wb.getClass().isInstance(wb)#<br/>
</cfoutput>
<!---
RETURNS "YES" when the object IS instantiated
--->
<cfset wb = createObject("java", "org.apache.poi.hssf.usermodel.HSSFWorkbook").init() />
<cfoutput>
(IS instantiated) isInstance = #wb.getClass().isInstance(wb)#<br/>
</cfoutput>
I am not sure why this happens. But I guess the lesson learned from this is be careful with your IsInstanceOf and isInstance checks. The answer might surprise you.
4 comments:
My first guess is that the difference in what you get back from isInstance is because the CF Objects don't have a true constructor. So really you are just setting it up when you run CreateObject. But then when you call your init() method, your init method is most like doing a "return this" which returns an instance of the object. Until that constructor is run nothing returns the instance of the object and therefore isInstance says it isn't an instance yet.
@Judah,
Your guess is spot on! I suspected some kind of wrapper was used. But could not figure out what it was. It turns out it is JavaProxy.
<cfset wb = createObject("java", "org.apache.poi.hssf.usermodel.HSSFWorkbook")>
<cfset proxy = createObject("java", "coldfusion.runtime.java.JavaProxy").init(wb.getClass())>
<cfoutput>
proxy.getClass().getName() = #proxy.getClass().getName()#<br/><br/>
</cfoutput>
Courtesy of:
http://www.compoundtheory.com/?ID=114&action=displayPost
Cheers
One of the basic security ideas of Java is that the objects loaded by one class loader cannot interact with objects loaded by another class loader. So things loaded by ColdFusion, through createObject, will not be able to interact with anything loaded through the URLClassLoader.
@Phil,
Yes, and vice versa. In this case there was also the additional issue of the JavaProxy throwing off the results as well.
-Leigh
Post a Comment