How to fix NPE during WebSocketFactory.upgrade() on embedded Jetty 8.1.12

1.6k views Asked by At

I'm trying to run the Cometd websocket server within a self executing war which runs jetty 8.1.12 in embedded mode. I'm able to run all the other web apps this way, but for the websocket case I get this error:

java.lang.NullPointerException
at org.eclipse.jetty.websocket.WebSocketFactory.upgrade(WebSocketFactory.java:238)
at org.eclipse.jetty.websocket.WebSocketFactory.acceptWebSocket(WebSocketFactory.java:396)
at org.cometd.websocket.server.WebSocketTransport.handle(WebSocketTransport.java:157)
at org.cometd.server.CometdServlet.service(CometdServlet.java:166)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:686)

I have read all the other posts and I think this is different.

I have 2 maven projects, one that builds an uber jar containing jetty-server 8.1.12 using maven-shades plugin and the other one that includes that first jar as a war overlay. The overlay puts all the jetty-server classes in the root of the war so it can be run with "java -jar my.war". Because Cometd also needs jetty for websockets, I made double sure all of the dependencies and jars in the WEB-INF/lib dir are all 8.1.12 as well. So there is only one server and its jetty 8.1.12 throughout. All the other posts/questions are because of a non-jetty or non-websocket container or non-http connect, but this is 100% jetty 8.1.12 and the webapp works fine when deployed with a standalone external jetty 8.1.12 instance.

Dependencies for the uberjar from maven-shades (for the embedded jetty self-exe war)

[INFO] com.pgi.pulsar:pulsar-container:jar:1.0-SNAPSHOT
[INFO] +- org.eclipse.jetty:jetty-server:jar:8.1.12.v20130726:compile
[INFO] |  +- org.eclipse.jetty.orbit:javax.servlet:jar:3.0.0.v201112011016:compile
[INFO] |  +- org.eclipse.jetty:jetty-continuation:jar:8.1.12.v20130726:compile
[INFO] |  \- org.eclipse.jetty:jetty-http:jar:8.1.12.v20130726:compile
[INFO] |     \- org.eclipse.jetty:jetty-io:jar:8.1.12.v20130726:compile
[INFO] +- org.eclipse.jetty:jetty-servlet:jar:8.1.12.v20130726:compile
[INFO] |  \- org.eclipse.jetty:jetty-security:jar:8.1.12.v20130726:compile
[INFO] +- org.eclipse.jetty:jetty-webapp:jar:8.1.12.v20130726:compile
[INFO] |  \- org.eclipse.jetty:jetty-xml:jar:8.1.12.v20130726:compile
[INFO] +- org.eclipse.jetty:jetty-servlets:jar:8.1.12.v20130726:compile
[INFO] |  +- org.eclipse.jetty:jetty-client:jar:8.1.12.v20130726:compile
[INFO] |  \- org.eclipse.jetty:jetty-util:jar:8.1.12.v20130726:compile
[INFO] \- junit:junit:jar:4.8.2:test

Here is the code to run embedded jetty:

public class Main {

public static void main(String[] args) throws Exception {
  Server server = new Server();
  SocketConnector connector = new SocketConnector();
  connector.setMaxIdleTime(1000 * 60 * 60);
  connector.setSoLingerTime(-1);
  String portValue = System.getProperty("pulsar.port");
  int port = (portValue != null ? Integer.parseInt(portValue) : 8080);
  connector.setPort(port);
  server.setConnectors(new Connector[]{connector});
  WebAppContext context = new WebAppContext();
  context.setServer(server);
  context.setContextPath("/");

  ProtectionDomain protectionDomain = Main.class.getProtectionDomain();
  URL location = protectionDomain.getCodeSource().getLocation();
  context.setWar(location.toExternalForm());

  server.setHandler(context);
  server.start();
  System.in.read();
  server.stop();
  server.join();

The libs in the webapp WEB-INF/libs:

 jar tvf target/pulsar-websockets-1.0-SNAPSHOT.war | grep WEB-INF/lib/jetty | cut -b 36-100
 WEB-INF/lib/jetty-client-8.1.12.v20130726.jar
 WEB-INF/lib/jetty-continuation-8.1.12.v20130726.jar
 WEB-INF/lib/jetty-http-8.1.12.v20130726.jar
 WEB-INF/lib/jetty-io-8.1.12.v20130726.jar
 WEB-INF/lib/jetty-jmx-8.1.12.v20130726.jar
 WEB-INF/lib/jetty-server-8.1.12.v20130726.jar
 WEB-INF/lib/jetty-util-8.1.12.v20130726.jar
 WEB-INF/lib/jetty-websocket-8.1.12.v20130726.jar
 WEB-INF/lib/jetty-xml-8.1.12.v20130726.jar

The problem feels like it might be related to a class-loading issue between jetty classes like HttpConnection (i read a post about HttpConnection-ThreadLocal and osgi) that are shared between the webapp and the enclosing jetty server. Those classes are in fact in both places, but I can't find a way to separate them since they are needed in both places.

Maybe there is a way to have jetty share its class-loaded classes with the webapp classloader? At this point, I've run out of ideas and don't know what I can try next. What can I do to get this to work?

3

There are 3 answers

2
Jerico Sandhorn On BEST ANSWER

Got it working. After comparing the exact differences between the external jetty server, which works, and the embedded configuration, I was able to get this to work. It required a little trial and error and its not altogether obvious, so I'm sharing what I did for others.

First, the ONLY jetty jar I needed in WEB-INF/lib is this one:

jetty-util-8.1.12.v20130726.jar

All the others I have in the outside for the embedded container. Even though this jar was present in the servers classpath, the app would not load. The only way it would work is if I added only that jar to the /lib dir. That led me to the next error:

java.lang.IllegalStateException: Websockets not supported on blocking connectors
  at org.eclipse.jetty.websocket.WebSocketFactory.upgrade(WebSocketFactory.java:237)
  at org.eclipse.jetty.websocket.WebSocketFactory.acceptWebSocket(WebSocketFactory.java:396)
  at org.cometd.websocket.server.WebSocketTransport.handle(WebSocketTransport.java:157)

Notice it gets past the NPE, which is progress. So then by looking at the log line in the other working jetty server, and a little reading on non-blocking connectors, I used this connector instead of the SocketConector:

import org.eclipse.jetty.server.nio.SelectChannelConnector;
. . .
SelectChannelConnector connector = new SelectChannelConnector();

Those two very simple changes got me up and running.

0
Montaro On

I had the same problem, the application I'm trying to build relying on atmosphere And I was running the app under Jetty-9.

I found the Jetty jars in the war/WEB-INF/lib are:

jetty-continuation-7.6.7.v20120910.jar jetty-http-7.6.7.v20120910.jar jetty-io-7.6.7.v20120910.jar jetty-security-7.6.7.v20120910.jar jetty-server-7.6.7.v20120910.jar jetty-servlet-7.6.7.v20120910.jar jetty-util-7.6.7.v20120910.jar jetty-websocket-7.6.7.v20120910.jar

I switched to Jetty-8 and the problem disappeared.

0
Antoine SAMAHA On

I was getting this error while using tomcat with vaadin 7 and atmosphere. The error had no effect on the good behavior of the application but was popping up every now and then.

java.lang.NullPointerException
at org.eclipse.jetty.websocket.WebSocketFactory.upgrade(WebSocketFactory.java:238)

Solved the problem by removing the gwt-dev-2.7.0.vaadin4.jar from my classpath. It seems I didn't need it anyway.