Bug 65260

Summary: Creating an SXSSFWorkbook fails if no fonts are available on the system
Product: POI Reporter: Alex <kurets.alex>
Component: SXSSFAssignee: POI Developers List <dev>
Status: RESOLVED FIXED    
Severity: enhancement    
Priority: P2    
Version: 4.1.2-FINAL   
Target Milestone: ---   
Hardware: PC   
OS: Linux   
Bug Depends on: 66230    
Bug Blocks:    

Description Alex 2021-04-22 10:04:16 UTC
Good day.
We use Apache POI 4.1.2 for creation .xlsx file.
Our application starts inside Docker container.
We use open-jdk(11th version) without predefined fonts. We needs that for security reason.
At firts time we used XSSFWorkbook/XSSFSheet. All worked correctly.
For reducing of memory usege we replaced XSSFWorkbook by SXSSFWorkbook.
After that we have next exception.

java.lang.InternalError: java.lang.reflect.InvocationTargetException
    at java.desktop/sun.font.FontManagerFactory$1.run(FontManagerFactory.java:86)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.desktop/sun.font.FontManagerFactory.getInstance(FontManagerFactory.java:74)
    at java.desktop/java.awt.Font.getFont2D(Font.java:497)
    at java.desktop/java.awt.Font.canDisplayUpTo(Font.java:2250)
    at java.desktop/java.awt.font.TextLayout.singleFont(TextLayout.java:469)
    at java.desktop/java.awt.font.TextLayout.<init>(TextLayout.java:530)
    at org.apache.poi.ss.util.SheetUtil.getDefaultCharWidth(SheetUtil.java:273)
    at org.apache.poi.xssf.streaming.AutoSizeColumnTracker.<init>(AutoSizeColumnTracker.java:117)
    at org.apache.poi.xssf.streaming.SXSSFSheet.<init>(SXSSFSheet.java:82)
    at org.apache.poi.xssf.streaming.SXSSFWorkbook.createAndRegisterSXSSFSheet(SXSSFWorkbook.java:684)
    at org.apache.poi.xssf.streaming.SXSSFWorkbook.createSheet(SXSSFWorkbook.java:705)
    at

How we understand that relates with missing fonts and AutoSizeColumnTracker in SXSSFSheet.

public SXSSFSheet(SXSSFWorkbook workbook, XSSFSheet xSheet) throws IOException {
        this._workbook = workbook;
        this._sh = xSheet;
        this._writer = workbook.createSheetDataWriter();
        this.setRandomAccessWindowSize(this._workbook.getRandomAccessWindowSize());
        this._autoSizeColumnTracker = new AutoSizeColumnTracker(this);
    }

This constructor has initialization of AutoSizeColumnTracker.
AutoSizeColumnTracker calculates defaultCharWidth.

Why does SXSSFWorkbook need in AutoSizeColumnTracker by default?
How can we disable that or maybe set custom defaultCharWidth without calculation?
Comment 1 Dominik Stadler 2021-04-27 05:45:40 UTC
It seems there is currently no way to avoid this dependency on some fonts being available.

We can review this in the future to see if there is a way to handle this more gracefully, maybe by catching and logging the exception with a fallback column width.

Patches highly welcome!
Comment 2 Andreas Beeker 2021-04-27 05:53:45 UTC
what is the security implications of having no fonts?
would it be compromised if we (try to) register a default font in the case we don't find any fonts?
Comment 3 Dominik Stadler 2022-12-26 15:48:03 UTC
We actually tried to solve this via #66230, but the implementation seems to be flawed, as the JVM throws an "InternalError", which is not part of the "Exception" class-hierarchy. 

A small further fix is necessary to adjust for this and make it work properly.
Comment 4 Dominik Stadler 2022-12-26 16:22:07 UTC
Should be solved now via r1906218
Comment 5 PJ Fanning 2023-02-04 15:19:02 UTC
I added r1907308 due to https://github.com/apache/poi/pull/425 - but looks like it might be causing issues itself
Comment 6 Michal 2023-08-28 10:52:19 UTC
Hello,
We are currently working with Apache POI version 5.2.3 and are encountering an issue that appears to be similar to the one reported by Alex for version 4.1.2. Our application is built on OpenJDK slim (11th version) and does not have any installed fonts.

In the source code, sheet is created with method:
SXSSFWorkbook.createSheet(sheetName)

