본문 바로가기
개발/기타

poi SXSSFWorkbook createSheet FontConfiguration NullPointException

by 궁즉변 변즉통 통즉구 2023. 7. 3.
반응형

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

반응형

댓글