WebSocket Client Reconnect

Another new feature was recently added to Tyrus (Java API for WebSocket Reference Implementation): Client ReconnectHandler. Some client use cases require almost persistent client-to-server connection and don’t really care about lower layer issues, like unstable internet connection.

Tyrus Client now include possibility of registering ReconnectHandler, which can help with these scenarios. Let’s see ReconnectHandler declaration:

1
2
3
4
5
6
7
8
9
10
public class ReconnectHandler {
public boolean onDisconnect(CloseReason closeReason) {
return false;
}
public boolean onConnectFailure(Exception exception) {
return false;
}
}

Method onDisconnect is executed whenever client endpoint @OnClose annotated method is called, method onConnectFailure is executed whenever client has some troubles connecting to remote endpoint (network issues, server returning HTTP Status 500, …). Both methods can return boolean value, which indicates whether client should try to reconnect or not.

It is perfectly fine to wait in any of these methods for some time – I would recommend it for onConnectFailure, because there usually is some reason for network failure and repeating requests without any delay can prolong them or even make them worse. Also I would recommend include some kind of counter, which would set the number of reconnect attempts.

Example implementation could look like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
ClientManager client = ClientManager.createClient();
ClientManager.ReconnectHandler reconnectHandler = new ClientManager.ReconnectHandler() {
private int counter = 0;
@Override
public boolean onDisconnect(CloseReason closeReason) {
counter++;
if (counter <= 3) {
System.out.println("### Reconnecting... (reconnect count: " + counter + ")");
return true;
} else {
return false;
}
}
@Override
public boolean onConnectFailure(Exception exception) {
counter++;
if (counter <= 3) {
System.out.println("### Reconnecting... (reconnect count: " + counter + ") " + exception.getMessage());
// Thread.sleep(...) or something other "sleep-like" expression can be put here - you might want
// to do it here to avoid potential DDoS when you don't limit number of reconnects.
return true;
} else {
return false;
}
}
};
client.getProperties().put(ClientManager.RECONNECT_HANDLER, reconnectHandler);
client.connectToServer(...)

Comments:

Hi Pavel
you said "Method onDisconnect is executed whenever client endpoint @OnClose annotated method is called". But is it also called when the server machine crashes, is it also called when the JVM process on the server crahsed and it it also called when the network crashes (hardware cable or software)? In all these use cases the @OnClose method is not called. I could try the implementation but would also like to know how it "should" work from a specification perspective.

Regards
Alain

Posted by guest on April 03, 2014 at 10:35 AM CEST #

Hi Alain,

in all of cases mentioned, @OnClose should be called on client side - when TCP connection is broken, client needs to be notified - @OnClose is called and CloseReason should be 1006: Closed abnormally. See https://tools.ietf.org/html/rfc6455#section-7.4.1 for more details.

If you have any testcase which proves me wrong, please retest it with recent Tyrus version (1.5 or 1.6-SNAPSHOT) and if you can still reproduce it, file a new issue at https://java.net/jira/browse/TYRUS and attach that testcase or at least description which would allow me to recostruct it.

Thanks!
Pavel

Posted by Pavel on April 03, 2014 at 10:41 AM CEST #

Hi Pavel,

I got this to work perfectly on the desktop with Tyrus 1.9 and prior versions as is described here: https://tyrus.java.net/documentation/1.9/user-guide.html#d0e1311. On Android 4.4.4 & 5.0 however, nothing happens (its as if there are no handlers). Is there some extra configuration required somewhere?

Thanks,
Alan

Posted by Alan on December 18, 2014 at 12:15 AM CET #

Hi Alan,

seems like you are not the only one who is experiencting this issue - its tracked as https://java.net/jira/browse/TYRUS-391

Thanks for reporting it!
Pavel

Posted by Pavel on January 05, 2015 at 10:31 AM CET #

I am using tyrus-standalone-client-1.10.jar, in my client java websocket application and websocket server runs in tomcat 8 server. I have a use case where I need to use OnClose method at client app for some task, also I need to use this onDisconnect and onConnectFailure methods to reconnect.

I have 3 questions:

1. Will this onDisconnect and onConnectFailure methods will connect to same session? Since I need to continue my communication again between different websockets clients.

2. In websockets to communicate between clients we use map to store the session. Since the server is down and later gets reconnected, this data inside the map is lost. Do we have any approach to keep hold this Map?

3. Do we have any mechanism to stop triggering OnClose method while reconnection? Why because in my case, this method has some task which should not run on re-connect.

4. ClientManager.RECONNECT_HANDLER is deprecated. Do we have any alternative for this?

Posted by guest on May 14, 2015 at 06:26 PM CEST #

Hey Guest,

1) no. Once the connection is broken, WebSocket session is lost. This cannot be easily solved or fixed, since it is a requirement from RFC 6455 - WebSocket protocol. WebLogic Server does have a feature which stores some data from previous session and puts them into newly created one, you could use that (or implement something similar, it is not that hard to do).

2) Not sure where the map is and whether you mean WebSocket Session or Servlet Session. Anyway, on server side, @OnClose will be invoked, so you can store your WebSocket Session related data somewhere else and make them accessible to reconnecting client.

3) No, and we don't even want to do that. @OnClose is tied to RFC 6455 - it signals that WebSocket connection is lost with appropriate CloseCode. That will happen no matter what. You can ignore it if you want, put it into some other cache where it can be picked up when @OnOpen is called again etc..

4) See javadoc, @deprecated comment:

/**
* Property usable in {@link #getProperties()}.
* <p/>
* Value must be {@link org.glassfish.tyrus.client.ClientManager.ReconnectHandler} instance.
*
* @deprecated please use {@link org.glassfish.tyrus.client.ClientProperties#RECONNECT_HANDLER}.
*/
@SuppressWarnings("UnusedDeclaration")
public static final String RECONNECT_HANDLER = ClientProperties.RECONNECT_HANDLER;

Regards,
Pavel

Posted by Pavel on May 14, 2015 at 06:36 PM CEST #

Post a Comment:
  • HTML Syntax: NOT allowed
About

Pavel Bucek-Oracle

Search

Categories
Archives
« August 2015
SunMonTueWedThuFriSat
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
     
Today