The root of the problem is that the WebSocketAddon isn't actually being
registered as Jersey is starting the server before handing back the
server instance. AddOns currently aren't able to be dynamically
registered. So for this, I would recommend logging an issue against
Jersey to have an option
to have server instances not being started automatically.
The obvious thing to do then, as a workaround, is to stop the server,
add the WebSocketAddon, and then start the server again, but it appears
we're too aggressive with the listeners when the server is stopped.
This is something we'll address for the next release.
Here's a workaround that, while ugly, does get you moving forward:
public SimpleServer() throws Exception {
URI uri =
UriBuilder.fromUri("
https://localhost").port(4443).build();
HttpServer webServer;
SSLContextConfigurator sslContext = new
SSLContextConfigurator();
sslContext.setKeyStoreFile(keyStorePath);
sslContext.setKeyStorePass(keyStorePass);
webServer =
GrizzlyServerFactory.createHttpServer(uri, null, true,
new
SSLEngineConfigurator(sslContext).setClientMode(false)
.setNeedClientAuth(false));
NetworkListener l = webServer.getListener("grizzly");
webServer.stop();
webServer.addListener(l);
// add the WebSocketFilter manually
FilterChain c = l.getFilterChain();
final int httpServerFilterIdx =
c.indexOfType(HttpServerFilter.class);
if (httpServerFilterIdx >= 0) {
// Insert the WebSocketFilter right after HttpCodecFilter
c.add(httpServerFilterIdx, new WebSocketFilter());
}
WebSocketEngine.getEngine().register(new
EchoApplication());
webServer.start();
}
> mccluresc_at_gmail.com <mailto:mccluresc_at_gmail.com>
> October 24, 2012 10:52 PM
> Hi,
>
> I am getting an HandshakeException ("Upgrade Failed") when I try to
> test WSS support with grizzly-websockets-2.2.16 and
> grizzly-http-client-1.2.
>
> My test-case is:
> import java.io.FileInputStream;
> import java.net.URI;
> import java.security.KeyStore;
> import java.util.concurrent.ExecutionException;
>
> import javax.net.ssl.SSLContext;
> import javax.net.ssl.TrustManagerFactory;
> import javax.ws.rs.core.UriBuilder;
>
> import org.glassfish.grizzly.http.server.HttpServer;
> import org.glassfish.grizzly.ssl.SSLContextConfigurator;
> import org.glassfish.grizzly.ssl.SSLEngineConfigurator;
> import org.glassfish.grizzly.websockets.HandshakeException;
> import org.glassfish.grizzly.websockets.WebSocketAddOn;
> import org.glassfish.grizzly.websockets.WebSocketEngine;
>
> import com.ning.http.client.AsyncHttpClient;
> import com.ning.http.client.AsyncHttpClientConfig;
> import com.ning.http.client.providers.grizzly.GrizzlyAsyncHttpProvider;
> import com.ning.http.client.websocket.DefaultWebSocketListener;
> import com.ning.http.client.websocket.WebSocket;
> import com.ning.http.client.websocket.WebSocketListener;
> import com.ning.http.client.websocket.WebSocketUpgradeHandler;
> import com.sun.jersey.api.container.grizzly2.GrizzlyServerFactory;
>
> public class WebSocketsTest {
> private static final String keyStorePath =
> WebSocketsTest.class.getResource("keystore").getFile();
> private static final String keyStorePass = "asdfgh";
> private static final String trustStorePath =
> WebSocketsTest.class.getResource("truststore").getFile();
> private static final String trustStorePass = "asdfgh";
>
> public static class SimpleServer {
> public SimpleServer() throws Exception {
> URI uri =
> UriBuilder.fromUri("https://localhost").port(443).build();
> HttpServer webServer;
> SSLContextConfigurator sslContext = new
> SSLContextConfigurator();
> sslContext.setKeyStoreFile(keyStorePath);
> sslContext.setKeyStorePass(keyStorePass);
> webServer =
> GrizzlyServerFactory.createHttpServer(uri, null, true,
> new
> SSLEngineConfigurator(sslContext).setClientMode(false)
>
> .setNeedClientAuth(false));
> webServer.getListener("grizzly")
> .registerAddOn(new
> WebSocketAddOn());
> WebSocketEngine.getEngine().register(new
> StreamApplication());
> webServer.start();
> }
> }
>
> public static class SimpleClient {
> public SimpleClient() throws Exception {
> KeyStore trustStore =
> KeyStore.getInstance("JKS");
> trustStore.load(new
> FileInputStream(trustStorePath), trustStorePass.toCharArray());
> TrustManagerFactory tmf =
> TrustManagerFactory.getInstance("SunX509");
> tmf.init(trustStore);
> SSLContext context =
> SSLContext.getInstance("SSL");
> context.init(null, tmf.getTrustManagers(), null);
> AsyncHttpClientConfig config = new
> AsyncHttpClientConfig.Builder().setSSLContext(context).build();
> AsyncHttpClient c = new AsyncHttpClient(new
> GrizzlyAsyncHttpProvider(config), config);
> WebSocketListener listener = new
> DefaultWebSocketListener() {
> @Override
> public void onMessage(String message) {
> System.out.println("Received message: "
> + message);
> }
> };
> try {
> WebSocketUpgradeHandler handler = new
> WebSocketUpgradeHandler.Builder().addWebSocketListener(listener).build(
> );
> WebSocket socket =
> c.prepareGet("wss://localhost/test").execute(handler).get();
> socket.sendTextMessage("TEST");
> } catch (ExecutionException e) {
> if (e.getCause() instanceof
> HandshakeException) {
> HandshakeException handshake =
> (HandshakeException) e.getCause();
>
> System.out.println("HandshakeException with code: " +
> handshake.getCode() + " and message: " + handshake.getMessage());
> } else
> throw e;
> }
> }
> }
>
> public static void main(String[] args) throws Exception {
> SimpleServer s = new SimpleServer();
> SimpleClient c = new SimpleClient();
> }
> }
>
> My output is:
> Oct 25, 2012 1:47:29 AM
> org.glassfish.grizzly.http.server.NetworkListener start
> INFO: Started listener bound to [localhost:443]
> Oct 25, 2012 1:47:29 AM org.glassfish.grizzly.http.server.HttpServer
> start
> INFO: [HttpServer] Started.
> SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
> SLF4J: Defaulting to no-operation (NOP) logger implementation
> SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for
> further details.
> HandshakeException with code: 1002 and message: Upgrade failed
>
> Any suggestions? Thanks!