cfsimplicity / spreadsheet-cfml

Standalone library for working with spreadsheets and CSV in CFML
MIT License
127 stars 36 forks source link

java.io.FileInputStream incompatible with org.apache.poi.openxml4j.opc.OPCPackage #213

Open ivanionut opened 3 years ago

ivanionut commented 3 years ago

Hello @cfsimplicity, I'm having an error in the production environment but in my development environment (which uses the same stack) it works fine.

Version: Lucee 5.3.8.138-SNAPSHOT
Servlet Container: Apache Tomcat/9.0.19
Java: 11.0.8 (AdoptOpenJDK) 64bit
OS: Linux (4.15.0-130-generic) 64bit
LuceeSpreadsheet: 2.13.0

this is the error:

java.lang.ClassCastException Error: java.io.FileInputStream incompatible with org.apache.poi.openxml4j.opc.OPCPackage 
  File "com/spreadsheet/Spreadsheet.cfc", line 1842
    return loadClass( className ).create( file );
  File "com/spreadsheet/Spreadsheet.cfc", line 1280
    var workbook = passwordProtected? workbookFromFile( arguments.src, arguments.password ): workbookFromFile( arguments.src );
  File "model/services/catalog.cfc", line 60
    variables.q_catalog = spreadsheet.read(src=variables.local_path_catalog, headerRow=1, format="query");
  File "controllers/schedule.cfc", line 41
    rc.updateCatalogo = recorditService.updateCatalog();
  File "framework/one.cfc", line 1635
    invoke( cfc, method, { rc : request.context, headers : request._fw1.headers } );
  File "framework/one.cfc", line 896
    doController( tuple, tuple.item, 'item' );

error

what am I doing wrong?

cfsimplicity commented 3 years ago

Hi Ivan. I don't really know. I've run the test suite with that version of Lucee and it passes ok. There must be a difference somewhere between your environments.

Are you reading the same spreadsheet file in both dev and production? Is it an xls or xlsx file?

ivanionut commented 3 years ago

hi. yes, I confirm, I read the same file, the xlsx file exists and the complete path is correct.

I thought about a permissions issue and set permissions 777 on the xlsx file, but it didn't solve. what other tests could I do?

cfsimplicity commented 3 years ago

Sorry, I don't know what else to suggest. The OPCPackage class is internal to POI, but if the environment and parameters are the same then I would expect it to behave in the same way.

cfsimplicity commented 3 years ago

Is it possible the file is password protected? I think OPCPackage is normally only needed for encryption.

Does the code work on your prod server with a simple test xls/xslx file?

ivanionut commented 3 years ago

hi @cfsimplicity, it's really weird ... i downloaded the xlsx file from the production server and tried it in my local environment and it works fine. the xlsx file is not password protected, furthermore the error occurs here:

Spreadsheet.cfc:1842

1840:               var file = CreateObject( "java", "java.io.FileInputStream" ).init( arguments.path );
1841:               if( arguments.KeyExists( "password" ) ) return loadClass( className ).create( file, arguments.password );
1842:               return loadClass( className ).create( file );
1843:           }
1844:       }

I don't understand what I'm doing wrong ...

cfsimplicity commented 3 years ago

Ivan, the error is coming from the POI class not the Spreadsheet library, which is just loading that class.

Is it just that particular file that is problematic? Does it work with a simple test file on your production server?

ivanionut commented 3 years ago

i also tried with a new one line xlsx file but i have the same problem ... Referenze.xlsx

cfsimplicity commented 3 years ago

In that case there must be something different about your prod environment. Sorry but I can't tell you what that might be.

ivanionut commented 3 years ago

hmmm, I'm getting a doubt.

this is the production server (where there are so many other websites). on the production server the virtual directory "javaloader" is mapped (as you see in the screen) and points to a path used for another site. can this be a problem? mapping

cfsimplicity commented 3 years ago

By default the library should use the JavaLoader package which ships with it in the same directory. Even if it was using the mapped JavaLoader elsewhere on your server, I'd expect it to behave in the same way.

ivanionut commented 3 years ago

you won't believe it but I solved it by doing a reboot of the production server (it was already scheduled) ... this job is really demoralizing ... :cry:

thanks anyway for the support!

ivanionut commented 3 years ago

hi @cfsimplicit, i'm getting exactly the same error ... :sob: i just don't know how to fix ... if you have any ideas, just let me know.

cfsimplicity commented 3 years ago

Is it possible the Lucee installation on the server is loading POI jars from anywhere else?

