Design Notes for Tika 4.x

This document captures the design decisions and architectural changes in Apache Tika 4.x.

Metadata Keys

Namespacing every metadata key keeps user-controlled data from overwriting values Tika itself asserts. See Metadata Changes in 4.x for the key-by-key consequences.

Fat Jars and Maven Shade Strategy

Tika 4.x moves away from fat jar/shaded artifacts. The tika-app and tika-server jars are now thin launchers that resolve their dependencies from lib/ (and plugins from plugins/) via the manifest Class-Path. The trade-off is that the jar is no longer self-contained: it must be run from inside the unzipped distribution, not pulled from Maven Central on its own. See the migration guide.

Plugins and PF4J Framework

Plugin Packaging

PF4J plugins are packaged exclusively as zips (not jars) to align with the move away from fat jars. Custom code addresses race conditions during the unzipping process across threads and processes.

Classloader Management

The team disabled PF4J’s default classpath loading to avoid complexity in unit tests. A configured plugins directory is now required.

This strict boundary prevents issues when components are loaded separately. For example, JSON strings replace JsonNode objects to avoid problems with independent Jackson loading in plugins.

We tried to have as few Tika dependencies in the plugins as possible.

Serialization Architecture

Design Principles

  • Maximize Jackson usage while minimizing custom serialization code

  • Exclude Jackson from tika-core and tika-parsers-standard-modules dependencies

  • Enable runtime configuration updates via Jackson’s readerForUpdating

Security Model

Trusted config files at initialization, a registry-restricted instantiation path, and a fail-closed allowlist for anything arriving on the wire. See Serialization: security model for the rules and their boundary.

Implementation Challenges

  • Converted code to true Java beans with matching getters/setters

  • Replaced generic collections (List, Set) with concrete types (ArrayList, HashSet)

  • Converted Path fields to String due to Jackson constraints

  • Avoided Java records to enable readerForUpdating functionality

Annotations System

The @TikaComponent annotation handles:

  • Automatic service file generation at build time

  • Creation of META-INF/tika/*.idx mapping files

  • Kebab-case conversion of class names to friendly identifiers (e.g., PDFParserpdf-parser)

  • Manual name overrides via name attribute

  • Optional spi=false setting for non-service-file registration

Development Tips

Common Issues

  • Plugin directories and @TikaComponent annotations becoming out of sync across modules

  • IntelliJ conflicts with command-line builds

  • Checkstyle running before Spotless, causing preventable failures

Build one module and its dependencies, skipping tests, checkstyle, and spotless:

./mvnw clean install -am -pl :tika-app -Pfast

Apply formatting, then build:

./mvnw clean spotless:apply install

Outstanding Tasks

  • Implement flexible component loading without @TikaComponent requirements

  • Enable friendly name usage throughout the codebase

  • Fix external renderer byte-passing in open containers

  • Simplify and strengthen serialization code

  • Complete the tika-app config-dump CLI integration (Not Yet in 4.x)