Description
Add first-class EE8 (javax.servlet) modules to JGit, alongside the
canonical jakarta.servlet modules — org.eclipse.jgit.http.server.ee8,
org.eclipse.jgit.lfs.server.ee8, and their test modules — so downstream
consumers that cannot migrate to jakarta.servlet can keep tracking JGit
master.
The modules are generated from the canonical sources: only the servlet
imports are rewritten (jakarta.servlet → javax.servlet, Jetty EE10 → EE8),
with the original Java package names and source line numbers preserved.
Apart from being generated, they get the full first-class treatment:
- Both toolchains — Bazel (a shared,
sed-based servlet-flavour transform
from bazlets, @com_googlesource_gerrit_bazlets//tools; no added external
dependency) and Maven (copy-and-rewrite reactor).
- Real OSGi bundles —
META-INF/MANIFEST.MF importing javax.servlet,
plus Eclipse PDE project files.
- Tested — a Bazel
generated_srcs_test (derivation, line-count
preservation, no jakarta residue) and the EE8 Maven reactor tests; both run
the HTTP/LFS suites against the generated EE8 jars.
- IDE-debuggable — the generated source jar attaches to the EE8 binary jar;
breakpoints in the running javax.servlet classes bind correctly (verified
live in Eclipse and IntelliJ).
This mirrors Jetty 12's own EE8 + EE10 dual model.
It is deliberately minimally invasive: the canonical production servlet
modules and sources are untouched, original package names are kept (zero import
churn for consumers), and there is no change to the JGit p2 update site. The
Bazel transform carries no per-repo data — it selects only the to_javax
direction of the shared bazlets toolchain.
The one restriction — no Tycho/p2 publishing. The EE8 modules keep the same
exported packages (same class FQDNs) as the canonical ones, so the two must
never share a classpath. They are therefore intentionally not added to the
JGit features, the p2 repository, or the target platform. Because p2 is off the
table, Bazel and Maven are the delivery channels: Bazel for source consumers
(Gerrit builds JGit from source), Maven for build/test and the artifact shape
needed for future binary (Maven Central) publication.
Motivation
JGit master ships its servlet-facing modules on jakarta.servlet
(Servlet 6 / Jetty 12 EE10). Major downstreams — Gerrit Code Review, Gitiles
and the Gerrit plugin ecosystem — still run on javax.servlet (Servlet 4 / Jetty 12
EE8) and cannot move to jakarta.servlet yet.
For Gerrit's stable branches the blocker is concrete: the incompatibility lies
along two orthogonal axes.
- Servlet namespace — Gerrit
stable-3.12/stable-3.13 are javax.servlet
(Servlet 4 / Jetty 12 EE8), while JGit master and stable-7.4 are
jakarta.servlet.
- Build system — Gerrit stable still uses WORKSPACE, while JGit master and
the master-tracking javax.servlet branch (servlet-4) use bzlmod.
Each candidate JGit branch satisfies only one axis — stable-7.4 is WORKSPACE
but jakarta, servlet-4 is javax but bzlmod — so Gerrit stable, which needs
javax on WORKSPACE, has no JGit branch that fits today.
The goal is to close this gap so the JGit submodule can be bumped on the
supported Gerrit releases (stable-3.12/stable-3.13) to JGit stable-7.4.
Gitiles has already been adapted to consume the JGit EE8 servlet bridge, which
validates the approach end to end; Gerrit and its stable branches still need
the same first-class EE8 artifacts from JGit.
The consequences today:
- Gerrit cannot consume JGit master as-is, because JGit master is
jakarta.servlet-only.
- A separate servlet-4 JGit branch is not sustainable — it would never be a
stable release line and would demand constant merge work.
- The resulting stale JGit submodule on
stable-3.12/stable-3.13 holds
back picking up JGit fixes and features downstream.
Without first-class EE8 modules in JGit, every javax.servlet consumer is
forced into either an out-of-tree rewrite (reverted once already — see
Alternatives) or an unmaintainable fork. First-class, generated EE8 modules
let all of them track JGit master directly.
Options analysis for the stable-branch maintenance problem:
https://davido.github.io/gerrit-jgit-maintenance/
Alternatives considered
-
Gerrit-local on-the-fly rewrite — the earlier attempt (Ivan Frade,
https://gerrit-review.googlesource.com/c/gerrit/+/446221). It rewrote JGit's
servlet code downstream at build time. Reverted by Matthias Sohn
(https://gerrit-review.googlesource.com/c/gerrit/+/447822), "only works in
bazel build but breaks the build in Eclipse." It was also untested at the
IDE/generation level and lived only downstream, so every consumer would need
its own copy. This proposal addresses that revert reason directly: the
generated EE8 modules build in Bazel and Maven, attach sources and debug in
Eclipse and IntelliJ, and carry a generation test.
-
A long-lived servlet-4 JGit branch — unsustainable: never a stable release
line, perpetual merge work to keep it current with master.
-
Copying the servlet code into a parallel EE8 tree — ~6,500 LoC plus
duplicated tests to hand-maintain in lockstep with the canonical modules.
Rejected in favour of generation, which keeps EE8 a mechanical transform of the
canonical sources (same line numbers, no logic to drift).
-
Relocating to org.eclipse.jgit.*.ee8 packages (which would be
p2-co-installable alongside the canonical modules) — rejected: it breaks the
simple import-only generation and forces every consumer to change its
imports. Keeping the same FQDNs is deliberate; the only cost is that the EE8
modules can't be published to p2 (they'd collide with the canonical ones), and
Bazel + Maven cover the consumers that need them.
Additional context
A complete JGit implementation is already up for review, under topic
ee8-servlet-bridge.
Verification status:
- Bazel:
generated_srcs_test, http.test.ee8:http,
lfs.server.test.ee8:lfs_server → all pass.
- Maven (Java 17): EE8 reactor
test → BUILD SUCCESS, 293 tests,
0 failures.
- Review CI: use the public review systems as the source of truth for
current status; companion changes may need re-verification after prerequisite
bazlets/JGit pins are published.
Usable today. Where no officially supported Gerrit build with an updated
JGit exists yet, Gerrit can be built directly from the
Gerrit stable companion change,
which already pins the JGit submodule to the current stable-7.4 tip plus the
single commit that adds the EE8 bridge — so you get the latest stable-7.4 JGit
with the bridge out of the box, no manual JGit bump.
The canonical production servlet modules and sources are untouched — the EE8
modules are additive; the only canonical-source change is a shared junit.http
test-helper refactor (extracting an AppServerBase) so the EE8 test module can
reuse it.
Shared transform toolchain. The Bazel source transform, the JUnit-suite
macro, and the generated-sources checker live once in bazlets
(@com_googlesource_gerrit_bazlets//tools) as a dependency-free sed
package-prefix rewrite. JGit selects the to_javax direction. (It can equally
be vendored in-tree under tools/jgit-ee8 if the project prefers no bazlets
dependency.)
Adjacent ecosystem already migrated (mirroring the Gerrit companion; not
part of this request, listed to show the EE8 bridge works end to end for real
consumers):
- Gitiles — adapted to consume the JGit EE8 servlet bridge ("Move Gitiles
off JGit servlet-4 via EE8 bridge"): its //lib:jgit-servlet now resolves to
the generated jgit-servlet-ee8 module; servlet tests pass.
- Gerrit LFS plugin — migrated to the JGit EE8 servlet bridge (a
Bazel-9/Bzlmod build modernization commit, then the EE8 swap); plugin build
and tests pass.
Bigger picture (future goal — not part of this request). JGit master is
already EE10 (jakarta.servlet); this request adds the EE8 (javax.servlet)
half, so JGit would ship both flavours from one tree — mirroring Jetty 12. The
same shared transform already runs in the other direction too: Gitiles' EE10
flavour is published for review
(gitiles change 601822).
That dual-flavour Gerrit is described in its own design proposal, up for review
(Gerrit EE8/EE10 flavoured release);
it is motivation only here, not part of this request.
Prior work:
A fuller design write-up exists — the same-FQDN / no-p2 reasoning, the
per-commit breakdown, the verification details, and the alternatives in depth:
JGit EE8 Servlet Bridge — Design Proposal.
Happy to land it wherever best fits the project's process (GitHub Discussion,
project wiki, an in-tree doc alongside tools/jgit-ee8/README.md, or just an
external link).
Links:
Description
Add first-class EE8 (
javax.servlet) modules to JGit, alongside thecanonical
jakarta.servletmodules —org.eclipse.jgit.http.server.ee8,org.eclipse.jgit.lfs.server.ee8, and their test modules — so downstreamconsumers that cannot migrate to
jakarta.servletcan keep tracking JGitmaster.
The modules are generated from the canonical sources: only the servlet
imports are rewritten (
jakarta.servlet→javax.servlet, Jetty EE10 → EE8),with the original Java package names and source line numbers preserved.
Apart from being generated, they get the full first-class treatment:
sed-based servlet-flavour transformfrom bazlets,
@com_googlesource_gerrit_bazlets//tools; no added externaldependency) and Maven (copy-and-rewrite reactor).
META-INF/MANIFEST.MFimportingjavax.servlet,plus Eclipse PDE project files.
generated_srcs_test(derivation, line-countpreservation, no
jakartaresidue) and the EE8 Maven reactor tests; both runthe HTTP/LFS suites against the generated EE8 jars.
breakpoints in the running
javax.servletclasses bind correctly (verifiedlive in Eclipse and IntelliJ).
This mirrors Jetty 12's own EE8 + EE10 dual model.
It is deliberately minimally invasive: the canonical production servlet
modules and sources are untouched, original package names are kept (zero import
churn for consumers), and there is no change to the JGit p2 update site. The
Bazel transform carries no per-repo data — it selects only the
to_javaxdirection of the shared bazlets toolchain.
The one restriction — no Tycho/p2 publishing. The EE8 modules keep the same
exported packages (same class FQDNs) as the canonical ones, so the two must
never share a classpath. They are therefore intentionally not added to the
JGit features, the p2 repository, or the target platform. Because p2 is off the
table, Bazel and Maven are the delivery channels: Bazel for source consumers
(Gerrit builds JGit from source), Maven for build/test and the artifact shape
needed for future binary (Maven Central) publication.
Motivation
JGit master ships its servlet-facing modules on
jakarta.servlet(Servlet 6 / Jetty 12 EE10). Major downstreams — Gerrit Code Review, Gitiles
and the Gerrit plugin ecosystem — still run on
javax.servlet(Servlet 4 / Jetty 12EE8) and cannot move to
jakarta.servletyet.For Gerrit's stable branches the blocker is concrete: the incompatibility lies
along two orthogonal axes.
stable-3.12/stable-3.13arejavax.servlet(Servlet 4 / Jetty 12 EE8), while JGit master and
stable-7.4arejakarta.servlet.the master-tracking
javax.servletbranch (servlet-4) use bzlmod.Each candidate JGit branch satisfies only one axis —
stable-7.4is WORKSPACEbut jakarta,
servlet-4is javax but bzlmod — so Gerrit stable, which needsjavax on WORKSPACE, has no JGit branch that fits today.
The goal is to close this gap so the JGit submodule can be bumped on the
supported Gerrit releases (
stable-3.12/stable-3.13) to JGitstable-7.4.Gitiles has already been adapted to consume the JGit EE8 servlet bridge, which
validates the approach end to end; Gerrit and its stable branches still need
the same first-class EE8 artifacts from JGit.
The consequences today:
jakarta.servlet-only.stable release line and would demand constant merge work.
stable-3.12/stable-3.13holdsback picking up JGit fixes and features downstream.
Without first-class EE8 modules in JGit, every
javax.servletconsumer isforced into either an out-of-tree rewrite (reverted once already — see
Alternatives) or an unmaintainable fork. First-class, generated EE8 modules
let all of them track JGit master directly.
Options analysis for the stable-branch maintenance problem:
https://davido.github.io/gerrit-jgit-maintenance/
Alternatives considered
Gerrit-local on-the-fly rewrite — the earlier attempt (Ivan Frade,
https://gerrit-review.googlesource.com/c/gerrit/+/446221). It rewrote JGit's
servlet code downstream at build time. Reverted by Matthias Sohn
(https://gerrit-review.googlesource.com/c/gerrit/+/447822), "only works in
bazel build but breaks the build in Eclipse." It was also untested at the
IDE/generation level and lived only downstream, so every consumer would need
its own copy. This proposal addresses that revert reason directly: the
generated EE8 modules build in Bazel and Maven, attach sources and debug in
Eclipse and IntelliJ, and carry a generation test.
A long-lived servlet-4 JGit branch — unsustainable: never a stable release
line, perpetual merge work to keep it current with master.
Copying the servlet code into a parallel EE8 tree — ~6,500 LoC plus
duplicated tests to hand-maintain in lockstep with the canonical modules.
Rejected in favour of generation, which keeps EE8 a mechanical transform of the
canonical sources (same line numbers, no logic to drift).
Relocating to
org.eclipse.jgit.*.ee8packages (which would bep2-co-installable alongside the canonical modules) — rejected: it breaks the
simple import-only generation and forces every consumer to change its
imports. Keeping the same FQDNs is deliberate; the only cost is that the EE8
modules can't be published to p2 (they'd collide with the canonical ones), and
Bazel + Maven cover the consumers that need them.
Additional context
A complete JGit implementation is already up for review, under topic
ee8-servlet-bridge.Verification status:
generated_srcs_test,http.test.ee8:http,lfs.server.test.ee8:lfs_server→ all pass.test→BUILD SUCCESS, 293 tests,0 failures.
current status; companion changes may need re-verification after prerequisite
bazlets/JGit pins are published.
Usable today. Where no officially supported Gerrit build with an updated
JGit exists yet, Gerrit can be built directly from the
Gerrit stable companion change,
which already pins the JGit submodule to the current
stable-7.4tip plus thesingle commit that adds the EE8 bridge — so you get the latest
stable-7.4JGitwith the bridge out of the box, no manual JGit bump.
The canonical production servlet modules and sources are untouched — the EE8
modules are additive; the only canonical-source change is a shared
junit.httptest-helper refactor (extracting an
AppServerBase) so the EE8 test module canreuse it.
Shared transform toolchain. The Bazel source transform, the JUnit-suite
macro, and the generated-sources checker live once in bazlets
(
@com_googlesource_gerrit_bazlets//tools) as a dependency-freesedpackage-prefix rewrite. JGit selects the
to_javaxdirection. (It can equallybe vendored in-tree under
tools/jgit-ee8if the project prefers no bazletsdependency.)
Adjacent ecosystem already migrated (mirroring the Gerrit companion; not
part of this request, listed to show the EE8 bridge works end to end for real
consumers):
off JGit servlet-4 via EE8 bridge"): its
//lib:jgit-servletnow resolves tothe generated
jgit-servlet-ee8module; servlet tests pass.Bazel-9/Bzlmod build modernization commit, then the EE8 swap); plugin build
and tests pass.
Bigger picture (future goal — not part of this request). JGit master is
already EE10 (
jakarta.servlet); this request adds the EE8 (javax.servlet)half, so JGit would ship both flavours from one tree — mirroring Jetty 12. The
same shared transform already runs in the other direction too: Gitiles' EE10
flavour is published for review
(gitiles change 601822).
That dual-flavour Gerrit is described in its own design proposal, up for review
(Gerrit EE8/EE10 flavoured release);
it is motivation only here, not part of this request.
Prior work:
https://gerrit-review.googlesource.com/c/gerrit/+/446221
Eclipse": https://gerrit-review.googlesource.com/c/gerrit/+/447822
A fuller design write-up exists — the same-FQDN / no-p2 reasoning, the
per-commit breakdown, the verification details, and the alternatives in depth:
JGit EE8 Servlet Bridge — Design Proposal.
Happy to land it wherever best fits the project's process (GitHub Discussion,
project wiki, an in-tree doc alongside
tools/jgit-ee8/README.md, or just anexternal link).
Links:
https://github.com/davido/jgit-ee8-servlet-bridge-design-proposal
ee8-servlet-bridge):https://review.gerrithub.io/q/topic:%22ee8-servlet-bridge%22
ee8-servlet-bridge):https://gerrit-review.googlesource.com/q/topic:%22ee8-servlet-bridge%22
https://davido.github.io/gerrit-jgit-maintenance/