spreadsheet-cfml icon indicating copy to clipboard operation
spreadsheet-cfml copied to clipboard

autoSizeColumns = true produces NPE

Open MordantWastrel opened this issue 5 years ago • 13 comments

OpenJDK 8u181, Alpine Linux in Docker, Lucee 5.3.2.38-SNAPSHOT, lucee-spreadsheet 2.0.2.

We have a working xlsx file generated from:

spreadsheet.addRows(workbook = sheet, data = dataQuery );

If we change it to:

spreadsheet.addRows(workbook = sheet, data = dataQuery, autoSizeColumns = true);

We get the following NPE:

`` The Error Occurred in/app/modules/lucee-spreadsheet/Spreadsheet.cfc: line 603 601: /* Adjusts the width of the specified column to fit the contents. For performance reasons, this should normally be called only once per column. */602: var columnIndex = ( arguments.column -1 );603: getActiveSheet( arguments.workbook ).autoSizeColumn( columnIndex, useMergedCells );604: }605: called from /app/modules/lucee-spreadsheet/Spreadsheet.cfc: line 567 called from /app/model/queryBuilder2/QueryBuilderDownloader.cfm: line 77

Java Stacktrace | lucee.runtime.exp.NativeException: java.lang.NullPointerException  at sun.awt.FontConfiguration.getVersion(FontConfiguration.java:1264)  at sun.awt.FontConfiguration.readFontConfigFile(FontConfiguration.java:219)  at sun.awt.FontConfiguration.init(FontConfiguration.java:107)  at sun.awt.X11FontManager.createFontConfiguration(X11FontManager.java:774)  at sun.font.SunFontManager$2.run(SunFontManager.java:431)  at java.security.AccessController.doPrivileged(Native Method)  at sun.font.SunFontManager.(SunFontManager.java:376)  at sun.awt.FcFontManager.(FcFontManager.java:35)  at sun.awt.X11FontManager.(X11FontManager.java:57)  at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)  at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)  at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)  at java.lang.reflect.Constructor.newInstance(Constructor.java:423)  at java.lang.Class.newInstance(Class.java:442)  at sun.font.FontManagerFactory$1.run(FontManagerFactory.java:83)  at java.security.AccessController.doPrivileged(Native Method)  at sun.font.FontManagerFactory.getInstance(FontManagerFactory.java:74)  at java.awt.Font.getFont2D(Font.java:491)  at java.awt.Font.canDisplayUpTo(Font.java:2060)  at java.awt.font.TextLayout.singleFont(TextLayout.java:470)  at java.awt.font.TextLayout.(TextLayout.java:531)  at org.apache.poi.ss.util.SheetUtil.getDefaultCharWidth(SheetUtil.java:273)  at org.apache.poi.ss.util.SheetUtil.getColumnWidth(SheetUtil.java:248)  at org.apache.poi.ss.util.SheetUtil.getColumnWidth(SheetUtil.java:233)  at org.apache.poi.xssf.usermodel.XSSFSheet.autoSizeColumn(XSSFSheet.java:551)  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)  at java.lang.reflect.Method.invoke(Method.java:498)  at lucee.runtime.reflection.pairs.MethodInstance.invoke(MethodInstance.java:56)  at lucee.runtime.reflection.Reflector.callMethod(Reflector.java:877)  at lucee.runtime.util.VariableUtilImpl.callFunctionWithoutNamedValues(VariableUtilImpl.java:810)  at lucee.runtime.PageContextImpl.getFunction(PageContextImpl.java:1706)  at modules.lucee_spreadsheet270.spreadsheet_cfc$cf.udfCall3(/modules/lucee-spreadsheet/Spreadsheet.cfc:603)  at modules.lucee_spreadsheet270.spreadsheet_cfc$cf.udfCall(/modules/lucee-spreadsheet/Spreadsheet.cfc)  at lucee.runtime.type.UDFImpl.implementation(UDFImpl.java:106)  at lucee.runtime.type.UDFImpl._call(UDFImpl.java:342)  at lucee.runtime.type.UDFImpl.call(UDFImpl.java:215)  at lucee.runtime.type.scope.UndefinedImpl.call(UndefinedImpl.java:766)  at lucee.runtime.util.VariableUtilImpl.callFunctionWithoutNamedValues(VariableUtilImpl.java:767)  at lucee.runtime.PageContextImpl.getFunction(PageContextImpl.java:1706)  at modules.lucee_spreadsheet270.spreadsheet_cfc$cf.udfCall3(/modules/lucee-spreadsheet/Spreadsheet.cfc:567)  at modules.lucee_spreadsheet270.spreadsheet_cfc$cf.udfCall(/modules/lucee-spreadsheet/Spreadsheet.cfc)  at lucee.runtime.type.UDFImpl.implementation(UDFImpl.java:106)  at lucee.runtime.type.UDFImpl._call(UDFImpl.java:342)  at lucee.runtime.type.UDFImpl.callWithNamedValues(UDFImpl.java:205)  at lucee.runtime.ComponentImpl._call(ComponentImpl.java:678)  at lucee.runtime.ComponentImpl._call(ComponentImpl.java:565)  at lucee.runtime.ComponentImpl.callWithNamedValues(ComponentImpl.java:1946)  at lucee.runtime.util.VariableUtilImpl.callFunctionWithNamedValues(VariableUtilImpl.java:845)  at lucee.runtime.PageContextImpl.getFunctionWithNamedValues(PageContextImpl.java:1725)  at model.querybuilder2.querybuilderdownloader_cfm$cf.call(/model/queryBuilder2/QueryBuilderDownloader.cfm:77)  at lucee.runtime.PageContextImpl._doInclude(PageContextImpl.java:941)  at lucee.runtime.PageContextImpl._doInclude(PageContextImpl.java:833)  at lucee.runtime.listener.ModernAppListener._onRequest(ModernAppListener.java:216)  at lucee.runtime.listener.ModernAppListener.onRequest(ModernAppListener.java:104)  at lucee.runtime.PageContextImpl.execute(PageContextImpl.java:2408)  at lucee.runtime.PageContextImpl._execute(PageContextImpl.java:2398)  at lucee.runtime.PageContextImpl.executeCFML(PageContextImpl.java:2373)  at lucee.runtime.engine.Request.exe(Request.java:43)  at lucee.runtime.engine.CFMLEngineImpl._service(CFMLEngineImpl.java:1045)  at lucee.runtime.engine.CFMLEngineImpl.serviceCFML(CFMLEngineImpl.java:991)  at lucee.loader.engine.CFMLEngineWrapper.serviceCFML(CFMLEngineWrapper.java:97)  at lucee.loader.servlet.CFMLServlet.service(CFMLServlet.java:51)  at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)  at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74)  at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:129)  at org.cfmlprojects.regexpathinfofilter.RegexPathInfoFilter.doFilter(RegexPathInfoFilter.java:47)  at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)  at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)  at org.tuckey.web.filters.urlrewrite.RuleChain.handleRewrite(RuleChain.java:176)  at org.tuckey.web.filters.urlrewrite.RuleChain.doRules(RuleChain.java:145)  at org.tuckey.web.filters.urlrewrite.UrlRewriter.processRequest(UrlRewriter.java:92)  at org.tuckey.web.filters.urlrewrite.UrlRewriteFilter.doFilter(UrlRewriteFilter.java:389)  at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)  at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)  at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84)  at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)  at io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:64)  at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)  at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:132)  at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)  at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)  at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)  at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)  at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)  at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)  at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)  at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)  at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)  at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:292)  at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:81)  at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:138)  at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:135)  at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)  at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)  at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:272)  at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81)  at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:104)  at io.undertow.server.Connectors.executeRootHandler(Connectors.java:336)  at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:830)  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)  at java.lang.Thread.run(Thread.java:748) Caused by: java.lang.NullPointerException ``

