Don't you love people who reply to their own posts? :) Anyhow, I did
find a solution lurking on the JavaLoader forums, and I hope this code
snippet helps someone in the future. Basically, this thread was the
important one:
http://groups.google.com/group/javaloader-dev/msg/9ac22919da73324f
Basically, ThreadContextClassLoader in combination with dom4j = problem
for JavaLoader. Mark's solution is to find out the current thread's
ClassLoader, and replace it with the one from JavaLoader. After bouncing
my CF 9 Application services, this code snippet works for me. I hope it
helps somebody else out in the future:
<cfoutput>
<cfset var.JLKey = "93345778-4949-4725-1235577891134557" />
<cfset var.paths = []>
<cfset var.jarpath = "/Users/mstaver/workspace/Fimble/ExternalCode" />
<cfdirectory action="list" name="files" directory="#var.jarpath#"
filter="*.jar" recurse="true" />
<cfloop query="files">
<cfset arrayAppend(var.paths, directory & "/" & name) />
</cfloop>
<cfif NOT structKeyExists(server, var.JLKey)>
<cfset server[var.JLKey] = createObject("component",
"component.JavaLoader").init(loadPaths=var.paths,
loadColdFusionClassPath=true) />
</cfif>
<cfscript>
_Thread = createObject("java", "java.lang.Thread");
currentClassloader = _Thread.currentThread().getContextClassLoader();
try { // Set the current thread's context class loader as Javaloader's
classloader, so dom4j doesn't die
_Thread.currentThread().setContextClassLoader(server[var.JLKey].getURLClassLoader());
fileAndPath = "/Users/mstaver/workspace/Fimble/11g.xlsx";
inp = createObject("java",
"java.io.FileInputStream").init("#fileAndPath#");
objWorkBook =
server[var.JLKey].create("org.apache.poi.xssf.usermodel.XSSFWorkbook").Init(inp);
}
catch(Any exc) {
rethrow;
}
finally { // We have to reset the classloader, due to thread pooling.
_Thread.currentThread().setContextClassLoader(currentClassloader);
}
</cfscript>
</cfoutput>
On 11/28/11 2:45 PM, Mike Staver wrote:
Ok, so I did some digging on Mark's JavaLoader forums. I found an
error further down my stack that seems to be common:
org.dom4j.DocumentFactory cannot be cast to org.dom4j.DocumentFactory
Mark's suggested method of loading JL is:
<cfset server[var.JLKey] = createObject("component",
"component.JavaLoader").init(loadPaths=var.paths,
loadColdFusionClassPath=true) />
That still didn't work for me. In yet another thread, he suggests:
" Make sure when you create your instance of JL, you tell it to use CF
as the parent classloader. Then you should have no issues. Mark"
I see the additional parameter for JL called parentClassLoader. Yet,
I'm dense sometimes and I can't figure out what should go there...
Being that he is in Australia, I don't see him answering my email
until later tonite :)
So, I envision calling JL like so:
<cfset server[var.JLKey] = createObject("component",
"component.JavaLoader").init(loadPaths=var.paths,
loadColdFusionClassPath=true, parentClassLoader=???) />
I have no idea what to put for the value in that third parameter.
Would it be a reference to the classes inside of my CF install in
D:\ColdFusion9\?
On 11/24/11 10:56 AM, Mike Staver wrote:
Thanks Charlie and Dawn. I definitely have just one version of poi in
that folder at a time. I typically load up those jars in the
onApplicationStart in the application.cfc. However, in the example I
provided I'm doing everything in one place. I will see what I can
find on the java loader forums. Thanks.
-Mike
On Nov 24, 2011, at 10:13 AM, Dawn Hoagland <[email protected]
<mailto:[email protected]>> wrote:
I did note in your java loader code that you're loading all of the
jars in that subdirectory. Any chance you have multiple versions of
POI there?
Looking over the java docs, try this:
*org.apache.poi.POIXMLProperties.CoreProperties.getRevision()*
On Thu, Nov 24, 2011 at 11:48 AM, Mike Staver <[email protected]
<mailto:[email protected]>> wrote:
Interesting. Since I'm using the same code on two different
systems and getting the same results - is there any way I can
see what is loaded in memory currently?
-Mike
On Nov 24, 2011, at 7:46 AM, Dawn Hoagland
<[email protected] <mailto:[email protected]>> wrote:
I've seen this happen when multiple versions of the library are
being loaded into memory. CF/Java SHOULD pick the one loaded
with the Javaloader, but doesn't always. I've seen this happen
when multiple versions of POI have been dropped in CF's lib
folder as well. When stuff like this happens, I write/test in
java only to eliminate issues with POI.
On Wed, Nov 23, 2011 at 9:35 PM, Mike Staver <[email protected]
<mailto:[email protected]>> wrote:
I've always been able to use POI via JavaLoader to read in
standard xls files and extract data out of the cells for
whatever I want, like storing in a database. Recently, I've
had to start coding to handle Office 2007 file formats like
xlsx and xlsm. POI 3.5 and higher should be able to do that
according to many examples I've found on the internet and
in Apache's own documentation. So, I'm currently using
ColdFusion 9, JavaLoader 1.0, and POI 3.8b4. For the
record, I've also tried POI 3.6 and 3.7 for this test and
sample code below. Here is my sample code:
<cfoutput>
<cfset var.JLKey = "93345778-4949-4705-1235577891134557" />
<cfset var.paths = []>
<cfset var.jarpath =
"/Users/mstaver/workspace/Fimble/ExternalCode" /> <!---
location of POI jars --->
<cfdirectory action="list" name="files"
directory="#var.jarpath#" filter="*.jar" recurse="true" />
<cfloop query="files">
<cfset arrayAppend(var.paths, directory & "/" & name) />
</cfloop>
<cfif NOT structKeyExists(server, var.JLKey)>
<cfset server[var.JLKey] = createObject("component",
"component.JavaLoader").init(loadPaths=var.paths,
loadColdFusionClassPath=false) />
</cfif>
<cfscript>
fileAndPath = "/Users/mstaver/workspace/Fimble/11g.xlsm";
inp = createObject("java",
"java.io.FileInputStream").init("#fileAndPath#");
objWorkBook =
server[var.JLKey].create("org.apache.poi.xssf.usermodel.XSSFWorkbook").Init(inp);
</cfscript>
</cfoutput>
When I write use this code with one small tweak (HSSF
instead of XSSF) and I feed in an xls file, everything
works as expected. However, when I use the exact code above
and feed it xlsx or xlsm, I get this error:
Object instantiation exception.
An exception occurred while instantiating a Java object.
The class must not be an interface or an abstract class.
Error: ''. The error occurred in
*/Users/mstaver/workspace/Fimble/test.cfm: line 18*
*Called from*
/Users/mstaver/workspace/Fimble/Application.cfc: line 97
*Called from* /Users/mstaver/workspace/Fimble/test.cfm: line 18
*Called from*
/Users/mstaver/workspace/Fimble/Application.cfc: line 97
16 : fileAndPath = "/Users/mstaver/workspace/Fimble/11g.xlsm";
17 : inp = createObject("java",
"java.io.FileInputStream").init("#fileAndPath#");
*18 : objWorkBook =
server[var.JLKey].create("org.apache.poi.xssf.usermodel.XSSFWorkbook").Init(inp);*
Further down the error stack, I think this is relevant:
Caused by: java.lang.NoClassDefFoundError: Could not initialize class
org.apache.poi.openxml4j.opc.internal.unmarshallers.PackagePropertiesUnmarshaller
I don't know where to go on this one. I've tried the SS
method, instead of XSSF - and it works fine, until I feed
it an xlsx or xlsm again. I don't get it. I've also tried
this on Windows 2003, besides here on my Macbook. Both
machines are running CF 9.0.1. I'm getting the impression
that I'm missing a class or something. I've followed
examples from all over the web, and from the POI docs.
Everything works until I feed it Office 2007 format docs...
-------------------------------------------------------------
To unsubscribe from this list, manage your profile @
http://www.acfug.org?fa=login.edituserform
For more info, see http://www.acfug.org/mailinglists
Archive @ http://www.mail-archive.com/discussion%40acfug.org/
List hosted by FusionLink <http://www.fusionlink.com>
-------------------------------------------------------------
--
Dawn
--
Dawn
-------------------------------------------------------------
To unsubscribe from this list, manage your profile @
http://www.acfug.org?fa=login.edituserform
For more info, see http://www.acfug.org/mailinglists
Archive @ http://www.mail-archive.com/discussion%40acfug.org/
List hosted by FusionLink <http://www.fusionlink.com>
-------------------------------------------------------------
-------------------------------------------------------------
To unsubscribe from this list, manage your profile @
http://www.acfug.org?fa=login.edituserform
For more info, see http://www.acfug.org/mailinglists
Archive @ http://www.mail-archive.com/discussion%40acfug.org/
List hosted by http://www.fusionlink.com
-------------------------------------------------------------