Skip to content

Bump Tomcat to 11.0.x and base Docker image to JDK 21 - #344

Open
tungleduyxyz wants to merge 2 commits into
masterfrom
jruby10-tomcat-upgrade
Open

tungleduyxyz wants to merge 2 commits into
masterfrom
jruby10-tomcat-upgrade

Conversation

@tungleduyxyz

@tungleduyxyz tungleduyxyz commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Summary

Companion PR to killbill-admin-ui-standalone's JRuby 10 upgrade. jruby-rack 2.0.0 (the release that targets JRuby 10/JDK21) is compiled against jakarta.servlet, which requires a Jakarta EE servlet container (Tomcat 10+) and a JDK 21+ JVM to run it.

Targets Tomcat 11.0.x rather than 10.1.x: both major lines are currently supported by the Tomcat project (which keeps 3 concurrent supported major versions), but 11.0.x implements the newest specs (Servlet 6.1 vs 10.1's 6.0) and will have a longer support runway before the next EOL rotation. Since we already require JDK 21 for jruby-rack 2.0 regardless, there's no downside to going straight to 11.0.x (it only requires JDK 17+; 10.1's JDK 11+ floor is irrelevant here).

  • ansible/roles/tomcat/tasks/install.yml: bump the maven-metadata.xml version regex and download URL from tomcat-10 (10.1.x) to tomcat-11 (11.0.x).
  • ansible/templates/tomcat/conf/web.xml.j2: update the schema from jakarta.ee/web-app_6_0.xsd to jakarta.ee/web-app_6_1.xsd, matching Tomcat 11's actual bundled default web.xml. server.xml.j2/context.xml.j2 needed no changes (pure org.apache.catalina.* internal classes, unaffected by the servlet spec version).
  • docker/templates/base/latest/Dockerfile: openjdk-11-jdk-headless -> openjdk-21-jdk-headless, and the java-11-openjdk -> java-21-openjdk JAVA_HOME symlink.

Validation

Validated the maven-metadata.xml regex against the live endpoint (resolves to 11.0.25, matching the current official Tomcat download page). Built the killbill-admin-ui-standalone WAR (rack 2.2.24 + jruby-rack 2.0.0 + json 2.21.2 + csv fix) and deployed it to a real local Tomcat 11.0.25 instance under JDK 21 end-to-end: booted successfully with no errors, served an HTTP 302 redirect to /users/sign_in with correct session cookie handling and Transfer-Encoding: chunked, and correctly established a JDBC connection. jruby-rack 2.0.0 (built against Servlet 6.0) works unmodified against Tomcat 11's Servlet 6.1 API, as expected since 6.1 is backward compatible with 6.0.

Important: shared base image

This base Docker image is shared with the killbill/killbill core server image. The core server team should validate their own deployment is compatible with Tomcat 11 (javax vs jakarta.servlet) and JDK 21 before this rolls out to production; core server source is out of scope for this repo/PR.

Comment thread ansible/roles/tomcat/tasks/install.yml Outdated
Arises from the killbill-admin-ui-standalone JRuby 10 upgrade: jruby-rack
2.0.0 (the release that targets JRuby 10/JDK21) is compiled against
jakarta.servlet, which requires a Jakarta EE servlet container (Tomcat
10+) and a JDK 21+ JVM to run it.

Targets Tomcat 11.0.x rather than 10.1.x: both major lines are currently
supported by the Tomcat project (which keeps 3 concurrent supported major
versions), but 11.0.x implements the newest specs (Servlet 6.1 vs 10.1's
6.0) and will have a longer support runway before the next EOL rotation.
Since we already require JDK 21 for jruby-rack 2.0 regardless, there's no
downside to going straight to 11.0.x (it only requires JDK 17+, same as
10.1's JDK 11+ floor is irrelevant here).

- ansible/roles/tomcat/tasks/install.yml: bump the maven-metadata.xml
  version regex and download URL from tomcat-10 (10.1.x) to tomcat-11
  (11.0.x). Validated the regex against the live
  repo1.maven.org/maven2/org/apache/tomcat/tomcat/maven-metadata.xml
  (resolves to 11.0.25, matching the current official download page).
- ansible/templates/tomcat/conf/web.xml.j2: update the schema from
  jakarta.ee/web-app_6_0.xsd to jakarta.ee/web-app_6_1.xsd, matching
  Tomcat 11's actual bundled default web.xml (verified against a real
  local Tomcat 11.0.25 install). server.xml.j2/context.xml.j2 needed no
  changes (pure org.apache.catalina.* internal classes, unaffected by the
  servlet spec version).
- docker/templates/base/latest/Dockerfile: openjdk-11-jdk-headless ->
  openjdk-21-jdk-headless, and the java-11-openjdk -> java-21-openjdk
  JAVA_HOME symlink.

Validated end to end: built the killbill-admin-ui-standalone WAR (rack
2.2.24 + jruby-rack 2.0.0 + json 2.21.2 + csv fix) and deployed it to a
real local Tomcat 11.0.25 instance under JDK21 - it booted successfully
with no errors, served an HTTP 302 redirect to /users/sign_in with
correct session cookie handling and Transfer-Encoding: chunked, and
correctly established a JDBC connection. jruby-rack 2.0.0 (built against
Servlet 6.0) works unmodified against Tomcat 11's Servlet 6.1 API, as
expected since 6.1 is backward compatible with 6.0.

IMPORTANT: this base Docker image is shared with the killbill/killbill
core server image. The core server team should validate their own
deployment is compatible with Tomcat 11 (javax vs jakarta.servlet) and
JDK 21 before this rolls out to production; core server source is out of
scope for this repo.

Co-authored-by: Copilot <[email protected]>
@tungleduyxyz
tungleduyxyz force-pushed the jruby10-tomcat-upgrade branch from 4dd501b to b2a4223 Compare September 9, 2026 03:55
@tungleduyxyz tungleduyxyz changed the title Bump Tomcat to 10.1.x and base Docker image to JDK 21 Bump Tomcat to 11.0.x and base Docker image to JDK 21 Sep 9, 2026
…2.x)

CI on this PR was failing: "Build killbill/base:latest" step, in the
"Configure native libraries" ansible task:

  configure: error: yes is not a directory

Root-caused by extracting and diffing the tomcat-native.tar.gz bundled in
each Tomcat distribution:
- Tomcat 9.0.x (the pre-PR baseline) bundles Tomcat Native 1.3.8, whose
  configure script special-cases the literal value "yes" for --with-ssl
  (falls back to auto-detecting OpenSSL from standard system paths).
- Tomcat 10.1.x AND 11.0.x both bundle Tomcat Native 2.0.x (2.0.9 and
  2.0.15 respectively), whose configure script dropped that special case:
  it now only accepts "no" or an actual directory path, otherwise erroring
  with "<value> is not a directory".

This means the bug was latent in the jump from Tomcat 9.0.x to EITHER
10.1.x or 11.0.x - not specific to the choice of 11.0.x made in this PR.

Fix: drop the --with-ssl=yes argument entirely. Confirmed by reading both
configure scripts that omitting --with-ssl produces the exact same
auto-detect-from-system-paths behavior as passing "yes" did on tcnative
1.x, and is also the documented tcnative 2.x default (skips the explicit
value check, falls through to the same "guess it" search over
/usr /usr/local /usr/local/ssl /usr/pkg /usr/sfw).

Validated by fully reproducing the native build in a fresh ubuntu:24.04
container (same toolchain packages the "Install toolchain" task installs:
dpkg-dev, gcc, libapr1-dev, libssl-dev, make; same JDK: openjdk-21-jdk-headless)
using Tomcat 11.0.25's actual bundled tomcat-native.tar.gz:
  checking for OpenSSL location... using openssl from /usr/lib and /usr/include
  checking OpenSSL library version >= 3.0.0... ok
  configure: creating ./config.status  (exit 0)
Then ran `make all` (produced libtcnative-2.so.0.0.15) and `make install`
(landed correctly in the configured libdir) - both exit 0.

Co-authored-by: Copilot <[email protected]>
@vnandwana

Copy link
Copy Markdown
Contributor

AMI and Docker image generation is triggered from the aws-marketplace repo, which has killbill-cloud as an Ansible Galaxy requirement. So, some changes are needed in aws-marketplace as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants