Upgrade to Java 21#5
Conversation
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
There was a problem hiding this comment.
🚩 swagger-inflector 2.0.11 depends on javax.servlet which may conflict with Java 21
The swagger-inflector at version 2.0.11 (pom.xml:255) is built on the javax.servlet API. While the servlet API is bundled by Jetty/the WAR container (not the JDK), a future upgrade of Jetty to 11+ or 12 would require migrating to jakarta.servlet, which would in turn require a newer swagger-inflector or a different framework. This dependency chain makes the Jetty upgrade (needed for Java 21 compat) non-trivial.
(Refers to line 255)
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
Agreed on the analysis, and this is exactly why the PR intentionally stays on javax. swagger-inflector 2.0.11 is javax.servlet/javax.ws.rs-only with no jakarta release, so the whole servlet stack (inflector + Jersey + Jetty) has to move together — which would mean replacing the core framework, not just bumping a dependency. That's a separate migration, out of scope for a Java-version upgrade.
For Java 21 specifically it isn't required: the javax servlet stack on Jetty 9.4.53 builds and runs on JDK 21 (verified — see the runtime test in the sibling thread). The Java-EE modules that were actually removed from the JDK (JAXB) are already provided as explicit javax.xml.bind / com.sun.xml.bind deps, so nothing is missing at runtime. Leaving this as a documented known follow-up rather than expanding this PR's scope.
| <maven.compiler.release>21</maven.compiler.release> | ||
| <swagger-parser-version>2.1.21</swagger-parser-version> | ||
| <swagger-core-version>2.2.17</swagger-core-version> | ||
| <jackson-version>2.16.1</jackson-version> |
There was a problem hiding this comment.
🔴 Jetty 9.4 is not supported on Java 21, risking runtime failures from strong module encapsulation
The PR upgrades the JDK from 8/11 to 21 in both Dockerfiles (Dockerfile:1, Dockerfile-telemetry:1) and the Maven compiler (pom.xml:51), but leaves Jetty at version 9.4.53 (pom.xml:256). Jetty 9.4.x officially supports only Java 8–11 (with limited compatibility up to 17). Java 21 enforces strong encapsulation of internal JDK APIs by default, and Jetty 9.4 is known to access internal APIs (e.g. sun.misc.Unsafe, sun.net.www.*) via reflection. Without --add-opens JVM flags, this will cause InaccessibleObjectException at runtime. The Jetty project recommends Jetty 10/11 for Java 11–17 and Jetty 12 for Java 17+. The jetty-runner used in both Dockerfiles (pom.xml:87-88) will be affected.
(Refers to lines 251-256)
Prompt for agents
The jetty-version property at pom.xml:256 is still 9.4.53.v20231009, which is not compatible with Java 21. Jetty 9.4 relies on internal JDK APIs that are strongly encapsulated in Java 21, leading to InaccessibleObjectException at runtime.
To fix this, upgrade Jetty to a version that officially supports Java 21:
- Jetty 12.x is the recommended line for Java 17+ (uses Jakarta Servlet 6.0)
- Jetty 11.x supports Java 11-17 (uses Jakarta Servlet 5.0)
- Jetty 10.x supports Java 11-17 (uses javax.servlet 4.0)
Note that upgrading from Jetty 9 to Jetty 10+ also involves a servlet API migration (javax.servlet to jakarta.servlet for Jetty 11/12). The jetty-runner artifact name may also change. The swagger-inflector dependency (2.0.11) also uses javax.servlet, so the entire servlet stack needs to be considered together.
Alternatively, as a short-term workaround, you could add --add-opens JVM flags in the Dockerfile CMD lines (e.g. --add-opens java.base/sun.misc=ALL-UNNAMED), but this is fragile and not a long-term solution.
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
Thanks — I investigated this concrete runtime claim empirically on JDK 21 before merging, and Jetty 9.4.53 runs cleanly here.
Test (OpenJDK 21.0.11, jetty-runner on the produced WAR), exercising the full request lifecycle including the reflection-heavy JAXB/XML path:
GET /api/v3/pet/1(JSON) → 200GET /api/v3/pet/1withAccept: application/xml→ 200, correct JAXB-serialized<Pet>…</Pet>GET /api/v3/pet/findByStatus?status=available→ 200POST /api/v3/pet(JSON body) → 200GET /api/v3/store/inventory→ 200
Server log contained no InaccessibleObjectException, no "illegal/ reflective access" warnings, and no sun.misc.Unsafe complaints — only the benign SLF4J no-op-binder notice and the jetty-runner is deprecated message. No --add-opens flags were needed.
On the upgrade path: Jetty can't be bumped here without replacing the framework. The app is built on swagger-inflector 2.0.11, which is javax.servlet-only. Jetty 11/12 use jakarta.servlet (incompatible with inflector 2.0.11 — there is no jakarta release of it), and Jetty 10 is the last javax.servlet line but is EOL and officially targets Java 11–17. So Jetty 9.4 (javax) is actually the best-supported option that keeps the current framework working on Java 21, and it's verified to do so. A Jetty 12 / jakarta move would be a separate framework-replacement effort, out of scope for this Java-version bump. If a future code path ever does trip encapsulation, the documented mitigation is --add-opens in the Dockerfile CMD, but it isn't required today.
Summary
Upgrades the build, runtime, and container images of this Swagger Inflector / Jetty JAX-RS app from Java 8 to Java 21 (LTS). This is the integration branch (
migration/java-21-migration) aggregating two task PRs: pom build config (#4) and Dockerfiles (#3).The app builds and runs on Java 21 with only a compiler-target bump — no
javax→jakartamigration is needed or appropriate here:swagger-inflector2.0.11 isjavax-only (there is nojakartarelease), and thejavaxJAX-RS/Jersey/Jetty 9.4 stack runs fine on JDK 21.javax.xml.bind:jaxb-api,com.sun.xml.bind:jaxb-*), so JAXB keeps working on 21.Changes
pom.xml:All
javax.*dependencies are intentionally left untouched.Dockerfile/Dockerfile-telemetry:Verification (JDK 21)
mvn clean package→ BUILD SUCCESS (test phase run, not skipped) producingtarget/swagger-petstore-1.0.27.war.jetty-runner:GET /api/v3/openapi.json→ 200 andGET /api/v3/store/inventory→ 200.docker buildof both images succeeds; container smoke test returns HTTP 200.The repo has no
.github/workflowsCI, so the verification gate is the Maven build + runtime smoke test above.Link to Devin session: https://partner-workshops.devinenterprise.com/sessions/121aff8a16234636a32e02276d172f25