Spring Boot and LibreOffice Integration: Local Conversion, Remote REST, and Docker Deployment Pitfalls

This article focuses on production-grade Spring Boot + LibreOffice integration for document-to-PDF conversion. It covers three practical paths: local mode, remote mode, and Docker deployment. The emphasis is on conversion performance, common misconceptions around remote calls, and layout corruption caused by missing fonts. Keywords: Spring Boot, LibreOffice, JODConverter.

Technical Specifications Snapshot

Parameter Description
Programming Language Java
Core Framework Spring Boot
Conversion Protocol Local UNO / Remote HTTP REST
Core Dependency jodconverter-spring-boot-starter 4.4.2
Local Dependency jodconverter-local 4.4.2
Remote Dependency jodconverter-remote 4.4.2
Runtime Environment Linux / Docker
Original Popularity 422 views, 7 likes, 12 saves

Document conversion in Spring Boot requires a clear deployment boundary first

When a business system needs to convert Word or Excel files to PDF, LibreOffice remains one of the most reliable options on the Java side. It offers strong compatibility with Office formats and fits backend batch conversion, contract archiving, and online preview scenarios.

In practice, Spring Boot integration with LibreOffice follows two main paths. One is local mode, where the application directly drives LibreOffice on the host machine. The other is remote mode, where the application calls a standalone conversion service. The coding experience is similar in both cases, but the deployment boundary is completely different.

Local mode works best for monolithic deployments and same-host conversion

Local mode is the most direct option. Spring Boot uses JODConverter to automatically manage the LibreOffice process pool, which makes it suitable when the application and LibreOffice run on the same host or inside the same container.


<dependency>

<groupId>org.jodconverter</groupId>

<artifactId>jodconverter-spring-boot-starter</artifactId>

<version>4.4.2</version>
</dependency>
<dependency>

<groupId>org.jodconverter</groupId>

<artifactId>jodconverter-local</artifactId>

<version>4.4.2</version>
</dependency>

These dependencies enable Spring Boot auto-configuration and add local LibreOffice conversion support.

jodconverter:
  local:
    enabled: true
    office-home: /opt/libreoffice24.2  # Specify the LibreOffice installation directory
    portNumbers: [8101, 8102, 8103]    # Multiple ports map to multiple worker processes
    maxTasksPerProcess: 100             # Maximum tasks per process
    task-execution-timeout: 360000      # Per-task execution timeout
    task-queue-timeout: 360000          # Task queue timeout
    process-timeout: 360000             # Process startup or shutdown timeout

The core value of this configuration is the multi-process conversion pool, which prevents a single blocked process from slowing down the entire service.

The conversion API remains consistent across both modes

Whether you use local mode or remote mode, your business code can continue to depend on DocumentConverter. This makes it easy to wrap the conversion logic in a reusable document service.

@Resource
private DocumentConverter documentConverter;

public void convert(InputStream inputStream, OutputStream outStream, File sourceFile, File targetFile) {
    // Stream-based conversion: convert a DOCX input stream to a PDF output stream
    documentConverter.convert(inputStream)
            .as(DefaultDocumentFormatRegistry.DOCX)
            .to(outStream)
            .as(DefaultDocumentFormatRegistry.PDF)
            .execute();

    // File-based conversion: convert the source file to a target PDF file
    documentConverter.convert(sourceFile)
            .to(targetFile)
            .as(DefaultDocumentFormatRegistry.PDF)
            .execute();
}

This code unifies both stream-based and file-based conversion entry points, which is ideal for building a generic document conversion service.

Remote mode does not work reliably by connecting directly to a soffice port

Many developers see the remote configuration and assume that exposing LibreOffice with --accept=socket... is enough for JODConverter to perform remote conversion. Real-world troubleshooting shows that this understanding is incomplete.


<dependency>

<groupId>org.jodconverter</groupId>

<artifactId>jodconverter-spring-boot-starter</artifactId>

<version>4.4.2</version>
</dependency>
<dependency>

<groupId>org.jodconverter</groupId>

<artifactId>jodconverter-remote</artifactId>

<version>4.4.2</version>
</dependency>

This dependency set enables remote HTTP service invocation, not a simple direct connection to a native UNO socket.

jodconverter:
  remote:
    enabled: true
    url: http://192.168.1.16:8100  # The URL must include the http protocol prefix
    ssl:
      enabled: false

The easiest detail to miss here is that url must include http://. Otherwise, it immediately throws java.net.MalformedURLException: no protocol.

Starting soffice and exposing a port directly usually causes remote timeouts

Many articles suggest the following command:

soffice --headless --nologo --nofirststartwizard --norestore \
  --accept="socket,host=0.0.0.0,port=8100;urp;" &

This command starts LibreOffice and makes it listen on a port, but it is not equivalent to the REST service required by JODConverter Remote. As a result, requests often hang and eventually fail with SocketTimeoutException: Read timed out.

The practical remote solution is to deploy the official JODConverter REST example service

A proven approach is to deploy the jodconverter-examples:rest image directly. In essence, it starts local LibreOffice inside the container and exposes a REST API externally. That is what matches the invocation model used by jodconverter-remote.

docker run -d -p 8100:8100 --privileged=true \
  -v /usr/share/fonts:/usr/share/fonts \
  -v /opt/application.properties:/etc/app/application.properties \
  ghcr.io/jodconverter/jodconverter-examples:rest

This command performs three critical actions: mounting fonts, mounting service configuration, and exposing the remote conversion API.

