Skip to content

Upgrade to Java 21#5

Open
devin-ai-integration[bot] wants to merge 4 commits into
mainfrom
migration/java-21-migration
Open

Upgrade to Java 21#5
devin-ai-integration[bot] wants to merge 4 commits into
mainfrom
migration/java-21-migration

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Jun 17, 2026

Copy link
Copy Markdown

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 javaxjakarta migration is needed or appropriate here:

  • swagger-inflector 2.0.11 is javax-only (there is no jakarta release), and the javax JAX-RS/Jersey/Jetty 9.4 stack runs fine on JDK 21.
  • The Java-EE modules removed from the JDK are already declared as explicit deps (javax.xml.bind:jaxb-api, com.sun.xml.bind:jaxb-*), so JAXB keeps working on 21.

Changes

pom.xml:

 maven-compiler-plugin (3.11.0):
-  <source>1.8</source>
-  <target>1.8</target>
+  <release>21</release>
+<maven.compiler.release>21</maven.compiler.release>   <!-- property -->
+maven-war-plugin            pinned 3.4.0   <!-- was implicit Maven default; 3.4.0 is JDK21-safe -->
 build-helper-maven-plugin   1.12   -> 3.6.0
 maven-jar-plugin            2.6    -> 3.4.1
 maven-resources-plugin      2.4.3  -> 3.3.1

All javax.* dependencies are intentionally left untouched.

Dockerfile / Dockerfile-telemetry:

- FROM openjdk:8-jre-alpine      (Dockerfile)
+ FROM eclipse-temurin:21-jre-alpine
- FROM openjdk:11-jre-slim       (Dockerfile-telemetry)
+ FROM eclipse-temurin:21-jre

Verification (JDK 21)

  • mvn clean package → BUILD SUCCESS (test phase run, not skipped) producing target/swagger-petstore-1.0.27.war.
  • Runtime smoke via jetty-runner: GET /api/v3/openapi.json → 200 and GET /api/v3/store/inventory → 200.
  • docker build of both images succeeds; container smoke test returns HTTP 200.

The repo has no .github/workflows CI, so the verification gate is the Maven build + runtime smoke test above.

Link to Devin session: https://partner-workshops.devinenterprise.com/sessions/121aff8a16234636a32e02276d172f25


Open in Devin Review

@devin-ai-integration

Copy link
Copy Markdown
Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 2 potential issues.

Open in Devin Review

Comment thread pom.xml

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚩 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)

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread pom.xml
Comment on lines +251 to 254
<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>

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 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.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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) → 200
  • GET /api/v3/pet/1 with Accept: application/xml → 200, correct JAXB-serialized <Pet>…</Pet>
  • GET /api/v3/pet/findByStatus?status=available → 200
  • POST /api/v3/pet (JSON body) → 200
  • GET /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.

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.

1 participant