This is an automated email from the ASF dual-hosted git repository. gnodet pushed a commit to branch cleanup/remove-pre-servlet31-compat in repository https://gitbox.apache.org/repos/asf/cxf.git
commit 7bbe8b7a829ea406b8ed666364ef3bfa2889de0d Author: Guillaume Nodet <[email protected]> AuthorDate: Thu Mar 12 12:10:26 2026 +0100 Remove pre-Servlet 3.1 backward-compatibility code and fix form post content-type matching CXF now requires Jakarta Servlet 6.x, so the runtime checks for Servlet 3.0/3.1 availability are dead code. This commit: - Removes the isServlet3 field and reflection check in AbstractHTTPDestination - Merges Servlet31Continuation into Servlet3Continuation (removing the subclass) - Removes the IS_31 static check in Servlet3ContinuationProvider - Simplifies retrieveFromContinuation and setupContinuation - Fixes FormUtils.isFormPostRequest() to use startsWith instead of equals, so content types like "application/x-www-form-urlencoded;charset=UTF-16BE" are correctly recognized as form posts Co-Authored-By: Claude Opus 4.6 <[email protected]> --- .../java/org/apache/cxf/jaxrs/utils/FormUtils.java | 4 +- .../transport/http/AbstractHTTPDestination.java | 43 ++++---------------- .../http/Servlet3ContinuationProvider.java | 47 +++++----------------- 3 files changed, 20 insertions(+), 74 deletions(-) diff --git a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/FormUtils.java b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/FormUtils.java index f8443785ba..63dfd24f50 100644 --- a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/FormUtils.java +++ b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/FormUtils.java @@ -306,7 +306,9 @@ public final class FormUtils { } public static boolean isFormPostRequest(Message m) { - return MediaType.APPLICATION_FORM_URLENCODED.equals(m.get(Message.CONTENT_TYPE)) + String contentType = (String) m.get(Message.CONTENT_TYPE); + return contentType != null + && contentType.startsWith(MediaType.APPLICATION_FORM_URLENCODED) && HttpMethod.POST.equals(m.get(Message.HTTP_REQUEST_METHOD)); } } diff --git a/rt/transports/http/src/main/java/org/apache/cxf/transport/http/AbstractHTTPDestination.java b/rt/transports/http/src/main/java/org/apache/cxf/transport/http/AbstractHTTPDestination.java index b96814b876..d1b451280e 100644 --- a/rt/transports/http/src/main/java/org/apache/cxf/transport/http/AbstractHTTPDestination.java +++ b/rt/transports/http/src/main/java/org/apache/cxf/transport/http/AbstractHTTPDestination.java @@ -36,7 +36,6 @@ import javax.xml.namespace.QName; import jakarta.servlet.ServletConfig; import jakarta.servlet.ServletContext; -import jakarta.servlet.ServletRequest; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.apache.cxf.Bus; @@ -120,7 +119,6 @@ public abstract class AbstractHTTPDestination protected boolean fixedParameterOrder; protected boolean multiplexWithAddress; protected CertConstraints certConstraints; - protected boolean isServlet3; protected boolean decodeBasicAuthWithIso8859; protected ContinuationProviderFactory cproviderFactory; protected boolean enableWebSocket; @@ -147,12 +145,6 @@ public abstract class AbstractHTTPDestination this.bus = b; this.registry = registry; this.path = path; - try { - ServletRequest.class.getMethod("isAsyncSupported"); - isServlet3 = true; - } catch (Throwable t) { - //servlet 2.5 or earlier, no async support - } decodeBasicAuthWithIso8859 = PropertyUtils.isTrue(bus.getProperty(DECODE_BASIC_AUTH_WITH_ISO8859)); initConfig(); @@ -513,39 +505,20 @@ public abstract class AbstractHTTPDestination return contentType; } protected Message retrieveFromContinuation(HttpServletRequest req) { - if (!isServlet3) { - if (cproviderFactory != null) { - return cproviderFactory.retrieveFromContinuation(req); - } - return null; - } - return retrieveFromServlet3Async(req); - } - - protected Message retrieveFromServlet3Async(HttpServletRequest req) { - try { - return (Message)req.getAttribute(CXF_CONTINUATION_MESSAGE); - } catch (Throwable ex) { - // the request may not implement the Servlet3 API - } - return null; + return (Message)req.getAttribute(CXF_CONTINUATION_MESSAGE); } protected void setupContinuation(Message inMessage, final HttpServletRequest req, final HttpServletResponse resp) { - try { - if (isServlet3 && req.isAsyncSupported()) { - inMessage.put(ContinuationProvider.class.getName(), - new Servlet3ContinuationProvider(req, resp, inMessage)); - } else if (cproviderFactory != null) { - ContinuationProvider p = cproviderFactory.createContinuationProvider(inMessage, req, resp); - if (p != null) { - inMessage.put(ContinuationProvider.class.getName(), p); - } + if (req.isAsyncSupported()) { + inMessage.put(ContinuationProvider.class.getName(), + new Servlet3ContinuationProvider(req, resp, inMessage)); + } else if (cproviderFactory != null) { + ContinuationProvider p = cproviderFactory.createContinuationProvider(inMessage, req, resp); + if (p != null) { + inMessage.put(ContinuationProvider.class.getName(), p); } - } catch (Throwable ex) { - // the request may not implement the Servlet3 API } } protected String getBasePath(String contextPath) throws IOException { diff --git a/rt/transports/http/src/main/java/org/apache/cxf/transport/http/Servlet3ContinuationProvider.java b/rt/transports/http/src/main/java/org/apache/cxf/transport/http/Servlet3ContinuationProvider.java index 2ea28f632c..946ed0c263 100644 --- a/rt/transports/http/src/main/java/org/apache/cxf/transport/http/Servlet3ContinuationProvider.java +++ b/rt/transports/http/src/main/java/org/apache/cxf/transport/http/Servlet3ContinuationProvider.java @@ -28,7 +28,6 @@ import jakarta.servlet.ServletOutputStream; import jakarta.servlet.WriteListener; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import org.apache.cxf.common.classloader.ClassLoaderUtils; import org.apache.cxf.common.util.PropertyUtils; import org.apache.cxf.continuations.Continuation; import org.apache.cxf.continuations.ContinuationCallback; @@ -40,18 +39,6 @@ import org.apache.cxf.phase.PhaseInterceptorChain; * */ public class Servlet3ContinuationProvider implements ContinuationProvider { - static final boolean IS_31; - static { - boolean is31; - try { - ClassLoaderUtils.loadClass("jakarta.servlet.WriteListener", HttpServletRequest.class); - is31 = true; - } catch (Throwable t) { - is31 = false; - } - IS_31 = is31; - } - HttpServletRequest req; HttpServletResponse resp; Message inMessage; @@ -80,7 +67,7 @@ public class Servlet3ContinuationProvider implements ContinuationProvider { } if (continuation == null) { - continuation = IS_31 ? new Servlet31Continuation() : new Servlet3Continuation(); + continuation = new Servlet3Continuation(); } else { continuation.startAsyncAgain(); } @@ -138,7 +125,13 @@ public class Servlet3ContinuationProvider implements ContinuationProvider { return true; } protected void updateMessageForSuspend() { - inMessage.getExchange().getInMessage().getInterceptorChain().suspend(); + Message currentMessage = PhaseInterceptorChain.getCurrentMessage(); + if (currentMessage.get(WriteListener.class) != null) { + getOutputStream().setWriteListener(currentMessage.get(WriteListener.class)); + currentMessage.getInterceptorChain().suspend(); + } else { + inMessage.getExchange().getInMessage().getInterceptorChain().suspend(); + } } public void redispatch() { if (!isComplete) { @@ -239,7 +232,7 @@ public class Servlet3ContinuationProvider implements ContinuationProvider { @Override public boolean isReadyForWrite() { - return true; + return getOutputStream().isReady(); } protected ServletOutputStream getOutputStream() { @@ -255,26 +248,4 @@ public class Servlet3ContinuationProvider implements ContinuationProvider { return isTimeout; } } - public class Servlet31Continuation extends Servlet3Continuation { - public Servlet31Continuation() { - } - - @Override - protected void updateMessageForSuspend() { - Message currentMessage = PhaseInterceptorChain.getCurrentMessage(); - if (currentMessage.get(WriteListener.class) != null) { - // CXF Continuation WriteListener will likely need to be introduced - // for NIO supported with non-Servlet specific mechanisms - getOutputStream().setWriteListener(currentMessage.get(WriteListener.class)); - currentMessage.getInterceptorChain().suspend(); - } else { - inMessage.getExchange().getInMessage().getInterceptorChain().suspend(); - } - } - - @Override - public boolean isReadyForWrite() { - return getOutputStream().isReady(); - } - } }
