반응형
Java에서 엑셀을 다룰 때 Apache POI 라이브러리를 자주 사용하게 된다. 그리고 대용량 처리를 위해서 Streaming API를 사용하는 SXSSFWorkbook을 사용하는데 서버에 올려서 테스트 중에 아래와 같은 에러가 발생했다.
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Handler dispatch failed; nested exception is java.lang.InternalError: java.lang.reflect.InvocationTargetException] with root cause
java.lang.NullPointerException: null
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)
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)
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)
...
에러가 발생한 코드를 확인해보니 시트를 생성할 때 발생했다.
// sheet 생성
SXSSFSheet objSheet = sxssfWorkbook.createSheet("시트명"); // 에러발생
원인을 확인했을 때, JDK에서 POI API를 호출 시 시스템 폰트를 참조하는데 서버에 사용가능한 폰트가 없어서 발생하는 에러였다.
일단 아래 명령으로 폰트를 조회해봤는데 command not found 가 떴다.
$ fc-list
-bash: fc-list: command not found
정상적으로 동작하는 서버에서 동일하게 확인을 해보니 아래와 같이 폰트들이 조회가 된다.
$ fc-list
/usr/share/fonts/dejavu/DejaVuSerif-Bold.ttf: DejaVu Serif:style=Bold
/usr/share/fonts/dejavu/DejaVuSerif-Italic.ttf: DejaVu Serif:style=Italic
/usr/share/fonts/dejavu/DejaVuSansMono-BoldOblique.ttf: DejaVu Sans Mono:style=Bold Oblique
/usr/share/fonts/dejavu/DejaVuSansCondensed-Oblique.ttf: DejaVu Sans,DejaVu Sans Condensed:style=Condensed Oblique,Oblique
/usr/share/fonts/dejavu/DejaVuSansCondensed-Bold.ttf: DejaVu Sans,DejaVu Sans Condensed:style=Condensed Bold,Bold
/usr/share/fonts/dejavu/DejaVuSansMono.ttf: DejaVu Sans Mono:style=Book
/usr/share/fonts/dejavu/DejaVuSansMono-Bold.ttf: DejaVu Sans Mono:style=Bold
/usr/share/fonts/dejavu/DejaVuSans.ttf: DejaVu Sans:style=Book
...
에러가 발생하는 서버에 폰트 설정을 아래와 같이 추가하고 어플리케이션을 재실행하니 정상동작한다.
sudo yum install fontconfig -y
서버에 위의 명령만 실행해도 디폴트 폰트들이 포함되고 설정이 되는데 혹시 안되면 아래와 같이 직접 폰트를 설치해준다.
# 폰트 설치
$ sudo yum install freetype fontconfig dejavu-sans-fonts -y
# 폰트 캐시 초기화
$ sudo fc-cache -f -v
추가적으로 Container환경인 경우는 Dockerfile에 설정을 해줘야 하는데 아래 명령어을 참조하자
RUN apk update
RUN apk add --no-cache fontconfig ttf-dejavu
도움받은 사이트: https://logical-code.tistory.com/191
반응형
'개발 > 기타' 카테고리의 다른 글
git fatal: the remote end hung up unexpectedly 오류 조치 (0) | 2023.07.30 |
---|---|
Gradle fat jar(의존성 포함한 jar) 생성, shadow plugin 활용 (0) | 2023.07.22 |
DBeaver posgresql JDBC 드라이버 수동 설정 (0) | 2023.06.19 |
PostgreSQL 문자열 합치기 (0) | 2023.05.29 |
PostgreSQL Upsert(Update&Insert) 사용 (0) | 2023.05.29 |
댓글