Search code examples
javawebsocketglassfishipv6tyrus

My Websocket takes forever to connect


UPDATE It seems that in org.glassfish.tyrus.core.BaseContainer in the constructor, these two lines run super slow:

this.managedExecutorService = lookupManagedExecutorService();
this.managedScheduledExecutorService = lookupManagedScheduledExecutorService();

What is the deal with the mention of Android in the comments of both methods, am I using the wrong code for Java that is aimed at Desktops?


I am using the code exactly as it is from:

Tyrus Websocket Documentation: 1.1.2 Client Endpoint

Somehow it takes about 10 seconds to connect, specifically at this line when I run Eclipse's debugger:

ClientManager client = ClientManager.createClient();

Could it be related to this? Potentially similar Stack Overflow Question

I am really lost, I feel like I am a rare outlier trying to use websockets with a Java client as opposed to a browser with Javascript.


Solution

  • So the cause of the troubles is the initialization of an InitialContext by Tyrus in order to re-use a (scheduled) executor service if one is available. Normally this fails fast if none is available (and this is logged as a debug-message, see further on), but in this case it failed only after trying to initialize a INITIAL_CONTEXT_FACTORY that could not work. To override this behavior, call
    System.setProperty(javax.naming.InitialContext.INITIAL_CONTEXT_FACTORY, "javax.naming.spi.InitialContextFactory")
    before creating a client. The initial InitialContext will then try to create an instance of an interface and this fails fast.

    The problems could probably be found earlier with verbose logging. Tyrus does not do a lot of (debug) logging but in this case a setup with jul over logback could have shown an early indication of the underlying troubles. As a general rule: always ensure you can view trace/debug logging when running into weird problems.

    As for the Android comments in the source code: this is just the platform where the incompatability with the "JDK8 compact2 profile" was noticed and it was resolved by not importing the javax.naming.InitialContext class directly (since apparently it does not exist in the compact2 profile) but using reflection instead (see also TYRUS-242).

    If you are creating a purely Java Websocket client, consider using the JDK 7 client. The JDK 7 client bundle (org.glassfish.tyrus:tyrus-container-jdk-client:1.10) is considerably smaller as the default one (org.glassfish.tyrus.bundles:tyrus-standalone-client:1.10).

    I also felt like I an outlier when I started using websockets with a Java client (I choose the Jetty websocket client API implementation). I also started using Tomcat embedded more (for example basic-jsp-embed). When combining these techniques, you get a powerful ("full duplex") network solution (more akin to peer-to-peer instead of client-server). Hopefully it will catch on.
    One caveat to remember is that some firewalls will drop connections (that look like http-connections) after 30 minutes (even when the connection is in use). So for a stable connection, make sure the client sends regular ping-messages to ensure a healthy connection and creates a new connection within/every 30 minutes.