yandrey321 opened a new pull request, #11367:
URL: https://github.com/apache/ozone/pull/11367

   ## What changes were proposed in this pull request?
   
   This patch upgrades Ozone from Jetty `9.4.58.v20250814` to Jetty `12.0.38`, 
targeting the
   **EE8** environment so that the `javax.servlet` namespace is retained.
   
   ### Why
   
   Jetty 9.x is out of community support and 9.4.x will never support JDK 17. 
Ozone server
   components already require JDK 17 (HDDS-14439). Staying on 9.4 blocks 
HDDS-8249 / HDDS-8250
   (JDK 17 crash fixes) and HDDS-16121 (Jetty `VirtualThreadPool`).
   
   Jetty 12's core no longer bundles a Servlet API. Servlet support moved into 
per-environment
   modules: `jetty-ee8-*` (`javax.servlet` 4.0), `jetty-ee9-*` 
(`jakarta.servlet` 5) and
   `jetty-ee10-*` (`jakarta.servlet` 6).
   
   ### Why EE8 rather than EE10
   
   Ozone depends on Hadoop 3.4.3, which is still `javax.servlet` 3.1. Targeting 
EE10 forces the
   entire web stack to `jakarta.*`: a `javax`→`jakarta` filter/listener bridge, 
forks of several
   hadoop-common servlet classes, and moving Jersey, Weld, CDI, Guice and JAXB 
to their jakarta
   lines. An earlier EE10 attempt on this Jira came to **357 changed files**, 
of which 265 were
   pure `javax.`→`jakarta.` import churn.
   
   EE8 reaches the same endpoint — one Jetty major and one `javax.servlet` 
provider on the
   classpath — in **48 files**. Jersey 2.48, Weld 3.x, Guice 6, CDI 2, JAXB 
2.3.x and every
   `web.xml` / `beans.xml` descriptor namespace are untouched.
   
   ### Dependency shape
   
   | Item | From | To |
   |---|---|---|
   | `jetty.version` | `9.4.58.v20250814` | `12.0.38` |
   | BOMs | `jetty-bom` | `jetty-bom` + `org.eclipse.jetty.ee8:jetty-ee8-bom` |
   | `servlet-api.version` | `3.1.0` (`javax.servlet:javax.servlet-api`) | 
`4.0.9` (`org.eclipse.jetty.toolchain:jetty-servlet-api`) |
   | `jetty-servlet` / `-webapp` / `-proxy` | `org.eclipse.jetty` | 
`org.eclipse.jetty.ee8:jetty-ee8-*` |
   | `jetty-http` / `-server` / `-util` / `-client` | unchanged | unchanged 
(Jetty 12 core) |
   | Jersey, Weld, Guice, CDI, HK2, JAXB, `jakarta.*` | — | **unchanged** |
   
   `org.eclipse.jetty.toolchain:jetty-servlet-api` becomes the single 
`javax.servlet` provider and
   `javax.servlet:javax.servlet-api` is dropped. Only the toolchain jar ships 
the
   `javax/servlet/catalog.xml` + XSD tree that `jetty-ee8-webapp`'s
   `WebDescriptor.__nonValidatingStaticParser` — a **static** field — resolves 
against; a missing
   catalog entry throws rather than being tolerated, so keeping both jars risks 
a fatal
   class-initialization failure.
   
   Both managed `hadoop-common` entries (jar and test-jar) now exclude 
`javax.servlet:javax.servlet-api`
   and `org.eclipse.jetty:*`. The Jetty exclusion is mandatory independently of 
the EE choice:
   `jetty-servlet` and `jetty-webapp` do not exist at 12.x, so `jetty-bom` 
silently stops managing
   them and Maven would otherwise fall back to Hadoop's 9.4.x.
   
   ### Notable behavioral changes
   
   **Admin servlets.** hadoop-common's `org.apache.hadoop.conf.ConfServlet` and
   `org.apache.hadoop.jmx.JMXJsonServlet` both route their admin-access check 
through
   `org.apache.hadoop.http.HttpServer2`, which references 
`org.eclipse.jetty.servlet.ServletContextHandler`,
   `org.eclipse.jetty.webapp.WebAppContext` and `FilterHolder`/`FilterMapping` 
— all removed or moved
   in Jetty 12. Those classes cannot load at all on a Jetty 12 classpath, so 
`/jmx` and `/conf` would
   answer 500 with a `NoClassDefFoundError`. This is unrelated to the EE 
environment. `/conf` is
   switched to Ozone's existing `HddsConfServlet`, and a new 
`HddsJMXJsonServlet` covers `/jmx`.
   
   **URI compliance.** Jetty 12 rejects ambiguous URIs (empty `//` segments, 
`%25`, encoded path
   separators, suspicious path characters) that 9.4 passed through. S3 object 
