Skip to content

Commit

Permalink
CAMEL-19481: Upgrade to Jetty 10
Browse files Browse the repository at this point in the history
  • Loading branch information
essobedo committed Jun 22, 2023
1 parent d5bbc6b commit 2f507b8
Show file tree
Hide file tree
Showing 85 changed files with 464 additions and 371 deletions.
4 changes: 2 additions & 2 deletions camel-dependencies/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
<aries-blueprint-proxy-version>1.1.12</aries-blueprint-proxy-version>
<aries-spifly-version>1.3.5</aries-spifly-version>
<aries-util-version>1.1.3</aries-util-version>
<arquillian-jetty-embedded-9-version>1.0.0.CR3</arquillian-jetty-embedded-9-version>
<arquillian-jetty-embedded-10-version>1.0.0.Final</arquillian-jetty-embedded-10-version>
<arquillian-version>1.6.0.Final</arquillian-version>
<arquillian-weld-embedded-version>2.0.0.Final</arquillian-weld-embedded-version>
<as2-lib-version>4.11.0</as2-lib-version>
Expand Down Expand Up @@ -323,7 +323,7 @@
<jettison-version>1.5.3</jettison-version>
<jetty-plugin-version>${jetty-version}</jetty-plugin-version>
<jetty-runner-groupId>org.eclipse.jetty</jetty-runner-groupId>
<jetty-version>${jetty9-version}</jetty-version>
<jetty-version>10.0.15</jetty-version>
<jetty9-version>9.4.51.v20230217</jetty9-version>
<jgit-version>6.3.0.202209071007-r</jgit-version>
<jgroups-raft-leveldbjni-version>1.8</jgroups-raft-leveldbjni-version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
"kind": "component",
"name": "jetty",
"title": "Jetty",
"description": "Expose HTTP endpoints using Jetty 9.",
"description": "Expose HTTP endpoints using Jetty 10.",
"deprecated": false,
"deprecationNote": "",
"firstVersion": "1.2.0",
"label": "http",
"javaType": "org.apache.camel.component.jetty9.JettyHttpComponent9",
"javaType": "org.apache.camel.component.jetty10.JettyHttpComponent10",
"supportLevel": "Stable",
"groupId": "org.apache.camel",
"artifactId": "camel-jetty",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"headers": {
"websocket.connectionKey": { "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Producer: Sends the message to all clients which are currently connected. You can use the sendToAll option on the endpoint instead of using this header. Consumer: Connection key identifying an individual client connection. You can save this and specify it again when routing to a producer endpoing in order to direct messages to a specific connected client.", "constantName": "org.apache.camel.component.websocket.WebsocketConstants#CONNECTION_KEY" },
"websocket.sendToAll": { "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Sends the message to all clients which are currently connected. You can use the sendToAll option on the endpoint instead of using this header.", "constantName": "org.apache.camel.component.websocket.WebsocketConstants#SEND_TO_ALL" },
"websocket.remoteAddress": { "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "java.net.InetSocketAddress", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Remote address of the websocket session.", "constantName": "org.apache.camel.component.websocket.WebsocketConstants#REMOTE_ADDRESS" },
"websocket.remoteAddress": { "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "java.net.SocketAddress", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Remote address of the websocket session.", "constantName": "org.apache.camel.component.websocket.WebsocketConstants#REMOTE_ADDRESS" },
"websocket.subprotocol": { "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "If a specific subprotocol was negotiated, it will be specfied in this header. Note that if you specify the any subprotocol to be supported, and a client requests a specific subprotocol, the connection will be accepted without a specific subprotocol being used. You need to specifically support a given protocol by name if you want it returned to the client and to show up in the message header.", "constantName": "org.apache.camel.component.websocket.WebsocketConstants#SUBPROTOCOL" },
"websocket.relativePath": { "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "If you specify a wildcard URI path for an endpoint, and a websocket client connects to that websocket endpoing, the relative path that the client specified will be provided in this header. For example, if you specified websocket:\/\/0.0.0.0:80\/api\/ as your endpoint URI, and a client connects to the server at ws:\/\/host.com\/api\/specialized\/apipath then specialized\/apipath is provided in the relative path header of all messages from that client.", "constantName": "org.apache.camel.component.websocket.WebsocketConstants#RELATIVE_PATH" }
},
Expand Down
29 changes: 22 additions & 7 deletions components/camel-atmosphere-websocket/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,18 @@
<version>${javax-servlet-api-version}</version>
</dependency>

<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-server</artifactId>
<version>${jetty9-version}</version>
</dependency>

<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>${jetty9-version}</version>
</dependency>

<!-- atmosphere -->
<dependency>
<groupId>org.atmosphere</groupId>
Expand Down Expand Up @@ -99,13 +111,16 @@
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-server</artifactId>
<version>${jetty-version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>org.eclipse.jetty</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>

<dependency>
Expand Down
2 changes: 1 addition & 1 deletion components/camel-cometd/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@

<properties>
<camel.osgi.import.pkg>
org.eclipse.jetty.*;version="[9.4,10)",
org.eclipse.jetty.*;version="[10,11)",
${camel.osgi.import.defaults},
*
</camel.osgi.import.pkg>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ protected ServerConnector getSslSocketConnector(Server server) throws Exception
sslParams = retrieveGlobalSslContextParameters();
}

SslContextFactory sslContextFactory = new SslContextFactory();
SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
sslContextFactory.setEndpointIdentificationAlgorithm(null);
if (sslParams != null) {
sslContextFactory.setSslContext(sslParams.createSSLContext(getCamelContext()));
Expand Down
4 changes: 2 additions & 2 deletions components/camel-jetty-common/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@
<packaging>jar</packaging>

<name>Camel :: Jetty :: Common</name>
<description>Camel Jetty 9.x support</description>
<description>Camel Jetty 10.x support</description>

<properties>
<camel.osgi.import.before.defaults>
org.eclipse.jetty.*;version="[9.4,10)",
org.eclipse.jetty.*;version="[10,11)",
javax.servlet.*;version="${servlet-version-range}"
</camel.osgi.import.before.defaults>
<firstVersion>2.15.0</firstVersion>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ groupId=org.apache.camel
artifactId=camel-jetty-common
version=3.21.0-SNAPSHOT
projectName=Camel :: Jetty :: Common
projectDescription=Camel Jetty 9.x support
projectDescription=Camel Jetty 10.x support
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"kind": "other",
"name": "jetty-common",
"title": "Jetty Common",
"description": "Camel Jetty 9.x support",
"description": "Camel Jetty 10.x support",
"deprecated": false,
"firstVersion": "2.15.0",
"supportLevel": "Stable",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,12 @@
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeoutException;
import java.util.stream.Collectors;

import javax.servlet.AsyncContext;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import javax.servlet.DispatcherType;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
Expand All @@ -41,14 +44,14 @@
import org.apache.camel.spi.UnitOfWork;
import org.apache.camel.support.ObjectHelper;
import org.apache.camel.util.UnsafeUriCharactersEncoder;
import org.eclipse.jetty.continuation.Continuation;
import org.eclipse.jetty.continuation.ContinuationSupport;

/**
* Servlet which leverage <a href="http://wiki.eclipse.org/Jetty/Feature/Continuations">Jetty Continuations</a>.
*/
public class CamelContinuationServlet extends CamelServlet {

static final String TIMEOUT_ERROR = "CamelTimeoutException";

static final String EXCHANGE_ATTRIBUTE_NAME = "CamelExchange";
static final String EXCHANGE_ATTRIBUTE_ID = "CamelExchangeId";

Expand Down Expand Up @@ -178,27 +181,20 @@ protected void handleDoService(final HttpServletRequest request, final HttpServl
final Exchange result = (Exchange) request.getAttribute(EXCHANGE_ATTRIBUTE_NAME);
if (result == null) {
// no asynchronous result so leverage continuation
final Continuation continuation = ContinuationSupport.getContinuation(request);
if (continuation.isInitial() && continuationTimeout != null) {
AsyncContext asyncContext = request.startAsync();
if (isInitial(request) && continuationTimeout != null) {
// set timeout on initial
continuation.setTimeout(continuationTimeout);
asyncContext.setTimeout(continuationTimeout.longValue());
}

asyncContext.addListener(new ExpiredListener(), request, response);

// are we suspended and a request is dispatched initially?
if (consumer.isSuspended() && continuation.isInitial()) {
if (consumer.isSuspended() && isInitial(request)) {
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
return;
}

if (continuation.isExpired()) {
String id = (String) continuation.getAttribute(EXCHANGE_ATTRIBUTE_ID);
// remember this id as expired
expiredExchanges.put(id, id);
log.warn("Continuation expired of exchangeId: {}", id);
consumer.getBinding().doWriteExceptionResponse(new TimeoutException(), response);
return;
}

// a new request so create an exchange
// must be prototype scoped (not pooled) so we create the exchange via endpoint
final Exchange exchange = consumer.createExchange(false);
Expand Down Expand Up @@ -231,7 +227,7 @@ protected void handleDoService(final HttpServletRequest request, final HttpServl
if (log.isTraceEnabled()) {
log.trace("Suspending continuation of exchangeId: {}", exchange.getExchangeId());
}
continuation.setAttribute(EXCHANGE_ATTRIBUTE_ID, exchange.getExchangeId());
request.setAttribute(EXCHANGE_ATTRIBUTE_ID, exchange.getExchangeId());

// we want to handle the UoW
UnitOfWork uow = exchange.getUnitOfWork();
Expand All @@ -248,9 +244,6 @@ protected void handleDoService(final HttpServletRequest request, final HttpServl
ee.setUnitOfWork(uow);
}

// must suspend before we process the exchange
continuation.suspend();

ClassLoader oldTccl = overrideTccl(exchange);

if (log.isTraceEnabled()) {
Expand All @@ -267,8 +260,8 @@ public void done(boolean doneSync) {
log.trace("Resuming continuation of exchangeId: {}", exchange.getExchangeId());
}
// resume processing after both, sync and async callbacks
continuation.setAttribute(EXCHANGE_ATTRIBUTE_NAME, exchange);
continuation.resume();
request.setAttribute(EXCHANGE_ATTRIBUTE_NAME, exchange);
asyncContext.dispatch();
} else {
log.warn("Cannot resume expired continuation of exchangeId: {}", exchange.getExchangeId());
consumer.releaseExchange(exchange, false);
Expand Down Expand Up @@ -308,6 +301,34 @@ public void done(boolean doneSync) {
}
}

private boolean isInitial(HttpServletRequest request) {
return request.getDispatcherType() != DispatcherType.ASYNC;
}

private class ExpiredListener implements AsyncListener {
@Override
public void onComplete(AsyncEvent event) throws IOException {
}

@Override
public void onTimeout(AsyncEvent event) throws IOException {
HttpServletRequest request = (HttpServletRequest) event.getSuppliedRequest();
String id = (String) request.getAttribute(EXCHANGE_ATTRIBUTE_ID);
// remember this id as expired
expiredExchanges.put(id, id);
log.warn("Continuation expired of exchangeId: {}", id);
request.setAttribute(TIMEOUT_ERROR, Boolean.TRUE);
}

@Override
public void onError(AsyncEvent event) throws IOException {
}

@Override
public void onStartAsync(AsyncEvent event) throws IOException {
}
}

private void updateHttpPath(Exchange exchange, String contextPath) {
String httpPath = (String) exchange.getIn().getHeader(JettyHttpConstants.HTTP_PATH);
// encode context path in case it contains unsafe chars, because HTTP_PATH isn't decoded at this moment
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EventListener;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -591,7 +592,7 @@ protected Connector getSslSocketConnector(Server server, JettyHttpEndpoint endpo
protected Connector createConnector(Server server, JettyHttpEndpoint endpoint) {

// now we just use the SelectChannelConnector as the default connector
SslContextFactory sslcf = null;
SslContextFactory.Server sslcf = null;

// Note that this was set on the endpoint when it was constructed. It was
// either explicitly set at the component or on the endpoint, but either way,
Expand All @@ -601,12 +602,12 @@ protected Connector createConnector(Server server, JettyHttpEndpoint endpoint) {

if (endpointSslContextParameters != null) {
try {
sslcf = createSslContextFactory(endpointSslContextParameters, false);
sslcf = (SslContextFactory.Server) createSslContextFactory(endpointSslContextParameters, false);
} catch (Exception e) {
throw new RuntimeCamelException(e);
}
} else if ("https".equals(endpoint.getProtocol())) {
sslcf = new SslContextFactory();
sslcf = new SslContextFactory.Server();
sslcf.setEndpointIdentificationAlgorithm(null);
String keystoreProperty = System.getProperty(JETTY_SSL_KEYSTORE);
if (keystoreProperty != null) {
Expand Down Expand Up @@ -634,7 +635,7 @@ protected Connector createConnector(Server server, JettyHttpEndpoint endpoint) {
}

protected abstract AbstractConnector createConnectorJettyInternal(
Server server, JettyHttpEndpoint endpoint, SslContextFactory sslcf);
Server server, JettyHttpEndpoint endpoint, SslContextFactory.Server sslcf);

private SslContextFactory createSslContextFactory(SSLContextParameters ssl, boolean client)
throws GeneralSecurityException, IOException {
Expand Down Expand Up @@ -1278,6 +1279,11 @@ public void handle(
HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
String msg = HttpStatus.getMessage(response.getStatus());
Object timeout = request.getAttribute(CamelContinuationServlet.TIMEOUT_ERROR);
if (Boolean.TRUE.equals(timeout)) {
request.setAttribute(RequestDispatcher.ERROR_STATUS_CODE, 504);
response.setStatus(504);
}
request.setAttribute(RequestDispatcher.ERROR_MESSAGE, msg);
super.handle(target, baseRequest, request, response);
}
Expand Down Expand Up @@ -1344,7 +1350,7 @@ private void addServerMBean(Server server) {

try {
Object o = getContainer(server);
o.getClass().getMethod("addEventListener", Container.Listener.class).invoke(o, mbContainer);
o.getClass().getMethod("addEventListener", EventListener.class).invoke(o, mbContainer);
mbContainer.getClass().getMethod("beanAdded", Container.class, Object.class)
.invoke(mbContainer, null, server);
} catch (RuntimeException rex) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
import javax.servlet.http.HttpServletRequest;

/**
* To enable handle attachments with Jetty 9 when this filter is set.
* To enable handle attachments with Jetty 10 when this filter is set.
* <p/>
* To replace the deprecated org.eclipse.jetty.servlets.MultiPartFilter Tell AttachmentHttpBinding to use Servlet 3
* HttpServletRequest.getParts API
Expand Down
Loading

0 comments on commit 2f507b8

Please sign in to comment.