jodconverter.local.port-numbers=2002,2003
jodconverter.local.working-dir=/tmp
spring.servlet.multipart.max-file-size=5MB
spring.servlet.multipart.max-request-size=5MB
server.port=8100

These settings control the number of LibreOffice instances inside the container, upload limits, and the listening port of the REST service.

The images reveal why remote mode is often misunderstood

Image description AI Visual Insight: This image shows the structure of the JODConverter auto-configuration classes. The key point is that both local and remote configuration branches exist at the framework level. That means the framework supports two integration styles, but it does not mean remote mode can connect directly to a native soffice socket. It still requires an HTTP server implementation that matches its expected protocol.

Image description AI Visual Insight: This image reflects documentation or issue-tracker guidance indicating that Remote mode depends on an additional online service. The technical implication is that the remote side integrates with a wrapped web service rather than a bare LibreOffice process. For that reason, direct port connection timeouts indicate an architectural mismatch, not just a network problem.

Packing both the application and LibreOffice into one Docker image is rarely cost-effective

If you use only local mode and your application itself runs in Docker, then the container must include the LibreOffice executable. The most direct approach is to package the JAR and LibreOffice into the same image.

FROM registry.cn-beijing.aliyuncs.com/hub-mirrors/openjdk:8-jdk-alpine

RUN apk add --no-cache bash libreoffice

COPY app.jar app.jar
COPY fonts/zhFonts /usr/share/fonts

ENV JAVA_HOME=/usr/lib/jvm/default-jvm
ENV LIBREOFFICE_HOME=/usr/lib/libreoffice
ENV PATH=$JAVA_HOME/bin:$LIBREOFFICE_HOME/program:$PATH

ENTRYPOINT ["/bin/bash", "-c"]
CMD ["java -Djava.security.egd=file:/dev/./urandom -jar app.jar"]

This Dockerfile works, but the downside is obvious: the image size quickly grows to around 1 GB, which significantly increases CI build and distribution costs.

Image description AI Visual Insight: This image shows clues related to the example project or build scripts. It indicates that the official remote service is actually an independently packaged application-layer wrapper rather than a single LibreOffice binary. That further supports the recommendation to split out the conversion service instead of repeatedly embedding the full runtime into the business container.

Image description AI Visual Insight: This image highlights Docker build context and file layout issues. The technical point is that COPY depends on relative paths inside the build context and cannot arbitrarily reference absolute host paths. In practice, fonts, the JAR, and configuration files should be organized into a unified build directory in advance.

Image description AI Visual Insight: This image reflects the runtime result after image build. It shows that the application and LibreOffice can coexist in the same container, but it also reveals the growing cost in image size and operational complexity. In production, a more reasonable architecture is usually separate deployment: an application container plus a conversion service container.

Font availability is usually the real cause of broken Excel-to-PDF layout, not the code

The most subtle issue in a remote service is often not an API error. The conversion may appear to succeed, but the resulting layout is damaged. A common symptom is that after converting Excel to PDF, column widths, line wrapping, and Chinese text layout all become distorted.

Image description AI Visual Insight: This image shows the original Excel file with correct layout, usually including clear column widths, Chinese fonts, and cell boundaries. That indicates the source file itself is intact, so the problem does not originate in upload or file reading.

Image description AI Visual Insight: This image shows the PDF after conversion with obvious layout anomalies. Typical symptoms include font substitution for Chinese text, compressed text that changes wrapping behavior, and inaccurate column-width calculation. In containerized environments, these issues are usually caused by missing fonts rather than incorrect JODConverter API usage.

Font completeness determines visual consistency in remote conversion

If local conversion works, the server host also works, but the remote service inside Docker fails, check the font mount first. This is especially important for common office fonts such as SimSun, Microsoft YaHei, and SimHei. If those fonts are missing, LibreOffice falls back to substitute fonts, which directly changes pagination and layout.

docker run -d -p 8100:8100 \
  -v /usr/share/fonts:/usr/share/fonts \
  ghcr.io/jodconverter/jodconverter-examples:rest

In this command, the most important part is not the port. It is the font directory mount. Without it, Chinese documents are highly likely to show garbled text or layout drift.

The conclusion is to prefer service separation over forced same-container integration

From an engineering cost perspective, the best practice is neither to have the business application connect directly to soffice remotely nor to stuff LibreOffice into the business image. Instead, deploy JODConverter REST as an independent service and let Spring Boot call it through remote mode.

This approach delivers three advantages: clear deployment boundaries, lighter application images, and independent governance of fonts and the conversion environment. If you want the simplest path and have a controllable single-host deployment, local mode remains the first choice.

FAQ

Q1: How should I choose between local and remote when integrating LibreOffice with Spring Boot?

A: Choose local mode for single-host deployments and low-complexity scenarios. Choose a remote REST service when multiple applications need to share conversion capabilities or when you want independent scaling.

Q2: Why does jodconverter.remote still time out after I start soffice and expose a port?

A: Because remote mode expects an HTTP conversion service by default, not a bare socket-based soffice process. The two sides do not match at the protocol layer.

Q3: What should I check first when Excel-to-PDF output has broken formatting?

A: Check fonts first. If Docker or the remote server lacks Chinese fonts, the conversion may still succeed, but the layout will be visibly distorted.

Core summary

This article systematically reconstructs two practical approaches for integrating LibreOffice with Spring Boot: local JODConverter conversion and remote REST-based conversion. It also analyzes the key problems behind failed direct soffice connections in remote mode, oversized same-container Docker deployments, and Excel-to-PDF layout corruption caused by missing fonts.