keys and WebHDFS paths
   need them. A new opt-in `Builder.allowAmbiguousUri(boolean)` installs an 
`OZONE` `UriCompliance`
   mode allowing exactly those four violations — and, unlike Jetty's `LEGACY` 
mode, **not**
   `%2e%2e` path traversal, UTF-16 `%u` encodings, truncated UTF-8 or userinfo. 
S3 Gateway and
   httpfs opt in; every other endpoint keeps Jetty's strict default.
   
   **XML content type.** EE8's `Response.setContentType` appends `;charset=` 
once `_encodingFrom`
   has moved past `NOT_SET`, and `QuotingInputFilter` promotes it on every 
request, whereas 9.4
   reset it — so a bare `application/xml` would ship as 
`application/xml;charset=utf-8`. A new
   `S3ContentTypeFilter` resets the encoding to `NOT_SET` to preserve the S3 
wire format.
   
   **Reason phrases.** Jetty 12 discards custom HTTP reason phrases at the core 
level, so
   `S3SecretManagementEndpoint` moves its error code into a `text/plain` entity 
body.
   
   **TLS SNI.** Jetty 12 defaults `SecureRequestCustomizer#sniHostCheck` to 
true, which breaks
   Ozone's hostname-agnostic TLS endpoints; it is constructed with `false`.
   
   **Base resources.** Core `ContextHandler.doStart()` now throws for a missing 
base directory,
   where 9.4 tolerated it. The log directory is created best-effort and `/logs` 
is skipped rather
   than failing startup if unavailable; `/static` is served only when its base 
resource exists.
   
   **Weld / CDI.** Weld 3.1.9's `JettyLegacyContainer` detects on 
`org.eclipse.jetty.util.Decorator`,
   which still exists in jetty-util 12, so it is selected — then 
`LegacyWeldDecorator.process()`
   touches the deleted `org.eclipse.jetty.servlet.ServletContextHandler` and 
throws
   `NoClassDefFoundError`. Because that is an `Error`, Weld's `catch 
