This is an automated email from the ASF dual-hosted git repository.

sarutak pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/spark.git


The following commit(s) were added to refs/heads/master by this push:
     new 94662eb63391 [SPARK-47086][SPARK-48022][BUILD][CORE][WEBUI] Upgrade 
Jetty to 12.1.5, Jersey to 3.1.11 and Servlet to 6.0
94662eb63391 is described below

commit 94662eb6339151b7fa3bb5a1b9942db059ee6a4b
Author: Kousuke Saruta <[email protected]>
AuthorDate: Fri Jan 9 18:39:33 2026 +0900

    [SPARK-47086][SPARK-48022][BUILD][CORE][WEBUI] Upgrade Jetty to 12.1.5, 
Jersey to 3.1.11 and Servlet to 6.0
    
    ### What changes were proposed in this pull request?
    This PR proposes to upgrade Jetty to 12.1.5, Jersey to 3.1.11 and Servlet 
to 6.0 which need to be upgraded together.
    Because Jetty 12 is [significantly changed from 
11.x,](https://jetty.org/docs/jetty/12.1/programming-guide/migration/11-to-12.html)
 this PR mainly considers following things to upgrade.
    
    * Redirect handler for http to https is rewritten using the standard 
Servlet API because most of the code can be reusable with `Filter` while it's 
difficult to do it with Jetty specific `Core API`.
    * `ProxyRedirectHandler` is rewritten using new `Core API` because 
`HandlerWrapper` is no longer available. It's difficult to implement 
`ProxyRedirectHandler` with the standard Servlet API so `Core API` is used.
    * In several places, the expected status code is changed from 302 to 301 to 
adapt Jetty's change.
      * 
https://github.com/jetty/jetty.project/blob/4905d09d7b6801e792d7b73946cf7b66e4be25d6/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java#L1205
    * In several places, consider the case where the value of location header 
is relative form to adapt Jetty's change.
      * 
https://github.com/jetty/jetty.project/blob/4905d09d7b6801e792d7b73946cf7b66e4be25d6/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java#L415
      * 
https://github.com/jetty/jetty.project/blob/4905d09d7b6801e792d7b73946cf7b66e4be25d6/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java#L1260
    
    ### Why are the changes needed?
    Jetty 11 is already EOF and starting Jan 1, 2026, no more release will be 
published.
    https://github.com/jetty/jetty.project/issues/13918
    
    ### Does this PR introduce _any_ user-facing change?
    No.
    
    ### How was this patch tested?
    Existing tests with some tweaks.
    
    ### Was this patch authored or co-authored using generative AI tooling?
    No.
    
    Closes #53116 from sarutak/upgrade-jetty.
    
    Authored-by: Kousuke Saruta <[email protected]>
    Signed-off-by: Kousuke Saruta <[email protected]>
---
 connector/kafka-0-10-sql/pom.xml                   |   4 +-
 core/pom.xml                                       |  18 +--
 .../main/scala/org/apache/spark/TestUtils.scala    |  14 +-
 .../spark/deploy/history/ApplicationCache.scala    |   2 +-
 .../spark/deploy/history/HistoryServer.scala       |   2 +-
 .../spark/deploy/rest/RestSubmissionServer.scala   |   2 +-
 .../org/apache/spark/metrics/MetricsSystem.scala   |   2 +-
 .../apache/spark/metrics/sink/MetricsServlet.scala |   2 +-
 .../spark/metrics/sink/PrometheusServlet.scala     |   2 +-
 .../spark/status/api/v1/ApiRootResource.scala      |   2 +-
 .../spark/status/api/v1/PrometheusResource.scala   |   2 +-
 .../scala/org/apache/spark/ui/JettyUtils.scala     | 179 +++++++++++----------
 .../main/scala/org/apache/spark/ui/SparkUI.scala   |   2 +-
 .../main/scala/org/apache/spark/ui/UIUtils.scala   |  13 +-
 .../src/main/scala/org/apache/spark/ui/WebUI.scala |   2 +-
 .../main/scala/org/apache/spark/util/Utils.scala   |   3 -
 .../deploy/history/ApplicationCacheSuite.scala     |   2 +-
 .../spark/deploy/history/HistoryServerSuite.scala  |  35 ++--
 .../history/RealBrowserUIHistoryServerSuite.scala  |   4 +-
 .../test/scala/org/apache/spark/ui/UISuite.scala   |  18 ++-
 dev/deps/spark-deps-hadoop-3-hive-2.3              |  20 +--
 pom.xml                                            |  26 +--
 project/MimaExcludes.scala                         |   6 +-
 repl/pom.xml                                       |   4 +-
 resource-managers/yarn/pom.xml                     |  12 +-
 .../apache/spark/deploy/yarn/AmIpFilterSuite.scala |   8 +-
 sql/core/pom.xml                                   |   4 +-
 sql/hive-thriftserver/pom.xml                      |   4 +-
 .../service/cli/thrift/ThriftHttpCLIService.java   |   4 +-
 streaming/pom.xml                                  |  12 +-
 30 files changed, 219 insertions(+), 191 deletions(-)

diff --git a/connector/kafka-0-10-sql/pom.xml b/connector/kafka-0-10-sql/pom.xml
index fd0ca36d36df..e1a8cd63272a 100644
--- a/connector/kafka-0-10-sql/pom.xml
+++ b/connector/kafka-0-10-sql/pom.xml
@@ -136,8 +136,8 @@
       <scope>test</scope>
     </dependency>
      <dependency>
-        <groupId>org.eclipse.jetty</groupId>
-        <artifactId>jetty-servlet</artifactId>
+        <groupId>org.eclipse.jetty.ee10</groupId>
+        <artifactId>jetty-ee10-servlet</artifactId>
         <version>${jetty.version}</version>
         <scope>test</scope>
       </dependency>
diff --git a/core/pom.xml b/core/pom.xml
index 21d21a9aab4b..f322e6d7c718 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -138,8 +138,8 @@
     <!-- Jetty dependencies promoted to compile here so they are shaded
          and inlined into spark-core jar -->
     <dependency>
-      <groupId>org.eclipse.jetty</groupId>
-      <artifactId>jetty-plus</artifactId>
+      <groupId>org.eclipse.jetty.ee10</groupId>
+      <artifactId>jetty-ee10-plus</artifactId>
       <scope>compile</scope>
     </dependency>
     <dependency>
@@ -163,13 +163,13 @@
       <scope>compile</scope>
     </dependency>
     <dependency>
-      <groupId>org.eclipse.jetty</groupId>
-      <artifactId>jetty-servlet</artifactId>
+      <groupId>org.eclipse.jetty.ee10</groupId>
+      <artifactId>jetty-ee10-servlet</artifactId>
       <scope>compile</scope>
     </dependency>
     <dependency>
-      <groupId>org.eclipse.jetty</groupId>
-      <artifactId>jetty-proxy</artifactId>
+      <groupId>org.eclipse.jetty.ee10</groupId>
+      <artifactId>jetty-ee10-proxy</artifactId>
       <scope>compile</scope>
     </dependency>
     <dependency>
@@ -178,8 +178,8 @@
       <scope>compile</scope>
     </dependency>
     <dependency>
-      <groupId>org.eclipse.jetty</groupId>
-      <artifactId>jetty-servlets</artifactId>
+      <groupId>org.eclipse.jetty.ee10</groupId>
+      <artifactId>jetty-ee10-servlets</artifactId>
       <scope>compile</scope>
     </dependency>
     <dependency>
@@ -541,7 +541,7 @@
               <overWriteIfNewer>true</overWriteIfNewer>
               <useSubDirectoryPerType>true</useSubDirectoryPerType>
               <includeArtifactIds>
-                
guava,protobuf-java,jetty-io,jetty-servlet,jetty-servlets,jetty-http,jetty-plus,jetty-util,jetty-server,jetty-security,jetty-proxy,jetty-client
+                
guava,protobuf-java,jetty-io,jetty-ee10-servlet,jetty-ee10-servlets,jetty-http,jetty-ee10-plus,jetty-util,jetty-server,jetty-security,jetty-proxy,jetty-client
               </includeArtifactIds>
               <silent>true</silent>
             </configuration>
diff --git a/core/src/main/scala/org/apache/spark/TestUtils.scala 
b/core/src/main/scala/org/apache/spark/TestUtils.scala
index aadfb2125cd6..1bfc6c3d0fad 100644
--- a/core/src/main/scala/org/apache/spark/TestUtils.scala
+++ b/core/src/main/scala/org/apache/spark/TestUtils.scala
@@ -41,11 +41,8 @@ import org.apache.logging.log4j.LogManager
 import org.apache.logging.log4j.core.LoggerContext
 import org.apache.logging.log4j.core.appender.ConsoleAppender
 import 
org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory
-import org.eclipse.jetty.server.Handler
 import org.eclipse.jetty.server.Server
-import org.eclipse.jetty.server.handler.DefaultHandler
-import org.eclipse.jetty.server.handler.HandlerList
-import org.eclipse.jetty.server.handler.ResourceHandler
+import org.eclipse.jetty.server.handler.{ContextHandler, 
ContextHandlerCollection, DefaultHandler, ResourceHandler}
 import org.json4s.JsonAST.JValue
 import org.json4s.jackson.JsonMethods.{compact, render}
 
@@ -333,9 +330,12 @@ private[spark] object TestUtils extends SparkTestUtils {
     // 0 as port means choosing randomly from the available ports
     val server = new Server(new 
InetSocketAddress(Utils.localCanonicalHostName(), 0))
     val resHandler = new ResourceHandler()
-    resHandler.setResourceBase(resBaseDir)
-    val handlers = new HandlerList()
-    handlers.setHandlers(Array[Handler](resHandler, new DefaultHandler()))
+    resHandler.setBaseResourceAsString(resBaseDir)
+    val resCxt = new ContextHandler
+    resCxt.setContextPath("/")
+    resCxt.setHandler(resHandler)
+    val handlers = new ContextHandlerCollection()
+    handlers.setHandlers(resCxt, new DefaultHandler())
     server.setHandler(handlers)
     server.start()
     try {
diff --git 
a/core/src/main/scala/org/apache/spark/deploy/history/ApplicationCache.scala 
b/core/src/main/scala/org/apache/spark/deploy/history/ApplicationCache.scala
index e979671890ea..c2fe0acec2e9 100644
--- a/core/src/main/scala/org/apache/spark/deploy/history/ApplicationCache.scala
+++ b/core/src/main/scala/org/apache/spark/deploy/history/ApplicationCache.scala
@@ -26,7 +26,7 @@ import com.google.common.cache.{CacheBuilder, CacheLoader, 
LoadingCache, Removal
 import com.google.common.util.concurrent.UncheckedExecutionException
 import jakarta.servlet.{DispatcherType, Filter, FilterChain, ServletException, 
ServletRequest, ServletResponse}
 import jakarta.servlet.http.{HttpServletRequest, HttpServletResponse}
-import org.eclipse.jetty.servlet.FilterHolder
+import org.eclipse.jetty.ee10.servlet.FilterHolder
 
 import org.apache.spark.internal.Logging
 import org.apache.spark.internal.LogKeys._
diff --git 
a/core/src/main/scala/org/apache/spark/deploy/history/HistoryServer.scala 
b/core/src/main/scala/org/apache/spark/deploy/history/HistoryServer.scala
index 14daa5d88b1c..a4e047f7683a 100644
--- a/core/src/main/scala/org/apache/spark/deploy/history/HistoryServer.scala
+++ b/core/src/main/scala/org/apache/spark/deploy/history/HistoryServer.scala
@@ -23,7 +23,7 @@ import scala.util.control.NonFatal
 import scala.xml.Node
 
 import jakarta.servlet.http.{HttpServlet, HttpServletRequest, 
HttpServletResponse}
-import org.eclipse.jetty.servlet.{ServletContextHandler, ServletHolder}
+import org.eclipse.jetty.ee10.servlet.{ServletContextHandler, ServletHolder}
 
 import org.apache.spark.{SecurityManager, SparkConf}
 import org.apache.spark.deploy.SparkHadoopUtil
diff --git 
a/core/src/main/scala/org/apache/spark/deploy/rest/RestSubmissionServer.scala 
b/core/src/main/scala/org/apache/spark/deploy/rest/RestSubmissionServer.scala
index e172a06f0a32..ee404ac11a96 100644
--- 
a/core/src/main/scala/org/apache/spark/deploy/rest/RestSubmissionServer.scala
+++ 
b/core/src/main/scala/org/apache/spark/deploy/rest/RestSubmissionServer.scala
@@ -25,8 +25,8 @@ import scala.io.Source
 import com.fasterxml.jackson.core.JsonProcessingException
 import jakarta.servlet.DispatcherType
 import jakarta.servlet.http.{HttpServlet, HttpServletRequest, 
HttpServletResponse}
+import org.eclipse.jetty.ee10.servlet.{FilterHolder, ServletContextHandler, 
ServletHolder}
 import org.eclipse.jetty.server.{HttpConfiguration, HttpConnectionFactory, 
Server, ServerConnector}
-import org.eclipse.jetty.servlet.{FilterHolder, ServletContextHandler, 
ServletHolder}
 import org.eclipse.jetty.util.thread.{QueuedThreadPool, 
ScheduledExecutorScheduler}
 import org.json4s._
 import org.json4s.jackson.JsonMethods._
diff --git a/core/src/main/scala/org/apache/spark/metrics/MetricsSystem.scala 
b/core/src/main/scala/org/apache/spark/metrics/MetricsSystem.scala
index af1f54007248..25736475be31 100644
--- a/core/src/main/scala/org/apache/spark/metrics/MetricsSystem.scala
+++ b/core/src/main/scala/org/apache/spark/metrics/MetricsSystem.scala
@@ -23,7 +23,7 @@ import java.util.concurrent.TimeUnit
 import scala.collection.mutable
 
 import com.codahale.metrics.{Metric, MetricRegistry}
-import org.eclipse.jetty.servlet.ServletContextHandler
+import org.eclipse.jetty.ee10.servlet.ServletContextHandler
 
 import org.apache.spark.{SecurityManager, SparkConf}
 import org.apache.spark.internal.Logging
diff --git 
a/core/src/main/scala/org/apache/spark/metrics/sink/MetricsServlet.scala 
b/core/src/main/scala/org/apache/spark/metrics/sink/MetricsServlet.scala
index 7d676cd2c27b..305b391cc5fc 100644
--- a/core/src/main/scala/org/apache/spark/metrics/sink/MetricsServlet.scala
+++ b/core/src/main/scala/org/apache/spark/metrics/sink/MetricsServlet.scala
@@ -24,7 +24,7 @@ import com.codahale.metrics.MetricRegistry
 import com.codahale.metrics.json.MetricsModule
 import com.fasterxml.jackson.databind.ObjectMapper
 import jakarta.servlet.http.HttpServletRequest
-import org.eclipse.jetty.servlet.ServletContextHandler
+import org.eclipse.jetty.ee10.servlet.ServletContextHandler
 
 import org.apache.spark.SparkConf
 import org.apache.spark.ui.JettyUtils._
diff --git 
a/core/src/main/scala/org/apache/spark/metrics/sink/PrometheusServlet.scala 
b/core/src/main/scala/org/apache/spark/metrics/sink/PrometheusServlet.scala
index 2ab49eae8cd8..8252f235e582 100644
--- a/core/src/main/scala/org/apache/spark/metrics/sink/PrometheusServlet.scala
+++ b/core/src/main/scala/org/apache/spark/metrics/sink/PrometheusServlet.scala
@@ -21,7 +21,7 @@ import java.util.Properties
 
 import com.codahale.metrics.MetricRegistry
 import jakarta.servlet.http.HttpServletRequest
-import org.eclipse.jetty.servlet.ServletContextHandler
+import org.eclipse.jetty.ee10.servlet.ServletContextHandler
 
 import org.apache.spark.SparkConf
 import org.apache.spark.annotation.{DeveloperApi, Since, Unstable}
diff --git 
a/core/src/main/scala/org/apache/spark/status/api/v1/ApiRootResource.scala 
b/core/src/main/scala/org/apache/spark/status/api/v1/ApiRootResource.scala
index 61e800844db0..c8717c97140d 100644
--- a/core/src/main/scala/org/apache/spark/status/api/v1/ApiRootResource.scala
+++ b/core/src/main/scala/org/apache/spark/status/api/v1/ApiRootResource.scala
@@ -22,8 +22,8 @@ import jakarta.servlet.ServletContext
 import jakarta.servlet.http.HttpServletRequest
 import jakarta.ws.rs._
 import jakarta.ws.rs.core.{Context, Response}
+import org.eclipse.jetty.ee10.servlet.{ServletContextHandler, ServletHolder}
 import org.eclipse.jetty.server.handler.ContextHandler
-import org.eclipse.jetty.servlet.{ServletContextHandler, ServletHolder}
 import org.glassfish.jersey.server.ServerProperties
 import org.glassfish.jersey.servlet.ServletContainer
 
diff --git 
a/core/src/main/scala/org/apache/spark/status/api/v1/PrometheusResource.scala 
b/core/src/main/scala/org/apache/spark/status/api/v1/PrometheusResource.scala
index 6efe3106ba56..ea30d59832b6 100644
--- 
a/core/src/main/scala/org/apache/spark/status/api/v1/PrometheusResource.scala
+++ 
b/core/src/main/scala/org/apache/spark/status/api/v1/PrometheusResource.scala
@@ -18,7 +18,7 @@ package org.apache.spark.status.api.v1
 
 import jakarta.ws.rs._
 import jakarta.ws.rs.core.MediaType
-import org.eclipse.jetty.servlet.{ServletContextHandler, ServletHolder}
+import org.eclipse.jetty.ee10.servlet.{ServletContextHandler, ServletHolder}
 import org.glassfish.jersey.server.ServerProperties
 import org.glassfish.jersey.servlet.ServletContainer
 
diff --git a/core/src/main/scala/org/apache/spark/ui/JettyUtils.scala 
b/core/src/main/scala/org/apache/spark/ui/JettyUtils.scala
index fedc6bb27309..78fe74b454f7 100644
--- a/core/src/main/scala/org/apache/spark/ui/JettyUtils.scala
+++ b/core/src/main/scala/org/apache/spark/ui/JettyUtils.scala
@@ -18,22 +18,25 @@
 package org.apache.spark.ui
 
 import java.net.{URI, URL, URLDecoder}
-import java.util.EnumSet
+import java.util.{EnumSet, List => JList}
 
+import scala.jdk.CollectionConverters._
 import scala.language.implicitConversions
 import scala.util.Try
 import scala.xml.Node
 
-import jakarta.servlet.DispatcherType
+import jakarta.servlet.{DispatcherType, Filter, FilterChain, ServletRequest, 
ServletResponse}
 import jakarta.servlet.http._
+import org.eclipse.jetty.client.{Response => CResponse}
 import org.eclipse.jetty.client.HttpClient
-import org.eclipse.jetty.client.api.Response
-import org.eclipse.jetty.client.http.HttpClientTransportOverHTTP
-import org.eclipse.jetty.proxy.ProxyServlet
+import org.eclipse.jetty.client.transport.HttpClientTransportOverHTTP
+import org.eclipse.jetty.ee10.proxy.ProxyServlet
+import org.eclipse.jetty.ee10.servlet._
+import org.eclipse.jetty.http.{HttpField, HttpFields, HttpHeader}
 import org.eclipse.jetty.server._
-import org.eclipse.jetty.server.handler._
+import org.eclipse.jetty.server.handler.{ContextHandler, 
ContextHandlerCollection, ErrorHandler}
 import org.eclipse.jetty.server.handler.gzip.GzipHandler
-import org.eclipse.jetty.servlet._
+import org.eclipse.jetty.util.{Callback, URIUtil}
 import org.eclipse.jetty.util.component.LifeCycle
 import org.eclipse.jetty.util.thread.{QueuedThreadPool, 
ScheduledExecutorScheduler}
 import org.json4s.JValue
@@ -172,7 +175,7 @@ private[spark] object JettyUtils extends Logging {
     val holder = new ServletHolder(staticHandler)
     Option(Utils.getSparkClassLoader.getResource(resourceBase)) match {
       case Some(res) =>
-        holder.setInitParameter("resourceBase", res.toString)
+        holder.setInitParameter("baseResource", res.toString)
       case None =>
         throw new Exception("Could not find resource path for Web UI: " + 
resourceBase)
     }
@@ -215,7 +218,7 @@ private[spark] object JettyUtils extends Logging {
 
       override def filterServerResponseHeader(
           clientRequest: HttpServletRequest,
-          serverResponse: Response,
+          serverResponse: CResponse,
           headerName: String,
           headerValue: String): String = {
         if (headerName.equalsIgnoreCase("location")) {
@@ -266,8 +269,7 @@ private[spark] object JettyUtils extends Logging {
 
     val errorHandler = new ErrorHandler()
     errorHandler.setShowStacks(conf.get(UI_SHOW_ERROR_STACKS))
-    errorHandler.setServer(server)
-    server.addBean(errorHandler)
+    server.setErrorHandler(errorHandler)
 
     val collection = new ContextHandlerCollection
     conf.get(PROXY_REDIRECT_URI) match {
@@ -392,24 +394,11 @@ private[spark] object JettyUtils extends Logging {
   }
 
   private def createRedirectHttpsHandler(securePort: Int, scheme: String): 
ContextHandler = {
-    val redirectHandler: ContextHandler = new ContextHandler
+    val redirectHandler = new ServletContextHandler
     redirectHandler.setContextPath("/")
     redirectHandler.setVirtualHosts(toVirtualHosts(REDIRECT_CONNECTOR_NAME))
-    redirectHandler.setHandler(new AbstractHandler {
-      override def handle(
-          target: String,
-          baseRequest: Request,
-          request: HttpServletRequest,
-          response: HttpServletResponse): Unit = {
-        if (baseRequest.isSecure) {
-          return
-        }
-        val httpsURI = createRedirectURI(scheme, securePort, baseRequest)
-        response.setContentLength(0)
-        response.sendRedirect(response.encodeRedirectURL(httpsURI))
-        baseRequest.setHandled(true)
-      }
-    })
+    redirectHandler.addFilter(
+      new FilterHolder(new HttpsRedirectFilter(scheme, securePort)), "/*", 
null)
     redirectHandler
   }
 
@@ -441,14 +430,20 @@ private[spark] object JettyUtils extends Logging {
       headerValue: String,
       clientRequest: HttpServletRequest,
       targetUri: URI): String = {
-    val toReplace = targetUri.getScheme() + "://" + targetUri.getAuthority()
-    if (headerValue.startsWith(toReplace)) {
-      val id = 
clientRequest.getPathInfo.substring("/proxy/".length).takeWhile(_ != '/')
-      val headerPath = headerValue.substring(toReplace.length)
-
-      
s"${clientRequest.getScheme}://${clientRequest.getHeader("host")}/proxy/$id$headerPath"
+    // As of Jetty 12, the value returned from getPathInfo doesn't contain the 
servlet context
+    // root, which complies with the Servlet specification.
+    val id = clientRequest.getPathInfo.substring(1).takeWhile(_ != '/')
+    val urlToId = 
s"${clientRequest.getScheme}://${clientRequest.getHeader("host")}/proxy/$id"
+    if (new URI(headerValue).getScheme != null) {
+      val toReplace = targetUri.getScheme() + "://" + targetUri.getAuthority()
+      if (headerValue.startsWith(toReplace)) {
+        val headerPath = headerValue.substring(toReplace.length)
+        urlToId + headerPath
+      } else {
+        null
+      }
     } else {
-      null
+      urlToId + headerValue
     }
   }
 
@@ -462,37 +457,8 @@ private[spark] object JettyUtils extends Logging {
     handler.addFilter(holder, "/*", EnumSet.allOf(classOf[DispatcherType]))
   }
 
-  private def decodeURL(url: String, encoding: String): String = {
-    if (url == null) {
-      null
-    } else {
-      URLDecoder.decode(url, encoding)
-    }
-  }
-
-  // Create a new URI from the arguments, handling IPv6 host encoding and 
default ports.
-  private def createRedirectURI(scheme: String, port: Int, request: Request): 
String = {
-    val server = request.getServerName
-    val redirectServer = if (server.contains(":") && !server.startsWith("[")) {
-      s"[${server}]"
-    } else {
-      server
-    }
-    val authority = s"$redirectServer:$port"
-    val queryEncoding = if (request.getQueryEncoding != null) {
-      request.getQueryEncoding
-    } else {
-      // By default decoding the URI as "UTF-8" should be enough for SparkUI
-      "UTF-8"
-    }
-    // The request URL can be raw or encoded here. To avoid the request URL 
being
-    // encoded twice, let's decode it here.
-    val requestURI = decodeURL(request.getRequestURI, queryEncoding)
-    val queryString = decodeURL(request.getQueryString, queryEncoding)
-    new URI(scheme, authority, requestURI, queryString, null).toString
-  }
-
-  def toVirtualHosts(connectors: String*): Array[String] = connectors.map("@" 
+ _).toArray
+  def toVirtualHosts(connectors: String*): JList[String] =
+    JList.of(connectors.map("@" + _).toArray: _*)
 
 }
 
@@ -522,7 +488,7 @@ private[spark] case class ServerInfo(
   def removeHandler(handler: ServletContextHandler): Unit = synchronized {
     // Since addHandler() always adds a wrapping gzip handler, find the 
container handler
     // and remove it.
-    rootHandler.getHandlers()
+    rootHandler.getHandlers.asScala
       .find { h =>
         h.isInstanceOf[GzipHandler] && 
h.asInstanceOf[GzipHandler].getHandler() == handler
       }
@@ -597,36 +563,85 @@ private[spark] case class ServerInfo(
  * a servlet context without the trailing slash (e.g. "/jobs") - Jetty will 
send a redirect to the
  * same URL, but with a trailing slash.
  */
-private class ProxyRedirectHandler(_proxyUri: String) extends HandlerWrapper {
+private class ProxyRedirectHandler(_proxyUri: String) extends Handler.Wrapper {
 
   private val proxyUri = _proxyUri.stripSuffix("/")
 
-  override def handle(
-      target: String,
-      baseRequest: Request,
-      request: HttpServletRequest,
-      response: HttpServletResponse): Unit = {
-    super.handle(target, baseRequest, request, new ResponseWrapper(request, 
response))
+  override def handle(request: Request, response: Response, callback: 
Callback): Boolean = {
+    super.handle(request, new ResponseWrapper(request, response), callback)
   }
 
-  private class ResponseWrapper(
-      req: HttpServletRequest,
-      res: HttpServletResponse)
-    extends HttpServletResponseWrapper(res) {
+  private class ResponseWrapper(req: Request, res: Response) extends 
Response.Wrapper(req, res) {
+    override def getHeaders(): HttpFields.Mutable = {
+      new MutableFieldsWrapper(req, super.getHeaders())
+    }
+  }
 
-    override def sendRedirect(location: String): Unit = {
-      val newTarget = if (location != null) {
+  private class MutableFieldsWrapper(
+      req: Request,
+      wrapped: HttpFields.Mutable) extends HttpFields.Mutable.Wrapper(wrapped) 
{
+    override def onAddField(field: HttpField): HttpField = {
+      if (field.is(HttpHeader.LOCATION.asString())) {
+        val location = field.getValue
+        // null check should be done by Jetty before adding Location header.
+        assert(location != null)
         val target = new URI(location)
         // The target path should already be encoded, so don't re-encode it, 
just the
         // proxy address part.
         val proxyBase = UIUtils.uiRoot(req)
         val proxyPrefix = if (proxyBase.nonEmpty) s"$proxyUri$proxyBase" else 
proxyUri
-        s"${res.encodeURL(proxyPrefix)}${target.getPath()}"
+        val newTarget = URIUtil.encodePath(proxyPrefix) + target.getPath()
+        new HttpField(field.getName(), newTarget)
       } else {
-        null
+        field
       }
-      super.sendRedirect(newTarget)
     }
   }
+}
+
+private class HttpsRedirectFilter(scheme: String, securePort: Int) extends 
Filter {
+
+  override def doFilter(
+      request: ServletRequest,
+      response: ServletResponse,
+      chain: FilterChain): Unit = {
+    if (request.isSecure) {
+      return
+    }
+    val httpRequest = request.asInstanceOf[HttpServletRequest]
+    val httpResponse = response.asInstanceOf[HttpServletResponse]
+    val httpsURI = createRedirectURI(scheme, securePort, httpRequest)
+    httpResponse.setContentLength(0)
+    httpResponse.sendRedirect(httpResponse.encodeRedirectURL(httpsURI))
+  }
 
+  // Create a new URI from the arguments, handling IPv6 host encoding and 
default ports.
+  private def createRedirectURI(scheme: String, port: Int, request: 
HttpServletRequest): String = {
+    val server = request.getServerName
+    val redirectServer = if (server.contains(":") && !server.startsWith("[")) {
+      s"[$server]"
+    } else {
+      server
+    }
+    val authority = s"$redirectServer:$port"
+    val characterEncoding = if (request.getCharacterEncoding != null) {
+      request.getCharacterEncoding
+    } else {
+      // By default decoding the URI as "UTF-8" should be enough for SparkUI
+      "UTF-8"
+    }
+    // The request URL can be raw or encoded here. To avoid the request URL 
being
+    // encoded twice, let's decode it here.
+    val requestURI = decodeURL(request.getRequestURI, characterEncoding)
+    val queryString = decodeURL(request.getQueryString, characterEncoding)
+    new URI(scheme, authority, requestURI, queryString, null).toString
+  }
+
+  private def decodeURL(url: String, encoding: String): String = {
+    if (url == null) {
+      null
+    } else {
+      URLDecoder.decode(url, encoding)
+    }
+  }
 }
diff --git a/core/src/main/scala/org/apache/spark/ui/SparkUI.scala 
b/core/src/main/scala/org/apache/spark/ui/SparkUI.scala
index a23764f98d49..ca406b382020 100644
--- a/core/src/main/scala/org/apache/spark/ui/SparkUI.scala
+++ b/core/src/main/scala/org/apache/spark/ui/SparkUI.scala
@@ -20,7 +20,7 @@ package org.apache.spark.ui
 import java.util.Date
 
 import jakarta.servlet.http.{HttpServlet, HttpServletRequest, 
HttpServletResponse}
-import org.eclipse.jetty.servlet.ServletContextHandler
+import org.eclipse.jetty.ee10.servlet.ServletContextHandler
 
 import org.apache.spark.{SecurityManager, SparkConf, SparkContext}
 import org.apache.spark.internal.Logging
diff --git a/core/src/main/scala/org/apache/spark/ui/UIUtils.scala 
b/core/src/main/scala/org/apache/spark/ui/UIUtils.scala
index 482b7cb0e74c..35b00daefdb5 100644
--- a/core/src/main/scala/org/apache/spark/ui/UIUtils.scala
+++ b/core/src/main/scala/org/apache/spark/ui/UIUtils.scala
@@ -32,6 +32,7 @@ import scala.xml.transform.{RewriteRule, RuleTransformer}
 
 import jakarta.servlet.http.HttpServletRequest
 import jakarta.ws.rs.core.{MediaType, MultivaluedMap, Response}
+import org.eclipse.jetty.server.Request
 import org.glassfish.jersey.internal.util.collection.MultivaluedStringMap
 
 import org.apache.spark.internal.Logging
@@ -186,9 +187,9 @@ private[spark] object UIUtils extends Logging {
   }
 
   // Yarn has to go through a proxy so the base uri is provided and has to be 
on all links
-  def uiRoot(request: HttpServletRequest): String = {
+  def uiRoot(knoxBasePathGetter: String => String): String = {
     // Knox uses X-Forwarded-Context to notify the application the base path
-    val knoxBasePath = Option(request.getHeader("X-Forwarded-Context"))
+    val knoxBasePath = Option(knoxBasePathGetter("X-Forwarded-Context"))
     // SPARK-11484 - Use the proxyBase set by the AM, if not found then use 
env.
     sys.props.get("spark.ui.proxyBase")
       .orElse(sys.env.get("APPLICATION_WEB_PROXY_BASE"))
@@ -196,6 +197,14 @@ private[spark] object UIUtils extends Logging {
       .getOrElse("")
   }
 
+  def uiRoot(request: HttpServletRequest): String = {
+    uiRoot(request.getHeader _)
+  }
+
+  def uiRoot(request: Request): String = {
+    uiRoot(request.getHeaders.get: String => String)
+  }
+
   def prependBaseUri(
       request: HttpServletRequest,
       basePath: String = "",
diff --git a/core/src/main/scala/org/apache/spark/ui/WebUI.scala 
b/core/src/main/scala/org/apache/spark/ui/WebUI.scala
index c0d0fb50ae36..7f8f2556dd08 100644
--- a/core/src/main/scala/org/apache/spark/ui/WebUI.scala
+++ b/core/src/main/scala/org/apache/spark/ui/WebUI.scala
@@ -25,7 +25,7 @@ import scala.xml.Node
 
 import jakarta.servlet.DispatcherType
 import jakarta.servlet.http.{HttpServlet, HttpServletRequest}
-import org.eclipse.jetty.servlet.{FilterHolder, FilterMapping, 
ServletContextHandler, ServletHolder}
+import org.eclipse.jetty.ee10.servlet.{FilterHolder, FilterMapping, 
ServletContextHandler, ServletHolder}
 import org.json4s.JsonAST.{JNothing, JValue}
 
 import org.apache.spark.{SecurityManager, SparkConf, SSLOptions}
diff --git a/core/src/main/scala/org/apache/spark/util/Utils.scala 
b/core/src/main/scala/org/apache/spark/util/Utils.scala
index 5ee4948bdaa2..1f82f9af1a9b 100644
--- a/core/src/main/scala/org/apache/spark/util/Utils.scala
+++ b/core/src/main/scala/org/apache/spark/util/Utils.scala
@@ -60,7 +60,6 @@ import org.apache.hadoop.yarn.conf.YarnConfiguration
 import org.apache.logging.log4j.{Level, LogManager}
 import org.apache.logging.log4j.core.LoggerContext
 import org.apache.logging.log4j.core.config.LoggerConfig
-import org.eclipse.jetty.util.MultiException
 import org.slf4j.Logger
 
 import org.apache.spark.{SPARK_VERSION, _}
@@ -2318,8 +2317,6 @@ private[spark] object Utils
           return true
         }
         isBindCollision(e.getCause)
-      case e: MultiException =>
-        e.getThrowables.asScala.exists(isBindCollision)
       case e: NativeIoException =>
         (e.getMessage != null && e.getMessage.matches("bind.*failed.*")) ||
           isBindCollision(e.getCause)
diff --git 
a/core/src/test/scala/org/apache/spark/deploy/history/ApplicationCacheSuite.scala
 
b/core/src/test/scala/org/apache/spark/deploy/history/ApplicationCacheSuite.scala
index d27c07c36c0d..f5968e383b05 100644
--- 
a/core/src/test/scala/org/apache/spark/deploy/history/ApplicationCacheSuite.scala
+++ 
b/core/src/test/scala/org/apache/spark/deploy/history/ApplicationCacheSuite.scala
@@ -25,7 +25,7 @@ import scala.collection.mutable
 import com.codahale.metrics.Counter
 import jakarta.servlet.http.{HttpServletRequest, HttpServletResponse}
 import org.apache.hadoop.conf.Configuration
-import org.eclipse.jetty.servlet.ServletContextHandler
+import org.eclipse.jetty.ee10.servlet.ServletContextHandler
 import org.mockito.ArgumentMatchers.any
 import org.mockito.Mockito._
 import org.mockito.invocation.InvocationOnMock
diff --git 
a/core/src/test/scala/org/apache/spark/deploy/history/HistoryServerSuite.scala 
b/core/src/test/scala/org/apache/spark/deploy/history/HistoryServerSuite.scala
index c7b1b27a1b89..cf024b8afb4e 100644
--- 
a/core/src/test/scala/org/apache/spark/deploy/history/HistoryServerSuite.scala
+++ 
b/core/src/test/scala/org/apache/spark/deploy/history/HistoryServerSuite.scala
@@ -671,17 +671,22 @@ abstract class HistoryServerSuite extends SparkFunSuite 
with BeforeAndAfter with
     val multiAttemptAppid = "local-1430917381535"
     val lastAttemptId = Some(2)
     val lastAttemptUrl = buildPageAttemptUrl(multiAttemptAppid, lastAttemptId)
-    Seq(None, Some(1), Some(2)).foreach { attemptId =>
-      val url = buildPageAttemptUrl(multiAttemptAppid, attemptId)
-      val (code, location) = getRedirectUrl(url)
-      assert(code === 302, s"Unexpected status code $code for $url")
-      attemptId match {
-        case None =>
-          assert(location.stripSuffix("/") === lastAttemptUrl.toString)
-        case _ =>
-          assert(location.stripSuffix("/") === url.toString)
-      }
-      HistoryServerSuite.getUrl(new URI(location).toURL)
+    // If an application has multiple attempts, the path ends with the last 
attempt ID is the root
+    // of the context path of the application.
+    Seq((None, 302), (Some(1), 302), (Some(2), 301)).foreach {
+      case (attemptId, expectedCode) =>
+        val url = buildPageAttemptUrl(multiAttemptAppid, attemptId)
+        val (code, location) = getRedirectUrl(url)
+        assert(
+          code === expectedCode, s"Unexpected status code $code for $url")
+        attemptId match {
+          case None =>
+            assert(location.stripSuffix("/") === lastAttemptUrl.getPath)
+          case _ =>
+            assert(location.stripSuffix("/") === url.getPath)
+        }
+        HistoryServerSuite.getUrl(
+          new URI(url.getProtocol, url.getAuthority, location, null, 
null).toURL)
     }
   }
 
@@ -691,13 +696,13 @@ abstract class HistoryServerSuite extends SparkFunSuite 
with BeforeAndAfter with
 
     val url = buildPageAttemptUrl(oneAttemptAppId, None)
     val (code, location) = getRedirectUrl(url)
-    assert(code === 302, s"Unexpected status code $code for $url")
-    assert(location === url.toString + "/")
+    assert(code === 301, s"Unexpected status code $code for $url")
+    assert(location === url.getPath + "/")
 
     val url2 = buildPageAttemptUrl(multiAttemptAppid, None)
     val (code2, location2) = getRedirectUrl(url2)
     assert(code2 === 302, s"Unexpected status code $code2 for $url2")
-    assert(location2 === url2.toString + "/2/")
+    assert(location2 === url2.getPath + "/2/")
   }
 
   def getRedirectUrl(url: URL): (Int, String) = {
@@ -755,7 +760,7 @@ abstract class HistoryServerSuite extends SparkFunSuite 
with BeforeAndAfter with
     conn.setInstanceFollowRedirects(false)
     conn.connect()
     assert(conn.getResponseCode === 302)
-    assert(conn.getHeaderField("Location") === s"http://$localhost:$port/";)
+    assert(conn.getHeaderField("Location") === "/")
   }
 }
 
diff --git 
a/core/src/test/scala/org/apache/spark/deploy/history/RealBrowserUIHistoryServerSuite.scala
 
b/core/src/test/scala/org/apache/spark/deploy/history/RealBrowserUIHistoryServerSuite.scala
index 7effeee3424b..a1ac2a0f09d9 100644
--- 
a/core/src/test/scala/org/apache/spark/deploy/history/RealBrowserUIHistoryServerSuite.scala
+++ 
b/core/src/test/scala/org/apache/spark/deploy/history/RealBrowserUIHistoryServerSuite.scala
@@ -18,8 +18,8 @@
 package org.apache.spark.deploy.history
 
 import jakarta.servlet.http.HttpServletRequest
-import org.eclipse.jetty.proxy.ProxyServlet
-import org.eclipse.jetty.servlet.{ServletContextHandler, ServletHolder}
+import org.eclipse.jetty.ee10.proxy.ProxyServlet
+import org.eclipse.jetty.ee10.servlet.{ServletContextHandler, ServletHolder}
 import org.openqa.selenium.WebDriver
 import org.scalatest.concurrent.Eventually._
 import org.scalatest.matchers.must.Matchers
diff --git a/core/src/test/scala/org/apache/spark/ui/UISuite.scala 
b/core/src/test/scala/org/apache/spark/ui/UISuite.scala
index a10060474caa..e506c0a7ab8d 100644
--- a/core/src/test/scala/org/apache/spark/ui/UISuite.scala
+++ b/core/src/test/scala/org/apache/spark/ui/UISuite.scala
@@ -25,7 +25,7 @@ import scala.io.Source
 
 import jakarta.servlet._
 import jakarta.servlet.http.{HttpServlet, HttpServletRequest, 
HttpServletResponse}
-import org.eclipse.jetty.servlet.{ServletContextHandler, ServletHolder}
+import org.eclipse.jetty.ee10.servlet.{ServletContextHandler, ServletHolder}
 import org.eclipse.jetty.util.thread.QueuedThreadPool
 import org.mockito.Mockito.{mock, when}
 import org.scalatest.concurrent.Eventually._
@@ -234,7 +234,7 @@ class UISuite extends SparkFunSuite {
     val targetUri = URI.create(s"http://$localhost:4040";)
     when(clientRequest.getScheme()).thenReturn("http")
     when(clientRequest.getHeader("host")).thenReturn(s"$localhost:8080")
-    when(clientRequest.getPathInfo()).thenReturn("/proxy/worker-id/jobs")
+    when(clientRequest.getPathInfo()).thenReturn("/worker-id/jobs")
     var newHeader = JettyUtils.createProxyLocationHeader(headerValue, 
clientRequest, targetUri)
     assert(newHeader.toString() === 
s"http://$localhost:8080/proxy/worker-id/jobs";)
     headerValue = s"http://$localhost:4041/jobs";
@@ -368,8 +368,11 @@ class UISuite extends SparkFunSuite {
       serverInfo.addHandler(redirect, securityMgr)
 
       // Test Jetty's built-in redirect to add the trailing slash to the 
context path.
+      // As of `Jetty 12`, when asking for the root of a servlet context 
without the trailing
+      // slash, status code 301 is returned.
       TestUtils.withHttpConnection(new URI(s"$serverAddr/ctx1").toURL) { conn 
=>
-        assert(conn.getResponseCode() === HttpServletResponse.SC_FOUND)
+        conn.setInstanceFollowRedirects(false)
+        assert(conn.getResponseCode() === 
HttpServletResponse.SC_MOVED_PERMANENTLY)
         val location = Option(conn.getHeaderFields().get("Location"))
           .map(_.get(0)).orNull
         assert(location === s"$proxyRoot/ctx1/")
@@ -400,7 +403,7 @@ class UISuite extends SparkFunSuite {
     }
   }
 
-  test("SPARK-45522: Jetty 10 and above shouuld return status code 302 with 
correct redirect url" +
+  test("SPARK-47086: Jetty 12 and above should return status code 301 with 
correct redirect url" +
     " when request URL ends with a context path without trailing '/'") {
     val proxyRoot = "https://proxy.example.com:443/prefix";
     val (conf, securityMgr, sslOptions) = sslDisabledConf()
@@ -415,9 +418,10 @@ class UISuite extends SparkFunSuite {
       assert(TestUtils.httpResponseCode(new URI(urlStr + "/").toURL) === 
HttpServletResponse.SC_OK)
 
       // In the case of trailing slash,
-      // 302 should be return and the redirect URL shouuld be part of the 
header.
-      assert(TestUtils.redirectUrl(new URI(urlStr).toURL) === proxyRoot + 
"/ctx/");
-      assert(TestUtils.httpResponseCode(new URI(urlStr).toURL) === 
HttpServletResponse.SC_FOUND)
+      // 301 should be return and the redirect URL should be part of the 
header.
+      assert(TestUtils.redirectUrl(new URI(urlStr).toURL) === proxyRoot + 
"/ctx/")
+      assert(TestUtils.httpResponseCode(
+        new URI(urlStr).toURL) === HttpServletResponse.SC_MOVED_PERMANENTLY)
     } finally {
       stopServer(serverInfo)
     }
diff --git a/dev/deps/spark-deps-hadoop-3-hive-2.3 
b/dev/deps/spark-deps-hadoop-3-hive-2.3
index 1aa699a89b82..8ca21486235f 100644
--- a/dev/deps/spark-deps-hadoop-3-hive-2.3
+++ b/dev/deps/spark-deps-hadoop-3-hive-2.3
@@ -109,9 +109,9 @@ 
jackson-module-scala_2.13/2.20.1//jackson-module-scala_2.13-2.20.1.jar
 jakarta.activation-api/2.1.3//jakarta.activation-api-2.1.3.jar
 jakarta.annotation-api/2.1.1//jakarta.annotation-api-2.1.1.jar
 jakarta.inject-api/2.0.1//jakarta.inject-api-2.0.1.jar
-jakarta.servlet-api/5.0.0//jakarta.servlet-api-5.0.0.jar
+jakarta.servlet-api/6.0.0//jakarta.servlet-api-6.0.0.jar
 jakarta.validation-api/3.0.2//jakarta.validation-api-3.0.2.jar
-jakarta.ws.rs-api/3.0.0//jakarta.ws.rs-api-3.0.0.jar
+jakarta.ws.rs-api/3.1.0//jakarta.ws.rs-api-3.1.0.jar
 jakarta.xml.bind-api/4.0.2//jakarta.xml.bind-api-4.0.2.jar
 janino/3.1.9//janino-3.1.9.jar
 java-diff-utils/4.16//java-diff-utils-4.16.jar
@@ -125,15 +125,15 @@ jaxb-runtime/4.0.5//jaxb-runtime-4.0.5.jar
 jcl-over-slf4j/2.0.17//jcl-over-slf4j-2.0.17.jar
 jdo-api/3.0.1//jdo-api-3.0.1.jar
 jdom2/2.0.6//jdom2-2.0.6.jar
-jersey-client/3.0.18//jersey-client-3.0.18.jar
-jersey-common/3.0.18//jersey-common-3.0.18.jar
-jersey-container-servlet-core/3.0.18//jersey-container-servlet-core-3.0.18.jar
-jersey-container-servlet/3.0.18//jersey-container-servlet-3.0.18.jar
-jersey-hk2/3.0.18//jersey-hk2-3.0.18.jar
-jersey-server/3.0.18//jersey-server-3.0.18.jar
+jersey-client/3.1.11//jersey-client-3.1.11.jar
+jersey-common/3.1.11//jersey-common-3.1.11.jar
+jersey-container-servlet-core/3.1.11//jersey-container-servlet-core-3.1.11.jar
+jersey-container-servlet/3.1.11//jersey-container-servlet-3.1.11.jar
+jersey-hk2/3.1.11//jersey-hk2-3.1.11.jar
+jersey-server/3.1.11//jersey-server-3.1.11.jar
 jettison/1.5.4//jettison-1.5.4.jar
-jetty-util-ajax/11.0.26//jetty-util-ajax-11.0.26.jar
-jetty-util/11.0.26//jetty-util-11.0.26.jar
+jetty-util-ajax/12.1.5//jetty-util-ajax-12.1.5.jar
+jetty-util/12.1.5//jetty-util-12.1.5.jar
 jjwt-api/0.12.6//jjwt-api-0.12.6.jar
 jjwt-impl/0.12.6//jjwt-impl-0.12.6.jar
 jjwt-jackson/0.12.6//jjwt-jackson-0.12.6.jar
diff --git a/pom.xml b/pom.xml
index 060a14792d3b..202985c4059a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -144,8 +144,8 @@
     <parquet.version>1.16.0</parquet.version>
     <orc.version>2.2.1</orc.version>
     <orc.classifier>shaded-protobuf</orc.classifier>
-    <jetty.version>11.0.26</jetty.version>
-    <jakartaservlet.version>5.0.0</jakartaservlet.version>
+    <jetty.version>12.1.5</jetty.version>
+    <jakartaservlet.version>6.0.0</jakartaservlet.version>
     <!-- SPARK-46938: Required by Hive / LibThrift libs -->
     <javaxservlet.version>4.0.1</javaxservlet.version>
     <chill.version>0.10.0</chill.version>
@@ -201,7 +201,7 @@
     <guava.failureaccess.version>1.0.3</guava.failureaccess.version>
     <gson.version>2.13.2</gson.version>
     <janino.version>3.1.9</janino.version>
-    <jersey.version>3.0.18</jersey.version>
+    <jersey.version>3.1.11</jersey.version>
     <joda.version>2.14.0</joda.version>
     <jsr305.version>3.0.0</jsr305.version>
     <jaxb.version>2.2.11</jaxb.version>
@@ -560,20 +560,20 @@
         <scope>provided</scope>
       </dependency>
       <dependency>
-        <groupId>org.eclipse.jetty</groupId>
-        <artifactId>jetty-servlet</artifactId>
+        <groupId>org.eclipse.jetty.ee10</groupId>
+        <artifactId>jetty-ee10-servlet</artifactId>
         <version>${jetty.version}</version>
         <scope>provided</scope>
       </dependency>
       <dependency>
-        <groupId>org.eclipse.jetty</groupId>
-        <artifactId>jetty-servlets</artifactId>
+        <groupId>org.eclipse.jetty.ee10</groupId>
+        <artifactId>jetty-ee10-servlets</artifactId>
         <version>${jetty.version}</version>
         <scope>provided</scope>
       </dependency>
       <dependency>
-        <groupId>org.eclipse.jetty</groupId>
-        <artifactId>jetty-proxy</artifactId>
+        <groupId>org.eclipse.jetty.ee10</groupId>
+        <artifactId>jetty-ee10-proxy</artifactId>
         <version>${jetty.version}</version>
         <scope>provided</scope>
       </dependency>
@@ -596,8 +596,8 @@
         <scope>provided</scope>
       </dependency>
       <dependency>
-        <groupId>org.eclipse.jetty</groupId>
-        <artifactId>jetty-plus</artifactId>
+        <groupId>org.eclipse.jetty.ee10</groupId>
+        <artifactId>jetty-ee10-plus</artifactId>
         <version>${jetty.version}</version>
         <scope>provided</scope>
       </dependency>
@@ -608,8 +608,8 @@
         <scope>provided</scope>
       </dependency>
       <dependency>
-        <groupId>org.eclipse.jetty</groupId>
-        <artifactId>jetty-webapp</artifactId>
+        <groupId>org.eclipse.jetty.ee10</groupId>
+        <artifactId>jetty-ee10-webapp</artifactId>
         <version>${jetty.version}</version>
         <scope>provided</scope>
       </dependency>
diff --git a/project/MimaExcludes.scala b/project/MimaExcludes.scala
index ff28a08072a8..c62569e21227 100644
--- a/project/MimaExcludes.scala
+++ b/project/MimaExcludes.scala
@@ -36,7 +36,11 @@ object MimaExcludes {
   // Exclude rules for 4.2.x from 4.1.0
   lazy val v42excludes = v41excludes ++ Seq(
     // Add DEBUG format to ErrorMessageFormat enum
-    ProblemFilters.exclude[Problem]("org.apache.spark.ErrorMessageFormat*")
+    ProblemFilters.exclude[Problem]("org.apache.spark.ErrorMessageFormat*"),
+    // [SPARK-47086][BUILD][CORE][WEBUI] Upgrade Jetty to 12.1.4
+    
ProblemFilters.exclude[MissingTypesProblem]("org.apache.spark.ui.ProxyRedirectHandler$ResponseWrapper"),
+    
ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.spark.ui.ProxyRedirectHandler#ResponseWrapper.sendRedirect"),
+    
ProblemFilters.exclude[IncompatibleMethTypeProblem]("org.apache.spark.ui.ProxyRedirectHandler#ResponseWrapper.this")
   )
 
   // Exclude rules for 4.1.x from 4.0.0
diff --git a/repl/pom.xml b/repl/pom.xml
index f0d0dd396389..2eb732c1c546 100644
--- a/repl/pom.xml
+++ b/repl/pom.xml
@@ -119,8 +119,8 @@
       <artifactId>jetty-server</artifactId>
     </dependency>
     <dependency>
-      <groupId>org.eclipse.jetty</groupId>
-      <artifactId>jetty-plus</artifactId>
+      <groupId>org.eclipse.jetty.ee10</groupId>
+      <artifactId>jetty-ee10-plus</artifactId>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jetty</groupId>
diff --git a/resource-managers/yarn/pom.xml b/resource-managers/yarn/pom.xml
index 30169ffa9672..3d4d441dfcf9 100644
--- a/resource-managers/yarn/pom.xml
+++ b/resource-managers/yarn/pom.xml
@@ -108,8 +108,8 @@
       <artifactId>jetty-server</artifactId>
     </dependency>
     <dependency>
-      <groupId>org.eclipse.jetty</groupId>
-      <artifactId>jetty-plus</artifactId>
+      <groupId>org.eclipse.jetty.ee10</groupId>
+      <artifactId>jetty-ee10-plus</artifactId>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jetty</groupId>
@@ -120,12 +120,12 @@
       <artifactId>jetty-http</artifactId>
     </dependency>
     <dependency>
-      <groupId>org.eclipse.jetty</groupId>
-      <artifactId>jetty-servlet</artifactId>
+      <groupId>org.eclipse.jetty.ee10</groupId>
+      <artifactId>jetty-ee10-servlet</artifactId>
     </dependency>
     <dependency>
-      <groupId>org.eclipse.jetty</groupId>
-      <artifactId>jetty-servlets</artifactId>
+      <groupId>org.eclipse.jetty.ee10</groupId>
+      <artifactId>jetty-ee10-servlets</artifactId>
     </dependency>
     <!-- End of shaded deps. -->
 
diff --git 
a/resource-managers/yarn/src/test/scala/org/apache/spark/deploy/yarn/AmIpFilterSuite.scala
 
b/resource-managers/yarn/src/test/scala/org/apache/spark/deploy/yarn/AmIpFilterSuite.scala
index aabf35d66e6b..f9bd0ab844b9 100644
--- 
a/resource-managers/yarn/src/test/scala/org/apache/spark/deploy/yarn/AmIpFilterSuite.scala
+++ 
b/resource-managers/yarn/src/test/scala/org/apache/spark/deploy/yarn/AmIpFilterSuite.scala
@@ -29,8 +29,8 @@ import scala.jdk.CollectionConverters._
 import jakarta.servlet.{FilterChain, FilterConfig, ServletContext, 
ServletException, ServletOutputStream, ServletRequest, ServletResponse}
 import jakarta.servlet.http.{Cookie, HttpServlet, HttpServletRequest, 
HttpServletResponse}
 import jakarta.ws.rs.core.MediaType
+import org.eclipse.jetty.ee10.servlet.{ServletContextHandler, ServletHolder}
 import org.eclipse.jetty.server.{Server, ServerConnector}
-import org.eclipse.jetty.servlet.{ServletContextHandler, ServletHolder}
 import org.eclipse.jetty.util.thread.QueuedThreadPool
 import org.mockito.Mockito.{mock, when}
 import org.scalatest.concurrent.Eventually._
@@ -272,10 +272,6 @@ class AmIpFilterSuite extends SparkFunSuite {
 
     override def encodeRedirectURL(url: String): String = url
 
-    override def encodeUrl(url: String): String = null
-
-    override def encodeRedirectUrl(url: String): String = null
-
     @throws[IOException]
     override def sendError(sc: Int, msg: String): Unit = {}
 
@@ -284,8 +280,6 @@ class AmIpFilterSuite extends SparkFunSuite {
 
     override def setStatus(status: Int): Unit = this.status = status
 
-    override def setStatus(sc: Int, sm: String): Unit = {}
-
     override def getStatus: Int = 0
 
     override def setContentType(contentType: String): Unit = this.contentType 
= contentType
diff --git a/sql/core/pom.xml b/sql/core/pom.xml
index a5b5c399d4fc..ab6a8f8182e6 100644
--- a/sql/core/pom.xml
+++ b/sql/core/pom.xml
@@ -159,8 +159,8 @@
       <artifactId>parquet-hadoop</artifactId>
     </dependency>
     <dependency>
-      <groupId>org.eclipse.jetty</groupId>
-      <artifactId>jetty-servlet</artifactId>
+      <groupId>org.eclipse.jetty.ee10</groupId>
+      <artifactId>jetty-ee10-servlet</artifactId>
     </dependency>
     <dependency>
       <groupId>com.fasterxml.jackson.core</groupId>
diff --git a/sql/hive-thriftserver/pom.xml b/sql/hive-thriftserver/pom.xml
index b70180ab753a..58447cfa4ece 100644
--- a/sql/hive-thriftserver/pom.xml
+++ b/sql/hive-thriftserver/pom.xml
@@ -91,8 +91,8 @@
       <scope>provided</scope>
     </dependency>
     <dependency>
-      <groupId>org.eclipse.jetty</groupId>
-      <artifactId>jetty-servlet</artifactId>
+      <groupId>org.eclipse.jetty.ee10</groupId>
+      <artifactId>jetty-ee10-servlet</artifactId>
       <scope>provided</scope>
     </dependency>
     <dependency>
diff --git 
a/sql/hive-thriftserver/src/main/java/org/apache/hive/service/cli/thrift/ThriftHttpCLIService.java
 
b/sql/hive-thriftserver/src/main/java/org/apache/hive/service/cli/thrift/ThriftHttpCLIService.java
index 9592bffcf1bf..1ada2bdb0bca 100644
--- 
a/sql/hive-thriftserver/src/main/java/org/apache/hive/service/cli/thrift/ThriftHttpCLIService.java
+++ 
b/sql/hive-thriftserver/src/main/java/org/apache/hive/service/cli/thrift/ThriftHttpCLIService.java
@@ -41,8 +41,8 @@ import org.eclipse.jetty.server.AbstractConnectionFactory;
 import org.eclipse.jetty.server.ConnectionFactory;
 import org.eclipse.jetty.server.HttpConnectionFactory;
 import org.eclipse.jetty.server.ServerConnector;
-import org.eclipse.jetty.servlet.ServletContextHandler;
-import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.ee10.servlet.ServletContextHandler;
+import org.eclipse.jetty.ee10.servlet.ServletHolder;
 import org.eclipse.jetty.util.ssl.SslContextFactory;
 import org.eclipse.jetty.util.thread.ExecutorThreadPool;
 import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler;
diff --git a/streaming/pom.xml b/streaming/pom.xml
index a8fd54bbf2b8..1822d4699f27 100644
--- a/streaming/pom.xml
+++ b/streaming/pom.xml
@@ -76,8 +76,8 @@
       <artifactId>jetty-server</artifactId>
     </dependency>
     <dependency>
-      <groupId>org.eclipse.jetty</groupId>
-      <artifactId>jetty-plus</artifactId>
+      <groupId>org.eclipse.jetty.ee10</groupId>
+      <artifactId>jetty-ee10-plus</artifactId>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jetty</groupId>
@@ -88,12 +88,12 @@
       <artifactId>jetty-http</artifactId>
     </dependency>
     <dependency>
-      <groupId>org.eclipse.jetty</groupId>
-      <artifactId>jetty-servlet</artifactId>
+      <groupId>org.eclipse.jetty.ee10</groupId>
+      <artifactId>jetty-ee10-servlet</artifactId>
     </dependency>
     <dependency>
-      <groupId>org.eclipse.jetty</groupId>
-      <artifactId>jetty-servlets</artifactId>
+      <groupId>org.eclipse.jetty.ee10</groupId>
+      <artifactId>jetty-ee10-servlets</artifactId>
     </dependency>
     <!-- End of shaded deps. -->
 


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

Reply via email to