I'm currently doing a server refactor along with a new build tool to replace maven. In doing so, I'm updating to 3.1.0-BETA2 and jetty 9.3.10.v20160621. I'm also trying to get cometd running without any configuration files, i.e., no web.xml; everything is to specified using embedded jetty techniques. Therefore, I don't think this error is related to the cometd or jetty versions above but rather an incorrect websocket configuration during startup. Something I'm doing wrong.
I have the longPolling transport working. IE, If I strip out all the websocket-related cometd and jetty jars, this test passes:
import org.eclipse.jetty.client.HttpClient;
import org.cometd.client.BayeuxClient;
import org.cometd.client.transport.ClientTransport;
import org.cometd.client.transport.LongPollingTransport;
@Test
public void testHttpTransport() throws Exception {
HttpClient httpClient = new HttpClient();
httpClient.start();
Map<String, Object> options = new HashMap<String, Object>();
ClientTransport httpTransport = new LongPollingTransport(options, httpClient);
client.handshake();
boolean connected = client.waitFor(1000, BayeuxClient.State.CONNECTED);
assertTrue("client should be connected", connected);
}
Bazel, the build tool I'm using (
http://bazel.io) works similar to buck or pants. In the root directory of a project, one declares external dependencies in a file called WORKSPACE. Maven dependencies are declared via the "maven_jar" build rule. Here are the relevant maven_jar rules. As bazel does not do transitive dependencies (like maven), one has to specify all the jars explicitly.
maven_jar(
name = "javax_websocket_javax_websocket_api",
artifact = "javax.websocket:javax.websocket-api:jar:1.1",
)
maven_jar(
name = "javax_annotation_javax_annotation_api",
artifact = "javax.annotation:javax.annotation-api:jar:1.2",
)
maven_jar(
name = "org_eclipse_jetty_jetty_http",
artifact = "org.eclipse.jetty:jetty-http:jar:9.3.10.v20160621",
)
maven_jar(
name = "org_eclipse_jetty_jetty_io",
artifact = "org.eclipse.jetty:jetty-io:jar:9.3.10.v20160621",
)
maven_jar(
name = "org_eclipse_jetty_jetty_security",
artifact = "org.eclipse.jetty:jetty-security:jar:9.3.10.v20160621",
)
maven_jar(
name = "org_eclipse_jetty_jetty_server",
artifact = "org.eclipse.jetty:jetty-server:jar:9.3.10.v20160621",
)
maven_jar(
name = "org_eclipse_jetty_jetty_servlet",
artifact = "org.eclipse.jetty:jetty-servlet:jar:9.3.10.v20160621",
)
maven_jar(
name = "org_eclipse_jetty_jetty_util",
artifact = "org.eclipse.jetty:jetty-util:jar:9.3.10.v20160621",
)
maven_jar(
name = "org_eclipse_jetty_jetty_webapp",
artifact = "org.eclipse.jetty:jetty-webapp:jar:9.3.10.v20160621",
)
maven_jar(
name = "org_eclipse_jetty_jetty_xml",
artifact = "org.eclipse.jetty:jetty-xml:jar:9.3.10.v20160621",
)
maven_jar(
name = "org_eclipse_jetty_jetty_annotations",
artifact = "org.eclipse.jetty:jetty-annotations:jar:9.3.10.v20160621",
)
maven_jar(
name = "org_eclipse_jetty_jetty_jndi",
artifact = "org.eclipse.jetty:jetty-jndi:jar:9.3.10.v20160621",
)
maven_jar(
name = "org_eclipse_jetty_jetty_plus",
artifact = "org.eclipse.jetty:jetty-plus:jar:9.3.10.v20160621",
)
maven_jar(
name = "org_eclipse_jetty_jetty_jmx",
artifact = "org.eclipse.jetty:jetty-jmx:jar:9.3.10.v20160621",
)
maven_jar(
name = "org_eclipse_jetty_jetty_deploy",
artifact = "org.eclipse.jetty:jetty-deploy:jar:9.3.10.v20160621",
)
maven_jar(
name = "org_eclipse_jetty_jetty_rewrite",
artifact = "org.eclipse.jetty:jetty-rewrite:jar:9.3.10.v20160621",
)
maven_jar(
name = "org_eclipse_jetty_jetty_util_ajax",
artifact = "org.eclipse.jetty:jetty-util-ajax:jar:9.3.10.v20160621",
)
maven_jar(
name = "org_eclipse_jetty_jetty_client",
artifact = "org.eclipse.jetty:jetty-client:jar:9.3.10.v20160621",
)
maven_jar(
name = "org_eclipse_jetty_websocket_javax_websocket_client_impl",
artifact = "org.eclipse.jetty.websocket:javax-websocket-client-impl:jar:9.3.10.v20160621",
)
maven_jar(
name = "org_eclipse_jetty_websocket_javax_websocket_server_impl",
artifact = "org.eclipse.jetty.websocket:javax-websocket-server-impl:jar:9.3.10.v20160621",
)
maven_jar(
name = "org_eclipse_jetty_websocket_websocket_api",
artifact = "org.eclipse.jetty.websocket:websocket-api:jar:9.3.10.v20160621",
)
maven_jar(
name = "org_eclipse_jetty_websocket_websocket_client",
artifact = "org.eclipse.jetty.websocket:websocket-client:jar:hybrid:9.3.10.v20160621",
)
maven_jar(
name = "org_eclipse_jetty_websocket_websocket_common",
artifact = "org.eclipse.jetty.websocket:websocket-common:jar:9.3.10.v20160621",
)
maven_jar(
name = "org_eclipse_jetty_websocket_websocket_server",
artifact = "org.eclipse.jetty.websocket:websocket-server:jar:9.3.10.v20160621",
)
maven_jar(
name = "org_eclipse_jetty_websocket_websocket_servlet",
artifact = "org.eclipse.jetty.websocket:websocket-servlet:jar:9.3.10.v20160621",
)
maven_jar(
name = "org_cometd_java_bayeux_api",
artifact = "org.cometd.java:bayeux-api:jar:3.1.0-BETA2",
)
maven_jar(
name = "org_cometd_java_cometd_java_common",
artifact = "org.cometd.java:cometd-java-common:jar:3.1.0-BETA2",
)
maven_jar(
name = "org_cometd_java_cometd_java_client",
artifact = "org.cometd.java:cometd-java-client:jar:3.1.0-BETA2",
)
maven_jar(
name = "org_cometd_java_cometd_java_server",
artifact = "org.cometd.java:cometd-java-server:jar:3.1.0-BETA2",
)
maven_jar(
name = "org_cometd_java_cometd_java_websocket_common_client",
artifact = "org.cometd.java:cometd-java-websocket-common-client:jar:3.1.0-BETA2",
)
maven_jar(
name = "org_cometd_java_cometd_java_websocket_common_server",
artifact = "org.cometd.java:cometd-java-websocket-common-server:jar:3.1.0-BETA2",
)
maven_jar(
name = "org_cometd_java_cometd_java_websocket_javax_client",
artifact = "org.cometd.java:cometd-java-websocket-javax-client:jar:3.1.0-BETA2",
)
maven_jar(
name = "org_cometd_java_cometd_java_websocket_javax_server",
artifact = "org.cometd.java:cometd-java-websocket-javax-server:jar:3.1.0-BETA2",
)
maven_jar(
name = "org_cometd_java_cometd_java_websocket_jetty_client",
artifact = "org.cometd.java:cometd-java-websocket-jetty-client:jar:3.1.0-BETA2",
)
maven_jar(
name = "org_cometd_java_cometd_java_websocket_jetty_server",
artifact = "org.cometd.java:cometd-java-websocket-jetty-server:jar:3.1.0-BETA2",
)
These external dependencies can be assembled into more managable sets via the java_library rule. Here's what these rules look like for jetty and cometd in my project:
java_library(
name = "cometd",
visibility = ["//visibility:public"],
exports = [
"@org_cometd_java_bayeux_api//jar",
"@org_cometd_java_cometd_java_common//jar",
"@org_cometd_java_cometd_java_client//jar",
"@org_cometd_java_cometd_java_server//jar",
"@org_slf4j_slf4j_api//jar",
# These are commented out for the moment
# "@org_cometd_java_cometd_java_websocket_common_client//jar",
# "@org_cometd_java_cometd_java_websocket_common_server//jar",
# "@org_cometd_java_cometd_java_websocket_javax_client//jar",
# "@org_cometd_java_cometd_java_websocket_javax_server//jar",
# "@org_cometd_java_cometd_java_websocket_jetty_client//jar",
],
)
java_library(
name = "jetty",
visibility = ["//visibility:public"],
exports = [
"javax-servlet-api",
"@javax_annotation_javax_annotation_api//jar",
"@org_eclipse_jetty_jetty_annotations//jar",
"@org_eclipse_jetty_jetty_deploy//jar",
"@org_eclipse_jetty_jetty_http//jar",
"@org_eclipse_jetty_jetty_io//jar",
"@org_eclipse_jetty_jetty_jmx//jar",
"@org_eclipse_jetty_jetty_jndi//jar",
"@org_eclipse_jetty_jetty_plus//jar",
"@org_eclipse_jetty_jetty_rewrite//jar",
"@org_eclipse_jetty_jetty_security//jar",
"@org_eclipse_jetty_jetty_server//jar",
"@org_eclipse_jetty_jetty_servlet//jar",
"@org_eclipse_jetty_jetty_util//jar",
"@org_eclipse_jetty_jetty_webapp//jar",
"@org_eclipse_jetty_jetty_xml//jar",
"@org_eclipse_jetty_jetty_util_ajax//jar",
"@org_ow2_asm_asm//jar",
"@org_ow2_asm_asm_commons//jar",
"@org_ow2_asm_asm_tree//jar",
# "@javax_websocket_javax_websocket_api//jar",
# "@org_eclipse_jetty_websocket_websocket_api//jar",
# "@org_eclipse_jetty_websocket_websocket_servlet//jar",
# "@org_eclipse_jetty_websocket_websocket_common//jar",
# "@org_eclipse_jetty_websocket_websocket_client//jar",
# "@org_eclipse_jetty_websocket_javax_websocket_client_impl//jar",
# "@org_eclipse_jetty_websocket_websocket_server//jar",
# "@org_eclipse_jetty_websocket_javax_websocket_server_impl//jar",
],
)
Here's how I am configuring the embedded jetty instance:
@Override
public void configure() throws Exception {
super.execute();
int port = 8080;
// Setup Threadpool
QueuedThreadPool threadPool = new QueuedThreadPool();
threadPool.setMaxThreads(100);
// Server
Server server = new Server(threadPool);
server.setStopAtShutdown(true);
server.setDumpAfterStart(true);
server.setDumpBeforeStop(false);
// Scheduler
server.addBean(new ScheduledExecutorScheduler());
// HTTP Configuration
HttpConfiguration http_config = new HttpConfiguration();
http_config.setSecureScheme("https");
http_config.setSecurePort(8443);
http_config.setOutputBufferSize(32768);
http_config.setRequestHeaderSize(8192);
http_config.setResponseHeaderSize(8192);
http_config.setSendServerVersion(true);
http_config.setSendDateHeader(false);
http_config.addCustomizer(new ForwardedRequestCustomizer());
// Servlet contexts
ServletContextHandler servletContexts = new ServletContextHandler(
ServletContextHandler.SESSIONS);
servletContexts.setContextPath("/k8a");
servletContexts.setResourceBase(System.getProperty("java.io.tmpdir"));
// Add dump servlet
servletContexts.addServlet(DumpServlet.class, "/dump/*");
// Add all preconfigured servlet holders
for (java.util.Map.Entry<ServletMapping,ServletHolder> e : servlets.entrySet()) {
for (String pathSpec : e.getKey().getPathSpecs()) {
servletContexts.addServlet(e.getValue(), pathSpec);
}
}
// Handler Structure
HandlerCollection handlers = new HandlerCollection();
ContextHandlerCollection contexts = new ContextHandlerCollection();
handlers.setHandlers(new Handler[] { contexts, servletContexts, new DefaultHandler() });
server.setHandler(handlers);
// === jetty-jmx.xml ===
MBeanContainer mbContainer = new MBeanContainer(
ManagementFactory.getPlatformMBeanServer());
server.addBean(mbContainer);
// === jetty-http.xml ===
ServerConnector http = new ServerConnector(
server,
new HttpConnectionFactory(http_config));
http.setPort(8080);
http.setIdleTimeout(60000);
server.addConnector(http);
// === jetty-https.xml ===
// SSL Context Factory
SslContextFactory sslContextFactory = new SslContextFactory();
sslContextFactory.setKeyStorePath("etc/ssl/localhost/localhost.jks");
sslContextFactory.setKeyStorePassword("foo-bar-baz");
sslContextFactory.setExcludeCipherSuites(
"SSL_RSA_WITH_DES_CBC_SHA",
"SSL_DHE_RSA_WITH_DES_CBC_SHA",
"SSL_DHE_DSS_WITH_DES_CBC_SHA",
"SSL_RSA_EXPORT_WITH_RC4_40_MD5",
"SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
"SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
"SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA");
// SSL HTTP Configuration
HttpConfiguration https_config = new HttpConfiguration(http_config);
https_config.addCustomizer(new SecureRequestCustomizer());
// SSL Connector
ServerConnector sslConnector = new ServerConnector(
server,
new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()),
new HttpConnectionFactory(https_config));
sslConnector.setPort(8443);
server.addConnector(sslConnector);
// === setup jetty plus ==
Configuration.ClassList.setServerDefault(server).addAfter(
"org.eclipse.jetty.webapp.FragmentConfiguration",
"org.eclipse.jetty.plus.webapp.EnvConfiguration",
"org.eclipse.jetty.plus.webapp.PlusConfiguration");
// === jetty-stats.xml ===
StatisticsHandler stats = new StatisticsHandler();
stats.setHandler(server.getHandler());
server.setHandler(stats);
ConnectorStatistics.addToAllConnectors(server);
// // === Rewrite Handler
// RewriteHandler rewrite = new RewriteHandler();
// rewrite.setHandler(server.getHandler());
// server.setHandler(rewrite);
// === jetty-requestlog.xml ===
NCSARequestLog requestLog = new NCSARequestLog();
requestLog.setFilename("yyyy_mm_dd.request.log");
requestLog.setFilenameDateFormat("yyyy_MM_dd");
requestLog.setRetainDays(90);
requestLog.setAppend(true);
requestLog.setExtended(true);
requestLog.setLogCookies(false);
requestLog.setLogTimeZone("GMT");
RequestLogHandler requestLogHandler = new RequestLogHandler();
requestLogHandler.setRequestLog(requestLog);
handlers.addHandler(requestLogHandler);
// === jetty-lowresources.xml ===
LowResourceMonitor lowResourcesMonitor=new LowResourceMonitor(server);
lowResourcesMonitor.setPeriod(1000);
lowResourcesMonitor.setLowResourcesIdleTimeout(200);
lowResourcesMonitor.setMonitorThreads(true);
lowResourcesMonitor.setMaxConnections(0);
lowResourcesMonitor.setMaxMemory(0);
lowResourcesMonitor.setMaxLowResourcesTime(5000);
server.addBean(lowResourcesMonitor);
server.start();
//server.join();
}
The cometd servlet is configured via a builder interface like so:
servletService.newServletBuilder()
.setName("cometd")
.setClass(CometDServlet.class)
.setAsyncSupported(true)
.setInitOrder(1)
.setMapping("/cometd/*")
.setInitParameter("timeout", "20000")
.setInitParameter("interval", "0")
.setInitParameter("maxInterval", "10000")
.setInitParameter("maxLazyTimeout", "5000")
.setInitParameter("long-polling.multiSessionInterval", "2000")
.setInitParameter("ws.cometdURLMapping", "/cometd/*")
.setInitParameter("maxMessageSize", "131072")
.setInitParameter("long-polling.multiSessionInterval", "2000")
.build();
This builder implementation basically creates a jetty ServletHolder that is added to the ServletContextHandler during jetty configuration.
Any hints what I'm doing wrong here? How can I configure jetty / cometd such that a ServerContainer is configured. Do I need to do this manually? If so, I'd (think) I'd like to use the Jetty implementation and not the JSR one.
Here's the stacktrace I get when I run this test:
import org.cometd.bayeux.client.ClientSession;
import org.cometd.client.BayeuxClient;
import org.cometd.client.transport.ClientTransport;
import org.cometd.client.transport.LongPollingTransport;
import org.eclipse.jetty.websocket.client.WebSocketClient;
import org.cometd.websocket.client.JettyWebSocketTransport;
@Test
public void testWebsocketTransport() throws Exception {
WebSocketClient webSocketClient = new WebSocketClient();
webSocketClient.start();
ClientTransport wsTransport = new JettyWebSocketTransport(null, null, webSocketClient);
HttpClient httpClient = new HttpClient();
httpClient.start();
Map<String, Object> options = new HashMap<String, Object>();
ClientTransport httpTransport = new LongPollingTransport(options, httpClient);
// Create the BayeuxClient
client.handshake();
boolean connected = client.waitFor(1000, BayeuxClient.State.CONNECTED);
assertTrue("client should be connected", connected);
}
java.lang.RuntimeException: javax.servlet.ServletException: java.lang.IllegalArgumentException: Missing WebSocket ServerContainer
at org.eclipse.jetty.servlet.ServletHandler.updateMappings(ServletHandler.java:1546)
at org.eclipse.jetty.servlet.ServletHandler.setServletMappings(ServletHandler.java:1601)
at org.eclipse.jetty.servlet.ServletHandler.addServletWithMapping(ServletHandler.java:1006)
at org.eclipse.jetty.servlet.ServletContextHandler.addServlet(ServletContextHandler.java:437)
Thanks in advance,
Paul