(Exception)` does not catch it
   and S3 Gateway context startup fails. Fixed with Jetty's canonical 
`jetty-ee8-cdi` module and a
   `CdiDecoratingListener`, which makes Weld's probe match `JettyContainer` 
first.
   
   The listener is installed on each of the three S3 Gateway contexts that 
register the Weld listener
   in their descriptor, guarded by `isEnabled()`: `BaseHttpServer` builds no 
`HttpServer2` at all for a
   disabled server, and `ozone.s3g.sts.http.enabled` is `false` by default, so 
an unguarded call would
   NPE and kill the whole gateway at startup. `BaseHttpServer.isEnabled()` is 
widened from private to
   protected for that check.
   
   **httpfs descriptors.** `<url-pattern>*</url-pattern>` is illegal per the 
Servlet spec and is
   corrected to `/*` (5 filter-mappings in each of the two descriptors).
   
   **hadoop-kms removed from integration-test.** `MiniKMS` embeds an unshaded 
Jetty 9 `Server` and
   cannot coexist with a Jetty 12 runtime. `TestOzoneAtRestEncryption` and 
`TestOzoneShellHA` now
   pre-seed a `JavaKeyStoreProvider` jceks before cluster start instead. The 
native secure-KMS path
   is followed up in HDDS-16424.
   
   ### New dist artifacts
   
   Beyond the expected EE8 set, the `jetty-ee8-cdi` choice pulls in 
`jetty-ee8-annotations`,
   `jetty-ee8-plus`, `jetty-plus`, `jetty-jndi` and — worth calling out 
explicitly —
   **`jakarta.transaction:jakarta.transaction-api`, a new third-party artifact 
in the
   distribution** (1.3.3, whose artifact name is literally "javax.transaction 
API"; EPL-2.0 +
   GPL2-w/-CPE, the same pairing as the `jakarta.annotation-api` already 
shipped).
   
   `jar-report.txt` and `bin/LICENSE.txt` are updated accordingly: 
`javax.servlet-api.jar`,
   `jetty-servlet.jar` and `jetty-webapp.jar` are removed; 
`jetty-servlet-api.jar`, `jetty-ee.jar`,
   `jetty-session.jar`, `jetty-jndi.jar`, `jetty-plus.jar`, 
`jakarta.transaction-api.jar` and the
   seven `jetty-ee8-*.jar` are added. `license.sh` reports no disallowed 
licenses and needs no
   `license.exceptions` entry.
   
   ### Known residuals (pre-existing, out of scope)
   
   - `org.eclipse.jetty.websocket:websocket-{api,client,common}:9.4.57` remain 
at **`test`** scope
     under `ozone-integration-test`. Not on any runtime or dist classpath.
   - `javax.servlet:servlet-api:2.5` reaches `ozone-filesystem-hadoop2` at 
**`provided`** scope via
     `hadoop-common:2.10.2`. This is the old Servlet 2.5 coordinate from the 
Hadoop 2.x
     compatibility module, absent from the distribution.
   
   Generated-by: Claude Code (claude-opus-5)
   
   ## 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/36659484942/job/109713286666
   
   Unit tests:
   
   - `hdds-server-framework`: `TestHttpServer2` (16), `TestHttpServer2SSL` 
(10), `TestBaseHttpServer` (7),
     `TestHttpServer2Metrics`, `TestHtmlQuoting`, 
`TestPrometheusServletAuthorization` — 43 tests, green.
     New coverage: URI-compliance admission at the wire level (including that 
`%2e%2e` and `%u` stay
     rejected under the relaxed mode), the base-resource/log-dir guards, and a
     `testDefaultServletsAnswer` that drives `/jmx`, `/conf`, `/stacks` and 
`/logLevel` over HTTP.
   - `ozone-s3gateway`: `TestS3ContentTypeFilter` (7, new), 
`TestS3GatewayHttpServers` (2, new),
     `TestGateway`, `TestSecretGenerate`, `TestSecretRevoke` — 17 tests, green. 
The new class asserts
     that an enabled context carries Jetty's `org.eclipse.jetty.cdi` attribute 
and that a disabled STS
     server is constructed without one.
   
   Integration tests:
   
   - `TestOzoneManagerHttpServer`, `TestEDEKCacheLoader` (new) — green.
   - `TestCpuMetrics`, `TestOzoneManagerRestInterface` — green.
   - `ProxyServerIntegrationTest` — green.
   - `TestS3SDK` (AWS SDK v1 + v2 against a live S3 Gateway) — 210 tests, green.
   - `TestS3GatewayHealthCheck` — 3 tests, green; starts a real `Gateway`, so 
it covers the CDI
     install path end to end in-process.
   - `TestOzoneAtRestEncryption` — 36 tests green.
   - `TestOzoneShellHA` — green.
   
   Build and checks: full reactor build and a wider `-Pdist` build (all 58 
modules, shade + Recon +
   docs enabled) with `dependency:analyze-only` **enabled** — no "Used 
undeclared", "Unused declared"
   or "Non-test scoped" findings. `checkstyle.sh` clean, `rat.sh` clean, no 
`@author` tags.
   `dependency.sh`'s jar-report comparison is empty against a clean `-Pdist` 
build.
   
   Classpath assertions over the reactor: every `org.eclipse.jetty*` coordinate 
resolves to `12.0.38`
   (`4.0.9` for `jetty-servlet-api`); no `ee9`/`ee10`; 
`org.eclipse.jetty:jetty-servlet`,
   `jetty-webapp` and `jetty-proxy` resolve to nothing.
   
   Compose robot smoketests, against a dist built from this branch: `ozone` 
(369 assertions, 18
   suites) and `ozonesecure` (450 assertions) both pass with zero failures, 
covering Recon, httpfs, the
   S3 and secret suites and secure-mode SPNEGO.
   
   `ozone-om-ha` ships `disabled-test.sh` upstream, so `ozone-ha` is run in its 
place: 461 assertions
   pass, 15 fail. All 15 trace to a single datanode container dying mid-run in 
this local 13-container
   environment, not to the upgrade — each failure is an 
`AnnotatedNoRouteToHostException` against that
   datanode's address, its container log stops abruptly four minutes before the 
first failure with no
   shutdown sequence or exception, and `ozone-ha` never stops a datanode 
itself. The two multipart-upload
   tests among them had already passed twice earlier in the same run under the 
`OBJECT_STORE` and
   `LEGACY` layouts. Re-running the affected `FILE_SYSTEM_OPTIMIZED` s3 block 
against a fresh cluster
   passes 149/149, including all 13 `Buckettagging` tests and both 
multipart-upload tests.
   
   The admin endpoints were also swept directly against a running cluster. 
`/conf`, `/jmx`, `/prom`,
   `/logLevel`, `/stacks` and `/logs/` answer 200 on OM, SCM, Recon and the S3 
Gateway web admin
   server, and on httpfs with `?user.name=`. `/static/` answers 403 because 
directory listing stays
   disabled, while a real asset under it (`/static/ozone.css`) answers 200. The 
S3 Gateway returns
   `Content-Type: application/xml` with no appended charset, confirming 
`S3ContentTypeFilter` at the
   wire level.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to