흔히 대용량 데이터를 엑셀 파일로 내보낼 때, SXSSFWorkbook을 사용합니다. SXSSFWorkbook은 다른 Workbook과는 달리 Streaming api를 사용하기 때문에 대용량 데이터의 경우 보다 적합합니다.
저도 엑셀 다운로드 기능 구현 시 SXSSFWorkbook를 사용했는데요, 특정 서버에서만 SXSSFWorkbook 생성 시 FontConfiguration에서 NullPointerException이 발생하는 문제가 있었습니다.
아래는 그 문제와 해결 방법입니다.
오류 내용 및 원인
그런데 이번에 서비스를 오픈하면서, 특정 서버에서만 SXSSFWorkbook.createSheet()을 했을 때 아래와 같은 예외가 발생했습니다.
Caused by: 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)
...
Caused by: java.lang.reflect.InvocationTargetException: null
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
at java.desktop/sun.font.FontManagerFactory$1.run(FontManagerFactory.java:84)
... 124 common frames omitted
Caused by: java.lang.NullPointerException: null
at java.desktop/sun.awt.FontConfiguration.getVersion(FontConfiguration.java:1262)
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:367)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at java.desktop/sun.font.SunFontManager.<init>(SunFontManager.java:312)
at java.desktop/sun.awt.FcFontManager.<init>(FcFontManager.java:35)
at java.desktop/sun.awt.X11FontManager.<init>(X11FontManager.java:56)
... 129 common frames omitted
확인 결과, JDK에서 POI API를 호출 시 시스템 폰트를 참조하는데, 해당 서버에는 사용 가능한 폰트가 없었기 때문에 발생한 것이였습니다.
해결 방법
fontconfig 디펜던시와 폰트를 설치해주고, 서비스를 재기동해주니 해결되었습니다.
아래는 fontconfig 디펜던시와 폰트 재설치 방법입니다.(CentOS 기준)
# fontconfig 디펜던시 설치
sudo yum install fontconfig -y
# 폰트 설치
sudo yum install freetype fontconfig dejavu-sans-fonts -y
# 폰트 캐시 초기화
sudo fc-cache -f -v
Reference
Prerequisites for Font Support in AdoptOpenJDK
Proper font support in AdoptOpenJDK requires some additional configuration on Linux and Solaris. Without it, you get unhelpful NullPointerExceptions.
blog.adoptopenjdk.net
ApachePoi fails with Font error on OpenJdk 1.8.0_121 Okay on Oracle Jre-技术分享-码神部落
点赞 0 收藏 0
www.mashen.zone
리눅스 폰트(linux font) 설치 및 font config 사용법
www.lesstif.com
'☕️ JAVA' 카테고리의 다른 글
[자바로 배우는 리팩토링 입문] 리팩토링이란? (0) | 2021.08.15 |
---|---|
Try with Resources - 손쉬운 자원 해제 (0) | 2021.03.09 |
BufferedReader 가 Scanner 보다 빠른 이유 (0) | 2020.11.08 |
Enum을 사용해보자 (0) | 2020.10.18 |
WebSocketSession에서 HttpSession를 얻는 방법 (0) | 2020.09.10 |