'spire.pdf in a docker container

I create an application that handle pdf and convert them to pdfa3 and also convert the document onto facturX. I developped my application using Springboot and it works fine. Now i'm trying to dockerize my application. I had issue with database connection and now I meet the following issue

facturx_1  | 2022-03-21 16:20:55.565 ERROR 1 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is class com.spire.ms.System.Exception: No 'Arial' font found!
...
facturx_1  | com.spire.pdf.conversion.PdfStandardsConverter.toPdfA3B(Unknown Source)
facturx_1  | fr.company.app.shared.Utils.loadPdfA3(Utils.java:88)
facturx_1  | fr.company.app.service.impl.FacturXServiceImpl.createFacturX(FacturXServiceImpl.java:75)
facturx_1  | fr.company.app.ui.controller.FacturXController.createFacturXOutoutStream(FacturXController.java:54)
...
facturx_1  | java.base/java.lang.Thread.run(Unknown Source)] with root cause
facturx_1  |
facturx_1  | com.spire.ms.System.Exception: No 'Arial' font found!
facturx_1  |    at com.spire.pdf.packages.sprZOa.spr  (Unknown Source) ~[spire.pdf.free-5.1.0.jar!/:5.1.0]
...
facturx_1  |    at com.spire.pdf.conversion.PdfStandardsConverter.toPdfA3B(Unknown Source) ~[spire.pdf.free-5.1.0.jar!/:5.1.0]
facturx_1  |    at fr.company.app.shared.Utils.loadPdfA3(Utils.java:88) ~[classes!/:0.0.1-SNAPSHOT]
facturx_1  |    at fr.company.app.service.impl.FacturXServiceImpl.createFacturX(FacturXServiceImpl.java:75) ~[classes!/:0.0.1-SNAPSHOT]
facturx_1  |    at fr.company.app.ui.controller.FacturXController.createFacturXOutoutStream(FacturXController.java:54) ~[classes!/:0.0.1-SNAPSHOT]

My code is the following :

public static PDDocument loadPdfA3(String pdfData) {
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

    byte[] decoded = Base64.getDecoder().decode(pdfData);
    InputStream inputStream = new ByteArrayInputStream(decoded);

    PdfStandardsConverter converter = new PdfStandardsConverter(inputStream);
    converter.toPdfA3B(outputStream);

    byte[] pdfBytes = outputStream.toByteArray();
    InputStream pdfInputStream = new ByteArrayInputStream(pdfBytes);

    try {
        return PDDocument.load(pdfInputStream);
    } catch (IOException e) {
        throw new AppServiceException(e.getLocalizedMessage());
    }
}

the line that returns the exception is the following converter.toPdfA3B(outputStream)

I implementing the following docker file :

# Build stage
FROM maven:3.8.4-openjdk-11 AS build
WORKDIR /app
COPY . /app
RUN mvn clean package -DskipTests

# Package and Run stage
FROM openjdk:11.0.14.1-jre
COPY --from=build app/target/facturx-ws.jar /usr/local/lib/facturx-ws.jar
EXPOSE 8092

ENTRYPOINT ["java", "-jar", "-Dspring.profiles.active=docker", "/usr/local/lib/facturx-ws.jar"]

Here is also my docker compose:

version: "3"
services:
  facturx:
    container_name: facturx
    image: facturx
    restart: always
    build:
      context: ./
      dockerfile: Dockerfile
    ports:
      - "8081:8080"
    environment:
      MYSQL_HOST: mysqldb
      MYSQL_USER: root
      MYSQL_PASSWORD: root
      MYSQL_PORT: 3306
    #    depends_on:
    #      - mysqldb
    networks:
      - appnetwork

  mysqldb:
    container_name: mysqldb
    image: mysql:8.0.28-oracle
    command: ['mysqld','--character-set-server=utf8','--default-authentication-plugin=mysql_native_password']
    volumes:
      - dbstore:/var/lib/mysql
    ports:
      - "3309:3306"
    environment:
      MYSQL_DATABASE: facturx
      MYSQL_ROOT_PASSWORD: root
    restart: unless-stopped
    networks:
      - appnetwork

volumes:
  dbstore: {}

networks:
  appnetwork:
    driver: bridge


Solution 1:[1]

I changed my Dockerfile :

# Build stage
FROM maven:3.8.4-openjdk-11 AS build

WORKDIR /app
COPY ../../facturx-ws/. /app
COPY ../../facturx-ws/src/main/resources/xsd /app/xsd
RUN mvn clean package -DskipTests

# Package and Run stage
FROM openjdk:11.0.14.1-jre
COPY --from=build app/target/facturx-ws.jar /usr/local/lib/facturx-ws.jar
COPY --from=build app/xsd /usr/local/lib/xsd
#COPY app/facturx-ws/src/main/resources/xsd /usr/local/lib/xsd
RUN echo "ttf-mscorefonts-installer msttcorefonts/accepted-mscorefonts-eula select true" | debconf-set-selections
RUN sed -i'.bak' 's/$/ contrib/' /etc/apt/sources.list
RUN apt-get update; apt-get install -y ttf-mscorefonts-installer fontconfig
RUN fc-cache -f -v
#EXPOSE 8092
ENTRYPOINT ["java", "-jar", "-Dspring.profiles.active=docker", "/usr/local/lib/facturx-ws.jar"]

I installed windows font by running ttf-mscorefonts-installer

Solution 2:[2]

The exception says: No 'Arial' font found. Be aware that when using spire.pdf to convert a pdf file on a non-windows system, you need to ensure all used fonts in the file are installed, otherwise your application might throw such exception. Here is a similar post on spire forum.

Solution 3:[3]

Thanks davidvera for your answer.

Tested below with e-iceblue:spire.pdf.free:4.4.1 and e-iceblue:spire.pdf.free:5.1.0

In our case the solution was for the Issues we had:

  1. Caused by: java.lang.NoClassDefFoundError: Could not initialize class com.spire.doc.packages...
  2. com.spire.ms.System.Exception: No 'Arial' font found!
  3. "Neutral cultures cannot be used in formatting and parsing and therefore cannot be set as the thread's current culture"
change impact
Used JDK instead of JRE fixed classloading issues (your issue outlined above did not appear)
Used debian instead of alpine (as base) unknown
Installed msttcorefonts no missing Arial issue
Ensure to set locale via Locale.setDefault(Locale.ROOT); Get rid of issue the cultural issue ;)

Knowing that this is not a lightweight docker image anymore, but it works we used the following Dockerfile.

FROM openjdk:11-jdk
RUN echo "update packages" && apt update && \
  echo "install ms fonts" && \
    sed -i'.bak' 's/$/ contrib/' /etc/apt/sources.list && \
    apt update && \
    apt install -y ttf-mscorefonts-installer fontconfig && \
    fc-cache -f -v

// add other application files

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 davidvera
Solution 2 Dheeraj Malik
Solution 3