Stack trace:
java.lang.InternalError: java.lang.reflect.InvocationTargetException
	at java.desktop/sun.font.FontManagerFactory$1.run(FontManagerFactory.java:86)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at java.desktop/sun.font.FontManagerFactory.getInstance(FontManagerFactory.java:74)
	at java.desktop/java.awt.Font.getFont2D(Font.java:497)
	at java.desktop/java.awt.Font.canDisplayUpTo(Font.java:2250)
	at java.desktop/java.awt.font.TextLayout.singleFont(TextLayout.java:469)
	at java.desktop/java.awt.font.TextLayout.<init>(TextLayout.java:530)
	at org.apache.poi.ss.util.SheetUtil.getDefaultCharWidth(SheetUtil.java:301)
	at org.apache.poi.xssf.streaming.AutoSizeColumnTracker.<init>(AutoSizeColumnTracker.java:117)
	at org.apache.poi.xssf.streaming.SXSSFSheet.<init>(SXSSFSheet.java:95)
	at org.apache.poi.xssf.streaming.SXSSFWorkbook.createAndRegisterSXSSFSheet(SXSSFWorkbook.java:726)
	at org.apache.poi.xssf.streaming.SXSSFWorkbook.createSheet(SXSSFWorkbook.java:745)
Caused by: java.lang.NullPointerException
	at java.desktop/sun.awt.FontConfiguration.getVersion(FontConfiguration.java:1264)
	at java.desktop/sun.awt.FontConfiguration.readFontConfigFile(FontConfiguration.java:225)
	at java.desktop/sun.awt.FontConfiguration.init(FontConfiguration.java:107)
	at java.desktop/sun.awt.X11FontManager.createFontConfiguration(X11FontManager.java:719)
	at java.desktop/sun.font.SunFontManager$2.run(SunFontManager.java:379)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at java.desktop/sun.font.SunFontManager.<init>(SunFontManager.java:324)
	at java.desktop/sun.awt.FcFontManager.<init>(FcFontManager.java:35)
	at java.desktop/sun.awt.X11FontManager.<init>(X11FontManager.java:56)


Is there any workaround for this case, or which fonts should be specified to install in the Dockerfile to resolve the issue?
Comment 7 PJ Fanning 2023-08-28 10:59:15 UTC
Have you tried disabling the AutoSizeColumnTracker ?
Comment 8 PJ Fanning 2023-08-28 11:03:38 UTC
There are unreleased code changes that should fix this. I'm not sure if we are ready to do a release though.
Comment 9 Michal 2023-08-28 11:16:33 UTC
(In reply to PJ Fanning from comment #7)
> Have you tried disabling the AutoSizeColumnTracker ?

By disabling do you mean usage of method SXSSFSheet.untrackAllColumnsForAutoSizing()?
Comment 10 PJ Fanning 2023-08-28 11:21:23 UTC
To be honest, until we do a 5.2.4 release, you might be best creating your own POI jars that start with the code in POI 5.2.3 but that cherry pick some SXSSF commits form this year.
Comment 11 PJ Fanning 2023-08-28 11:29:23 UTC
It might be worth looking at https://github.com/quarkiverse/quarkus-poi who worked around this issue. Have a look at their Docker image. Its setup may help you to set up your own Docker image.
Comment 12 Michal 2023-08-28 11:40:52 UTC
Okay, I've seen some commits related to catching exceptions in the SXSSFSheet constructor (UnsatisfiedLinkError). 
Thank you, I will probably create my own JAR for now as you suggested, and I'm looking forward to the 5.2.4 release.
Comment 13 Dominik Stadler 2023-09-04 19:40:13 UTC
Likely fixed on trunk and in the next release, thus resolving again.
Comment 14 kai.vannahme 2023-09-26 11:04:32 UTC
Posting my workaround from Github:

I had the same problem. I went through the stacktrace. In the SheetUtil.java getDefaultCharWidth is called. In case of an internal error as reported by OP you can handle that error when the system property "org.apache.poi.ss.ignoreMissingFontSystem" is set to true. It will return a default char width then instead of rethrowing the error.

So you either set this property to true in your environment or you might add a configuration to your spring application as following:

@configuration
public class FontConfiguration {

@PostConstruct
public void setProperty() {
    System.setProperty("org.apache.poi.ss.ignoreMissingFontSystem", "true");
}
}
Comment 15 Michal 2023-10-13 12:39:37 UTC
Version 5.2.4 resolved the issue, thank you all for your help!