MordantWastrel avatar Jan 18 '19 14:01 MordantWastrel

Hi Samuel. Again I can't reproduce this.

Using Lucee 5.3.2.38-SNAPSHOT via CommandBox on AdoptOpenJdk 1.8.0_202 I ran this code without any problem:

data = QueryNew( "column1,column2","VarChar,VarChar", [ [ "a", "b" ], [ "c", "d" ] ] );
s = New luceeSpreadsheet.Spreadsheet();
wb = s.newXlsx();
s.addRows( workbook=wb, data=data, autoSizeColumns=true );
s.download( wb, "test" );

As with issue 58, could this be related to Docker in some way?

cfsimplicity avatar Jan 18 '19 16:01 cfsimplicity

Does this solve the problem (i.e. apt install fontconfig)?

https://dev.lucee.org/t/fixed-adoptopenjdk-and-fontconfig-error-ubuntu-18-04/5119

cfsimplicity avatar Feb 17 '19 08:02 cfsimplicity

It does not.

We are on Alpine rather than Ubuntu but I was still able to apk add fontconfig.

MordantWastrel avatar Feb 17 '19 14:02 MordantWastrel

Pity. Your stacktrace does indicate the NPE is similarly related to the sun.awt.FontConfiguration class. Suggests there's something specific to AdoptOpenJDK and Linux (I'm not seeing any problem on WIndows as I say). I don't know enough about either to shed any light unfortunately.