Try adding the following script to check the location of the jars being loaded:

spreadsheet.dumpPathToClass( "org.apache.poi.ss.usermodel.WorkbookFactory" );
abort;

It should point to a jar inside the /lib folder within the spreadsheet library folder.

PS: run it just before the line which is erroring.

ivanionut commented 3 years ago

this is the result of the dump:

file:/var/www/mywebsite/app/com/spreadsheet/lib/poi-4.1.2.jar!/org/apache/poi/ss/usermodel/WorkbookFactory.class
cfsimplicity commented 3 years ago

That looks correct. How about: spreadsheet.dumpPathToClass( "org.apache.poi.openxml4j.opc.OPCPackage" );?

cfsimplicity commented 3 years ago

To rule out a problem with the server mapped JavaLoader instance you mentioned earlier, you could explicitly point the library to the version bundled with it.

1) Create an application mapping called bundledJavaLoader in your Application.cfc which points to the bundled javaloader folder:

this.mappings[ "bundledJavaLoader" ] = "/var/www/mywebsite/app/com/spreadsheet/javaLoader/";

2) When initializing the library, add the javaLoaderDotPath argument to override the default dot path:

spreadsheet = New luceeSpreadsheet.SpreadSheet( javaLoaderDotPath: "bundledJavaLoader.JavaLoader" );

3) Check the path has been overridden:

dump( spreadsheet.getEnvironment().javaLoaderDotPath );

4) Flush the previous cached JavaLoader instance:

spreadsheet.flushPoiLoader();
ivanionut commented 3 years ago

hi, first of all sorry for the delay.

I did the tests you indicated:

function test( struct rc = {} ) localmode="modern"{

    spreadsheet = new com.spreadsheet.Spreadsheet( javaLoaderDotPath: "bundledJavaLoader.JavaLoader" );
    dump( spreadsheet.getEnvironment().javaLoaderDotPath );
    spreadsheet.flushPoiLoader();
    dump( spreadsheet.getEnvironment().javaLoaderDotPath );
    spreadsheet.dumpPathToClass( "org.apache.poi.openxml4j.opc.OPCPackage" );

    q_catalog = spreadsheet.read(src='/var/www/mywebsite/app/media/schedule/catalog/Referenze.xlsx', headerRow=1, format="query");
    dump( q_catalog );
    abort;
}

error

and this is the error (referring to the lineq_catalog = spreadsheet.read(...)):

application.logERROR 21:32:32, 14 gen, 2021http-nio-8888-exec-5
"java.io.FileInputStream incompatible with org.apache.poi.openxml4j.opc.OPCPackage;java.io.FileInputStream incompatible with org.apache.poi.openxml4j.opc.OPCPackage;lucee.runtime.exp.NativeException: java.io.FileInputStream incompatible with org.apache.poi.openxml4j.opc.OPCPackage
/com/spreadsheet/Spreadsheet.cfc:1842
/com/spreadsheet/Spreadsheet.cfc:1280
/controllers/schedule.cfc:53
/framework/one.cfc:1635
/framework/one.cfc:896

