Release Artifacts: What Goes Where
A 4.x Tika release publishes to three channels, each with a different audience:
| Channel | URL | Audience |
|---|---|---|
Maven Central |
Java consumers adding Tika to a Maven / Gradle build. Get lean basic jars plus pom + sources-jar + javadoc-jar. Maven resolves transitive deps for them. |
|
Apache dist |
Humans downloading runnable archives or drop-in plugin zips. No Maven involved. Want fat / self-contained artifacts. |
|
Docker Hub |
|
Container deployers. |
The driving principle: fat distribution artifacts (zips, shaded jars, runnable bundles) do not go to Maven Central; basic Maven artifacts (slim jars + pom) do not need to clutter Apache dist. Channel-specific shapes keep each ecosystem clean.
Per-artifact matrix
| Artifact | Maven Central | Apache dist | Docker apache/tika |
Docker apache/tika-grpc |
|---|---|---|---|---|
|
✓ slim jar (Maven-native) |
— |
inside the image |
inside the image |
|
✓ slim jar |
✓ assembly zip (slim jar + |
— |
— |
|
✓ slim jar |
— |
— |
— |
|
— |
✓ |
extracted into image |
— |
|
✓ slim jar |
✓ assembly zip (slim jar + |
— |
— |
|
✓ slim jar (~10 KB, metadata) |
✓ |
— (mount the shaded jar into |
inside the image |
|
✓ slim jar |
✓ pf4j zip distribution |
only |
all of them, inside the image |
|
✓ |
— |
— |
inside the image |
|
✗ not attached (TIKA-4723: |
— |
— |
— (local debugging only; the image build assembles its own context) |
|
— |
✓ |
— |
— |
Why each shape
Slim vs shaded jars (parser packages)
tika-parser-scientific-package (and sqlite3, nlp) are
"drop-in classpath" artifacts. Sysadmins running tika-server who want a
parser added to its classpath grab one fat jar and cp it into
/tika-extras/. That’s the use case the shaded jar serves on Apache dist.
A Maven consumer wanting the same parsers does not want a 25 MB jar
shaded over their classpath — Maven’s transitive dep resolution gives them
the same classes via the module jar + its deps. So Central gets the slim
(~10 KB) metadata jar; pom transitive deps do the work.
Mechanism: maven-shade-plugin configured with
<outputFile>${project.build.directory}/${project.artifactId}-${project.version}-shaded.jar</outputFile>
and <shadedArtifactAttached>false</shadedArtifactAttached>. Shade writes
the fat jar to a separate file on disk but does not attach it to the
Maven artifact set, so mvn deploy only uploads the slim main jar.
pf4j plugin zips (tika-pipes-*)
The .zip for each pipes plugin is the runtime drop-in form: unzip into
<server>/plugins/<plugin-name>/ and pf4j discovers it at startup. That’s
an Apache dist artifact, not a Maven artifact.
The plugin’s jar is on Maven Central for users building atop the plugin API or embedding it programmatically.
Mechanism: maven-assembly-plugin with <attach>false</attach> in each
plugin pom (TIKA-4723). Because <attach>false</attach> also skips the
local-repo install, each plugin pom additionally runs
maven-install-plugin:install-file during the package phase, writing
the zip into the local repo at canonical coordinates
(<groupId>:<artifactId>:zip:<version>). Sibling modules
(tika-pipes-fork-parser, tika-server-*, tika-grpc, integration
tests) declare the zip as a test-scope Maven dep and rely on this
mechanism to resolve it from the local repo without ever publishing it
to Central.
The package binding is deliberate and must not be moved to install.
A reactor mvn package — what the tika-main-jdk21 and tika-main-jdk26
Jenkins jobs run, and what a contributor building the tree runs — never
reaches the install phase, so an install-bound install-file leaves
the zip unresolvable and every consuming module fails dependency
resolution. It builds only where a previous mvn install/deploy on the
same machine happened to leave a matching zip in the local repo, which
made the breakage look intermittent until the 4.0.0 → 4.1.0-SNAPSHOT
bump invalidated every cached copy.
tika-grpc
tika-grpc is a standalone gRPC server, parallel to tika-server — not built
on top of tika-server-core. It depends directly on tika-core and the
parser modules (via tika-parsers-standard-package).
Maven Central gets the slim tika-grpc.jar for users embedding the gRPC
server in a Maven build. Apache dist publishes nothing for tika-grpc.
Users either pull apache/tika-grpc from Docker Hub or add tika-grpc
as a Maven dep.
The release workflow builds the image from a build context it assembles
itself (dependency:copy-dependencies for the runtime jars, plus a cp of
every pipes-plugin zip and parser-package jar) — nothing there is published
as a release artifact. mvn package -Pdocker -pl tika-grpc produces an
equivalent runnable tika-grpc-<v>.zip for local debugging only; the image
build does not consume it.
tika-grpc expects pf4j plugins for full functionality; starting without plugins logs a warning with a download URL pointing at Apache dist. Most fetcher-dependent RPC calls will fail at runtime if no plugins are present.
Server: slim jar on Central, bin.zip on dist
tika-server-standard-<v>.jar is the slim runtime jar — its manifest
declares Class-Path: lib/ and it expects to be run from a directory
that also contains a populated lib/ (and plugins/). Standalone the
slim jar can’t run. Maven Central publishes it for embedders who’ll
resolve lib/ via Maven dep resolution.
tika-server-standard-<v>.zip is the full assembled distribution:
the slim jar + lib/ + the bundled tika-pipes-file-system plugin + a
startup script. Apache dist publishes this for sysadmins who want
unzip + java -jar.
Dist carries only the .zip: no slim jar, no -bin.tgz, no -bin
classifier. The name is tika-server-standard-<v>.zip, consistent with
tika-app, tika-eval-app, and the pipes plugins.
Where this is configured in the source tree
The Apache dist staging include list: pom.xml, apache-release
profile, the <copy> step inside the antrun task. One <include> line per
artifact, each ending in so any signature already produced by the build
travels with it (CHANGES.txt is copied verbatim). The pipes-plugin zips are
covered by a single glob,
tika-pipes/tika-pipes-plugins//target/tika-pipes--$\{project.version}.zip,
so adding a plugin needs no change here. After the copy, the same antrun task
generates the .sha512 and .asc files and fails the build on a missing or
unsigned artifact.
Per-module shaping: each module’s pom decides what shape its target/
produces (assembly with <attach>false</attach> for plugin zips and
app zips; shade with outputFile + <shadedArtifactAttached>false</shadedArtifactAttached>
for parser packages).
Maven Central deployment: happens via mvn deploy (or
mvn release:perform). Any artifact that’s attached to the Maven project
gets uploaded. The whole point of the <attach>false</attach> /
<shadedArtifactAttached>false</shadedArtifactAttached> pattern is to
keep the fat distribution shapes off Central without disrupting the
build process.
Docker image contents: .github/workflows/docker-release.yml (the
release publish workflow). The release-tika-grpc job currently
assembles a custom build context from per-module outputs (
dependency:copy-dependencies, per-plugin cp, parser-package cp).
The release-tika-server job builds from tika-server-standard-<v>.zip
(unpacked into /opt/tika-server/).