Skip to content

HDDS-8280. Upgrade Jetty 9.4 to 12 (Jakarta EE10) - #11201

Open
yandrey321 wants to merge 11 commits into
apache:masterfrom
yandrey321:HDDS-8280
Open

HDDS-8280. Upgrade Jetty 9.4 to 12 (Jakarta EE10)#11201
yandrey321 wants to merge 11 commits into
apache:masterfrom
yandrey321:HDDS-8280

Conversation

@yandrey321

Copy link
Copy Markdown
Contributor

What changes were proposed in this pull request?

Approach

The bulk of the diff is mechanical: javax.servletjakarta.servlet,
javax.ws.rsjakarta.ws.rs, javax.annotation.{PostConstruct,PreDestroy,Priority}
jakarta.*, org.eclipse.jetty.servlet.*org.eclipse.jetty.ee10.servlet.*, and the
version matrix in the root pom (Jetty 12.0.38, Jersey 3.1.12, jakarta.ws.rs-api 3.1.0,
jakarta.servlet-api 6.0.0, Weld 5.1.7, Guice 7.0.0, CDI-api 4.0.1). Transitive
Jetty 9 is excluded from the hadoop-common/hdfs dependencies so only Jetty 12 is on the
server classpath.

The rest of this description covers the non-mechanical parts — the places where a
straight rename was not sufficient.

1. javax↔jakarta servlet bridge for hadoop's auth filters (central design choice)

hadoop-common stays on javax.servlet / Jetty 9 upstream, but Ozone's SPNEGO / Kerberos /
delegation-token authentication is provided by hadoop's javax.servlet.Filter
implementations. Rather than fork that authentication chain, a minimal bridge
(hadoop-hdds/framework/.../server/http/servletbridge/) wraps a javax filter as a jakarta
Filter (JavaxFilterBridge), presents jakarta request/response as javax views to the
delegate, and overlays the authenticated principal (remote user, user principal, auth type,
roles) back onto the jakarta request for the downstream chain. ServletElementsFactory
is the single wiring point (holder.setFilter(new JavaxFilterBridge(...))). This keeps
hadoop's auth code as the source of truth while the HTTP stack runs on jakarta, and is why
both javax.servlet-api (3.1.0) and jakarta.servlet-api (6.0.0) are kept on the classpath
(different packages, so they coexist).

2. Forked JMXJsonServlet into Ozone (jakarta)

hadoop-common's JMXJsonServlet is javax-based and cannot be registered on a jakarta
ServletContextHandler, so it is forked into
hadoop-hdds/framework/.../server/http/JMXJsonServlet.java as a jakarta servlet with
identical behavior. (Ozone already forks HttpServer2/HddsConfServlet, so this follows
the existing pattern.)

3. HttpServer2 structural rewrite for removed/changed Jetty 12 APIs

  • HandlerCollection (removed) → Handler.Sequence + ContextHandlerCollection.
  • RequestLogHandler (removed) → CustomRequestLog set directly on the Server.
  • org.eclipse.jetty.util.ArrayUtil (removed) → java.util.Arrays.
  • MultiException (removed) → ExceptionUtil.MultiException.
  • Base-resource strictness: Jetty 12 validates a context's base resource at start-up and
    refuses to start when it does not exist (Jetty 9 tolerated it). The shared /static assets
    are unpacked into each module's webapps/ directory at package time, so they are present
    in the packaged jar/dist but absent during the unit-test phase. Both default contexts are
    guarded: /logs creates its directory, and /static is served only when its base resource
    exists. This preserves production behavior while letting OM/SCM HTTP-server unit tests start.

4. S3ContentTypeFilter — keep the bare application/xml content-type

AWS S3 (and Ozone pre-upgrade) return application/xml with no charset. On Jetty 12 the
response tracks a character encoding that, once promoted from NOT_SET internally, causes
Jetty to rebuild the header as application/xml;charset=utf-8 even when a bare value was set.
The new filter resets the tracked encoding to NOT_SET right before writing an
application/xml content-type, so S3 clients continue to see the bare value they expect.

5. CDI 4 / Weld 5 bean discovery (s3gateway)

CDI 4's default bean-discovery-mode changed from all to annotated, which caused Weld 5
to skip beans like OzoneClientCache that were previously discovered. The s3gateway
beans.xml files are set to version="4.0" bean-discovery-mode="all" to preserve discovery.

6. JAX-RS / DI container wiring

  • web.xml descriptors bumped to Servlet 6.0 (jakarta namespace,
    https://jakarta.ee/xml/ns/jakartaee, web-app_6_0.xsd) with jakarta.ws.rs.Application
    init-params (recon, s3gateway, httpfsgateway).
  • Recon moves to Guice 7 (jakarta GuiceFilter).
  • Recon JAXB: EE10's jakarta.xml.bind-api 4.0.x dropped an API Recon relied on at runtime;
    this surfaced only in the assembled distribution as jakarta.xml.bind.PropertyException.
    The JAXB dependency is aligned so the runtime resolves against jakarta 4.0.x.

7. Stricter default URI compliance (S3 proxy test harness)

Jetty 12's default URI compliance rejects // and percent-encoded characters that appear in
S3 object keys. The S3 integration-test ProxyServer sets UriCompliance.LEGACY and enables
setDecodeAmbiguousURIs(true) so such keys are forwarded rather than 400-rejected, matching
the S3 Gateway's own lenient handling.

Generated-by: Claude Code (claude-opus-4-8)

What is the link to the Apache JIRA

https://issues.apache.org/jira/browse/HDDS-8280

How was this patch tested?

CI: https://github.com/yandrey321/ozone/actions/runs/33823459774/job/100873964388

Unit, integration, robot tests.

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