at org.apache.poi.xssf.usermodel.XSSFWorkbookFactory.lambda$static$0(XSSFWorkbookFactory.java:36)
at org.apache.poi.xssf.usermodel.XSSFWorkbookFactory$$Lambda$172/000000000000000000.apply(Unknown Source)
at org.apache.poi.ss.usermodel.WorkbookFactory.create(WorkbookFactory.java:196)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at lucee.runtime.reflection.pairs.MethodInstance.invoke(MethodInstance.java:56)
at lucee.runtime.java.JavaObject.call(JavaObject.java:266)
at lucee.runtime.java.JavaObject.call(JavaObject.java:288)
at lucee.runtime.util.VariableUtilImpl.callFunctionWithoutNamedValues(VariableUtilImpl.java:785)
at lucee.runtime.PageContextImpl.getFunction(PageContextImpl.java:1732)
at com.spreadsheet.spreadsheet_cfc$cf.udfCallb(/com/spreadsheet/Spreadsheet.cfc:1842)
at com.spreadsheet.spreadsheet_cfc$cf.udfCall(/com/spreadsheet/Spreadsheet.cfc)
at lucee.runtime.type.UDFImpl.implementation(UDFImpl.java:106)
at lucee.runtime.type.UDFImpl._call(UDFImpl.java:344)
at lucee.runtime.type.UDFImpl.call(UDFImpl.java:217)
at lucee.runtime.type.scope.UndefinedImpl.call(UndefinedImpl.java:784)
at lucee.runtime.util.VariableUtilImpl.callFunctionWithoutNamedValues(VariableUtilImpl.java:785)
at lucee.runtime.PageContextImpl.getFunction(PageContextImpl.java:1732)
at com.spreadsheet.spreadsheet_cfc$cf.udfCall7(/com/spreadsheet/Spreadsheet.cfc:1280)
at com.spreadsheet.spreadsheet_cfc$cf.udfCall(/com/spreadsheet/Spreadsheet.cfc)
at lucee.runtime.type.UDFImpl.implementation(UDFImpl.java:106)
at lucee.runtime.type.UDFImpl._call(UDFImpl.java:344)
at lucee.runtime.type.UDFImpl.callWithNamedValues(UDFImpl.java:207)
at lucee.runtime.ComponentImpl._call(ComponentImpl.java:683)
at lucee.runtime.ComponentImpl._call(ComponentImpl.java:570)
at lucee.runtime.ComponentImpl.callWithNamedValues(ComponentImpl.java:1919)
at lucee.runtime.util.VariableUtilImpl.callFunctionWithNamedValues(VariableUtilImpl.java:864)
at lucee.runtime.PageContextImpl.getFunctionWithNamedValues(PageContextImpl.java:1751)
at controllers.schedule_cfc$cf$d.udfCall(/controllers/schedule.cfc:53)
at lucee.runtime.type.UDFImpl.implementation(UDFImpl.java:106)
at lucee.runtime.type.UDFImpl._call(UDFImpl.java:344)
at lucee.runtime.type.UDFImpl.callWithNamedValues(UDFImpl.java:207)
at lucee.runtime.ComponentImpl._call(ComponentImpl.java:683)
at lucee.runtime.ComponentImpl._call(ComponentImpl.java:570)
at lucee.runtime.ComponentImpl.callWithNamedValues(ComponentImpl.java:1919)
at lucee.runtime.util.VariableUtilImpl.callFunctionWithNamedValues(VariableUtilImpl.java:898)
at lucee.runtime.functions.dynamicEvaluation.Invoke.call(Invoke.java:49)
at framework.one_cfc$cf.udfCallb(/framework/one.cfc:1635)
at framework.one_cfc$cf.udfCall(/framework/one.cfc)
at lucee.runtime.type.UDFImpl.implementation(UDFImpl.java:106)
at lucee.runtime.type.UDFImpl._call(UDFImpl.java:344)
at lucee.runtime.type.UDFImpl.call(UDFImpl.java:217)
at lucee.runtime.type.scope.UndefinedImpl.call(UndefinedImpl.java:784)
at lucee.runtime.util.VariableUtilImpl.callFunctionWithoutNamedValues(VariableUtilImpl.java:785)
at lucee.runtime.PageContextImpl.getFunction(PageContextImpl.java:1732)
at framework.one_cfc$cf.udfCall6(/framework/one.cfc:896)
at framework.one_cfc$cf.udfCall(/framework/one.cfc)
at lucee.runtime.type.UDFImpl.implementation(UDFImpl.java:106)
at lucee.runtime.type.UDFImpl._call(UDFImpl.java:344)
at lucee.runtime.type.UDFImpl.call(UDFImpl.java:217)
at lucee.runtime.ComponentImpl._call(ComponentImpl.java:682)
at lucee.runtime.ComponentImpl._call(ComponentImpl.java:570)
at lucee.runtime.ComponentImpl.call(ComponentImpl.java:1900)
at lucee.runtime.listener.Modern
-- very long stack, omitted 2869 bytes

I really don't know why this error comes up. ... for the moment I have rewritten the function that does the manipulation of the xlsx file in python (callable with cfexecute()).

cfsimplicity commented 3 years ago

OK, no change then. As I say it was just to rule out a problem with the JavaLoader mapping.

Thanks for posting the full stack trace. That shows where the error is happening, which is inside the POI java classes. I don't understand why the OPCPackage class is being invoked when the file is being read, or why it's rejecting the FileInputStream. But I didn't write that code. A proper java expert would probably know.

Glad you've been able to work around it for now. Let's leave this ticket open in case anything comes up to shed any light on it.

cfsimplicity commented 3 years ago

@ivanionut It might be worth trying the latest release 2.14.0 which uses a new version of POI and no longer requires JavaLoader to load it in Lucee.

ivanionut commented 3 years ago

hi I like the new implementation! as soon as I can I will do new tests and I will communicate the results!

thanks!