cfsimplicity avatar Feb 17 '19 18:02 cfsimplicity

We are using the official openjdk 8 docker image as the base, which is what all Commandbox docker images use for now. Not adoptopenjdk. I think it's also u181.

On Sun, Feb 17, 2019, 12:43 PM Julian Halliwell <[email protected] wrote:

Pity. Your stacktrace does indicate the NPE is similarly related to the sun.awt.FontConfiguration class. Suggests there's something specific to AdoptOpenJDK and Linux (I'm not seeing any problem on WIndows as I say). I don't know enough about either to shed any light unfortunately.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/cfsimplicity/lucee-spreadsheet/issues/161#issuecomment-464493349, or mute the thread https://github.com/notifications/unsubscribe-auth/ALUw1vv-EWcSzfOXIXy2egjaP8qZkDyGks5vOaLNgaJpZM4aICv8 .

MordantWastrel avatar Feb 17 '19 18:02 MordantWastrel

OK, OpenJDK generally and Linux then.

cfsimplicity avatar Feb 17 '19 18:02 cfsimplicity

A little bit of googling suggests this is a problem with the headless version of OpenJDK used by Docker, which doesn't expect AWT/fonts to be needed. There are a couple of other suggested solutions, including for Alpine:

https://stackoverflow.com/questions/30626136/cannot-load-font-in-jre-8

Any good?

cfsimplicity avatar Feb 17 '19 20:02 cfsimplicity

The alpine suggestion of:

apk add --update ttf-dejavu

...did not work. Even if it had, that's 138 MB of packages.

The Commandbox docker image also does add a number of font-related packages to support cfdocument and PDF rendering:

https://github.com/Ortus-Solutions/docker-commandbox/commit/c9bf05f40499d1f425f90337f5d183c24eb05cb0

But I don't think switching to the non-headless JDK is an option as that would likely also blow up the image size.

MordantWastrel avatar Feb 18 '19 15:02 MordantWastrel

OK, but I think we've established the cause of the problem: POI requires the AWT font classes which appear to be missing from the headless OpenJDK.

Perhaps Ortus can address that as they've done with PDF rendering? Failing that, I'm not sure how you're going to get POI to work unless you're prepared to switch to a JRE that includes the required classes.

cfsimplicity avatar Feb 18 '19 15:02 cfsimplicity

I'm not actually sure that it does require them if the java.awt.headless option is enabled, as it is for the Commandbox docker image. Do we actually know what the required classes are?

It would likely be easier to just add those than to add 100+ MB of packages. I'll create a ticket on the Ortus repo for Commandbox though.

https://github.com/Ortus-Solutions/docker-commandbox/issues/32

MordantWastrel avatar Feb 18 '19 16:02 MordantWastrel

I'm afraid I can't tell you exactly which classes would need to be added. The library does call various AWT classes/packages explicitly but the NPE you've seen seems to be from an internal POI call according to the stack trace.

Btw, in your Ortus ticket you say "some features" of the library require POI. Actually almost all do: it's basically a POI wrapper for CFML.

cfsimplicity avatar Feb 18 '19 16:02 cfsimplicity

"some features" refers to this library (lucee-spreadsheet) -- most everything in this library works just fine. It's only the column resize and the streaming XLSX that don't.

MordantWastrel avatar Feb 18 '19 16:02 MordantWastrel

Yes this library, that what I meant. It relies on POI for almost everything.

Annoying that it's only those two features. I totally agree we ideally want to identify just what's missing that causes the NPE. Normally a missing class will result in a "class not defined" or similar, so perhaps it's just some small piece of configuration that's not being set somewhere.

cfsimplicity avatar Feb 18 '19 16:02 cfsimplicity