Gottox socket.io-java-client "Error while handshaking" null pointer exception - java

I'm trying to use socket.io to connect to a streaming server hosted by Geoloqi
I grabbed the Gottox socket.io-java-client code straight from github and didn't make any modifications, except to change the url, but it's giving me the "Error while handshaking" message. The url should work as I got it from the makers of Geoloqi: https://community.geoloqi.com/discussion/19/data-streaming#Item_11 (see the 1st response).
Here is the code, from BasicExample.java
package basic;
/*
* socket.io-java-client Test.java
*
* Copyright (c) 2012, Enno Boland
* socket.io-java-client is a implementation of the socket.io protocol in Java.
*
* See LICENSE file for more information
*/
import io.socket.IOAcknowledge;
import io.socket.IOCallback;
import io.socket.SocketIO;
import io.socket.SocketIOException;
import org.json.JSONException;
import org.json.JSONObject;
public class BasicExample implements IOCallback {
private SocketIO socket;
/**
* #param args
*/
public static void main(String[] args) {
try {
new BasicExample();
} catch (Exception e) {
e.printStackTrace();
}
}
public BasicExample() throws Exception {
socket = new SocketIO();
// socket.connect("http://localhost:8080/", this);
socket.connect("https://subscribe.geoloqi.com:443", this);
// Sends a string to the server.
socket.send("Hello Server");
// Sends a JSON object to the server.
socket.send(new JSONObject().put("key", "value").put("key2",
"another value"));
// Emits an event to the server.
socket.emit("event", "argument1", "argument2", 13.37);
}
#Override
public void onMessage(JSONObject json, IOAcknowledge ack) {
try {
System.out.println("Server said:" + json.toString(2));
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onMessage(String data, IOAcknowledge ack) {
System.out.println("Server said: " + data);
}
#Override
public void onError(SocketIOException socketIOException) {
System.out.println("an Error occured");
socketIOException.printStackTrace();
}
#Override
public void onDisconnect() {
System.out.println("Connection terminated.");
}
#Override
public void onConnect() {
System.out.println("Connection established");
}
#Override
public void on(String event, IOAcknowledge ack, Object... args) {
System.out.println("Server triggered event '" + event + "'");
}
}
Here is the error message:
an Error occured
io.socket.SocketIOException: Error while handshaking
at io.socket.IOConnection.handshake(IOConnection.java:322)
at io.socket.IOConnection.access$7(IOConnection.java:292)
at io.socket.IOConnection$ConnectThread.run(IOConnection.java:199)
Caused by: java.lang.NullPointerException
at io.socket.IOConnection.handshake(IOConnection.java:302)
... 2 more
May 1, 2013 10:02:49 PM io.socket.IOConnection cleanup
INFO: Cleanup
What's going wrong with the code?

Looking at the source code where the exception is coming from (IOConnection.java:302, from the inner NullPointerException), there's this block of code:
if (connection instanceof HttpsURLConnection) {
((HttpsURLConnection) connection)
.setSSLSocketFactory(sslContext.getSocketFactory());
}
Clearly connection must be non-null, otherwise it wouldn't pass the instanceof test. Therefore, sslContext must be null. Since the only other places in that file that sslContext is referenced is in setSslContext() and getSslContext(), the only logical conclusion is that you must call setSslContext() prior to making an SSL connection. SocketIO.setDefaultSSLSocketFactory() also calls through to IOConnection.setSslContext(), so you can call that too instead.
Try this:
SocketIO.setDefaultSSLSocketFactory(SSLContext.getDefault());
socket = new SocketIO();
socket.connect("https://subscribe.geoloqi.com:443", this);
...

I got the same error when I used https://github.com/Gottox/socket.io-java-client to create my Java client. Seems like my server was based on 1.X and this only supports 1.0 (https://github.com/Gottox/socket.io-java-client/issues/101). Solved by using https://github.com/socketio/socket.io-client-java instead.

Related

How to check is a Websocket connection is alive

I have a websocket connection to a server:
import javax.websocket.*;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
#ClientEndpoint
public class WebsocketExample {
private Session userSession;
private void connect() {
try {
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
container.connectToServer(this, new URI("someaddress"));
} catch (DeploymentException | URISyntaxException | IOException e) {
e.printStackTrace();
}
}
#OnOpen
public void onOpen(Session userSession) {
// Set the user session
this.userSession = userSession;
System.out.println("Open");
}
#OnClose
public void onClose(Session userSession, CloseReason reason) {
this.userSession = null;
System.out.println("Close");
}
#OnMessage
public void onMessage(String message) {
// Do something with the message
System.out.println(message);
}
}
After some time, it seems I don't receive any more messages from the server but the onClose method has not been called.
I would like to have a sort of timer that would at least log an error (and at best try to reconnect) if I did not receive any message during the last five minutes for instance. The timer would be reset when I receive a new message.
How can I do this?
Here is what I did. I changed javax.websocket by jetty and implemented a ping call:
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
import org.eclipse.jetty.websocket.client.WebSocketClient;
import java.io.IOException;
import java.net.URI;
import java.nio.ByteBuffer;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
#WebSocket
public class WebsocketExample {
private Session userSession;
private final ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
private void connect() {
try {
SslContextFactory sslContextFactory = new SslContextFactory();
WebSocketClient client = new WebSocketClient(sslContextFactory);
client.start();
client.connect(this, new URI("Someaddress"));
} catch (Exception e) {
e.printStackTrace();
}
}
#OnWebSocketConnect
public void onOpen(Session userSession) {
// Set the user session
this.userSession = userSession;
System.out.println("Open");
executorService.scheduleAtFixedRate(() -> {
try {
String data = "Ping";
ByteBuffer payload = ByteBuffer.wrap(data.getBytes());
userSession.getRemote().sendPing(payload);
} catch (IOException e) {
e.printStackTrace();
}
},
5, 5, TimeUnit.MINUTES);
}
#OnWebSocketClose
public void onClose(int code, String reason) {
this.userSession = null;
System.out.println("Close");
}
#OnWebSocketMessage
public void onMessage(String message) {
// Do something with the message
System.out.println(message);
}
}
Edit: This is just a ping example... I don't know if all servers are supposed to answer by a pong...
Edit2: Here is how to deal with the pong message. The trick was not to listen for String messages, but to Frame messages:
#OnWebSocketFrame
#SuppressWarnings("unused")
public void onFrame(Frame pong) {
if (pong instanceof PongFrame) {
lastPong = Instant.now();
}
}
To manage server time out, I modified the scheduled task as follows:
scheduledFutures.add(executorService.scheduleAtFixedRate(() -> {
try {
String data = "Ping";
ByteBuffer payload = ByteBuffer.wrap(data.getBytes());
userSession.getRemote().sendPing(payload);
if (lastPong != null
&& Instant.now().getEpochSecond() - lastPong.getEpochSecond() > 60) {
userSession.close(1000, "Timeout manually closing dead connection.");
}
} catch (IOException e) {
e.printStackTrace();
}
},
10, 10, TimeUnit.SECONDS));
... and handle the reconnection in the onClose method
You should work around this problem by implementing a heartbeat system which one side sends ping and one side answers with pong. Almost every websocket client and server (as far as I know) support this feature internally. This ping/pong frames could be sent from both sides. I usually implement it on server side because I usually know it has better chance to stay alive than clients (my opinion). If clients dont send back pong for long time, I know the connection is dead. On client side, I check the same: If server has not sent ping messages for a long time, I know connection is dead.
If ping/pong are not implemented in libraries you use (which I think javax websocket has it) you could make your own protocol for that.
The accepted answer uses Jetty specific API. There's a standard API for this:
to send ping: session.getAsyncRemote().sendPing(data)
to send pong (just keep-alive, without answer) session.getAsyncRemote().sendPong(data)
to react to pongs either session.addMessageHandler(handler) where handler implements MessageHandler.Whole<PongMessage> or create a method that is annotated with #OnMessage and has PongMessage param:
#OnMessage
public void onMessage(PongMessage pong) {
// check if the pong has the same payload as ping that was sent etc...
}
Periodic ping/keep-alive sending can be scheduled for example using ScheduledExecutorService just as the accepted answer does, but proper care of synchronization must be taken: if session.getBasicRemote() is used then all calls to the remote need to be synchronized. In case of session.getAsyncRemote() probably all containers except Tomcat handle synchronization automatically: see the discussion in this bug report.
Finally, it's important to cancel the pinging task (ScheduledFuture obtained from executor.scheduleAtFixedRate(...)) in onClose(...).
I've developed a simple WebsocketPingerService to ease up things (available in maven central). Create an instance and store it somewhere as a static var:
public Class WhicheverClassInYourApp {
public static WebsocketPingerService pingerService = new WebsocketPingerService();
// more code here...
}
You can configure ping interval, ping size, failure limit after which sessions should be closed, etc by passing arguments to the constructor.
After that register your endpoints for pinging in onOpen(...) and deregister in onClose(...):
#ClientEndpoint // or #ServerEndpoint -> pinging can be done from both ends
public class WebsocketExample {
private Session userSession;
#OnOpen
public void onOpen(Session userSession) {
this.userSession = userSession;
WhicheverClassInYourApp.pingerService.addConnection(userSession);
}
#OnClose
public void onClose(Session userSession, CloseReason reason) {
WhicheverClassInYourApp.pingerService.removeConnection(userSession);
}
// other methods here
}

Any idea on how to implement the push-based messaging system using CoAP with Java?

I am willing to use CoAP protocol for implementing a java push-based messaging system. Particularly in such a system, a client opens just once a connection with a server (resource) and the server pushes messages (‘non-confirmable’) with a specific rate (e.g., 10 messages per second). However I did not find any existing solution to build the above system.
What I found is the pull-based messaging system. For such case, a client opens a connection with the server and after some time the client sends a GET request. Then, the server handles the request and pushes (as response) a single message to the client.
Hence, for each GET, I have a single message as response -- i.e., a two-way asynchronous interaction.
Does anybody have any idea on how to implement the push-based messaging system using CoAP? Does CoAP supports such a system?
The pull-based messaging system is implemented as follows
Server Part
public class CoapServerPartAsync extends CoapServer {
private static final int COAP_PORT = 8891;
private static int incrementor = 1;
/*
* Application entry point.
*/
public static void main(String[] args) {
try {
// create server
CoapServerPartAsync server = new CoapServerPartAsync();
// add endpoints on all IP addresses
server.addEndpoints();
server.start();
} catch (SocketException e) {
System.err.println("Failed to initialize server: " + e.getMessage());
}
}
/**
* Add endpoints listening on default CoAP port on all IP addresses of all network interfaces.
*
* #throws SocketException if network interfaces cannot be determined
*/
private void addEndpoints() throws SocketException {
InetSocketAddress bindToAddress = new InetSocketAddress("127.0.0.1", COAP_PORT);
addEndpoint(new CoapEndpoint(bindToAddress));
}
/*
* Constructor for a new Hello-World server. Here, the resources
* of the server are initialized.
*/
public CoapServerPartAsync() throws SocketException {
// provide an instance of a Hello-World resource
add(new HelloWorldResource());
}
/*
* Definition of the Hello-World Resource
*/
class HelloWorldResource extends CoapResource {
public HelloWorldResource() {
// set resource identifier
super("helloWorld");
// set display name
getAttributes().setTitle("Hello-World Resource");
}
#Override
public void handleGET(CoapExchange exchange){
// respond to the request
System.out.println("Push [Hello World!"+(incrementor)+"]");
exchange.respond("Hello World!"+(incrementor));
incrementor++;
}
}
}
Client Part
public class CoapClientPartAsync {
// static boolean getResponse = false;
public static void main(String args[]) {
CoapClient client = new CoapClient("coap://127.0.0.1:8891/helloWorld").useNONs();
while(true){
CoapObserveRelation relation = client.observe(
new CoapHandler() {
#Override public void onLoad(CoapResponse response){
String content = response.getResponseText();
System.out.println("NOTIFICATION: " + content);
}
#Override public void onError() {
System.err.println("OBSERVING FAILED (press enter to exit)");
}
});
try {
Thread.sleep(1000);
}catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

jquery signalr client works- but in java it cannot be made to work

We have a SignalR hub. The following jQuery code connects and properly processes SignalR client "call" events successfully on cordova.
var connectionURL = "https://SOMEURL.azurewebsites.net/message";
connection = $.connection(connectionURL);
connection.start().done(function () {
console.log("Connected to hub again");
});
connection.disconnected(function () {
setTimeout(function () {
connection.start().done(function () {
console.log("Disconnected and Connected to hub again");
});
}, 5000);
});
connection.stateChanged(function (change) {
if (change.newState == $.signalR.connectionState.reconnecting) {
}
else if (change.newState == $.signalR.connectionState.connected) {
}
else if (change.newState == $.signalR.connectionState.disconnected) {
}// else if
});
connection.received(function (data) {
connectId = connection.id + "";
console.log("onDeviceReady run");
// call the function to parse the data
if (data.PayloadType == "Dispatch") {
dataDispatch(data);
}
if (data.PayloadType == "ConnectionAcknowledge") {
sendConnectionAcknowledge(data);
}
});
However when I try to emulate this code in java android using the SignalR Java Client, I get a lot of log output (tonnes), and no connection ever finishes. it gets as far as the debug at line awaitConnection.get(); and never prints the second line of debug, instead it prints endless (thousands) of lines of semi gibberish (it's not piping, it's like it's some sort of "SSL handshake" but it's not doing anything but logging the same thing repeatedly, very odd) anyway it never runs the 2nd line of "my" debug
package com.some.thing;
import android.util.Log;
import java.util.concurrent.ExecutionException;
import microsoft.aspnet.signalr.client.Platform;
import microsoft.aspnet.signalr.client.SignalRFuture;
import microsoft.aspnet.signalr.client.http.android.AndroidPlatformComponent;
import microsoft.aspnet.signalr.client.hubs.HubConnection;
import microsoft.aspnet.signalr.client.hubs.HubProxy;
import microsoft.aspnet.signalr.client.hubs.SubscriptionHandler1;
public class SignalRClient {
public static void startConnection() {
Platform.loadPlatformComponent(new AndroidPlatformComponent());
String host = "https://SOMEURL.azurewebsites.net/message";
HubConnection connection = new HubConnection(host);
HubProxy hub = connection.createHubProxy( "IDoNoHaveThisNorKnowIt" );
SignalRFuture<Void> awaitConnection = connection.start();
try {
Log.v("CONANSignalR :=", "CONNECTING");
awaitConnection.get();
Log.v("CONANSignalR :=", "CONNECTED");
} catch (InterruptedException e) {
// Handle ...
} catch (ExecutionException e) {
// Handle ...
}
hub.on("IDoNotKnowThisEither", new SubscriptionHandler1<String>(){
#Override
public void run( String status ){
Log.v("CONANDispatch :=", status);
}
}, String.class);
}
}
Can anyone help me translate the working, jQuery SignalR client code into usable java client code? I don't have any information on the hub so I cannot know the proxy or the function names, I'd like to see everything (like the jQuery).
EDIT
To test things, I have altered my original jquery code it use to say
console.log("onDeviceReady run");
now it says
console.log("SignalR Raw Data:" + JSON.stringify(data));
when I do this this is what the jquery returns
SignalR Raw Data:{"ConnectionId":"9c4b4ba5-cb6e-4dcb-8df9-069cbf749873","OrderId":null,"SenderId":null,"PayloadType":"ConnectionAck","Message":"Welcome, you are connected to the Hub!","Payload":null,"Initiator":"HUB","Version":null}
however none of this appears inside the java equivalent
connection.received(new MessageReceivedHandler() {
#Override
public void onMessageReceived(JsonElement json) {
System.out.println("RAW received message: " + json.toString());
// ADD HANDLING OF RECEIVED IN HERE
}
});
i.e. the text "RAW received message:" doesn't appear at all
Since you don't know hub name, you have to use handle events on connection object directly (like you do in js client).
Here is sample code which could get you started (note, this is not tested, written just from top of my head):
public static void startConnection() {
Platform.loadPlatformComponent(new AndroidPlatformComponent());
String host = "https://SOMEURL.azurewebsites.net/message";
HubConnection connection = new HubConnection(host);
// subscribe to received - equal to `connection.received(function (data)` from javascript
connection.received(new MessageReceivedHandler() {
#Override
public void onMessageReceived(JsonElement json) {
System.out.println("RAW received message: " + json.toString());
// ADD HANDLING OF RECEIVED IN HERE
}
});
// equal to `connection.disconnected(function ()` from javascript
connection.closed(new Runnable() {
#Override
public void run() {
// ADD CODE TO HANDLE DISCONNECTED EVENT
}
});
// equal to `connection.stateChanged(function (change)`
connection.stateChanged(new StateChangedCallback() {
#Override
public void stateChanged(ConnectionState oldState, ConnectionState newState) {
// ADD CODE TO HANDLE STATE CHANGES
}
});
// start the connection
connection.start()
.done(new Action<Void>() {
#Override
public void run(Void obj) throws Exception {
System.out.println("Connected");
}
});
}
Also, I recommend you to check sample chat client for java which can be found here: https://github.com/SignalR/java-samples/blob/master/signalr-sample-chat/src/microsoft/aspnet/signalr/samples/chat/Program.java
Most of code I posted is based on that one.

Pusher: Decrease timeout for connection state

I'm currently experimenting with websockets using the Pusher library for Java.
Pusher automatically changes its connection state from CONNECTED to DISCONNECTED if the internet connection is lost. However, this only seems to happen after 150 seconds of being disconnected. This is very unfortunate as in those 150s, a lot of messages can get lost, and a de facto old message can still be seen as the most up-to-date.
How can I know if the last received message is the most up-to-date? Or is there any way to decrease the timeout for the connection state?
Here is the pusher code I'm using:
import com.pusher.client.Pusher;
import com.pusher.client.channel.Channel;
import com.pusher.client.channel.ChannelEventListener;
import com.pusher.client.channel.SubscriptionEventListener;
import com.pusher.client.connection.ConnectionEventListener;
import com.pusher.client.connection.ConnectionState;
import com.pusher.client.connection.ConnectionStateChange;
public class Testing {
public static void main(String[] args) throws Exception {
// Create a new Pusher instance
Pusher pusher = new Pusher("PusherKey");
pusher.connect(new ConnectionEventListener() {
#Override
public void onConnectionStateChange(ConnectionStateChange change) {
System.out.println("State changed to " + change.getCurrentState() +
" from " + change.getPreviousState());
}
#Override
public void onError(String message, String code, Exception e) {
System.out.println("There was a problem connecting!");
}
}, ConnectionState.ALL);
// Subscribe to a channel
Channel channel = pusher.subscribe("channel", new ChannelEventListener() {
#Override
public void onSubscriptionSucceeded(String channelName) {
System.out.println("Subscribed!");
}
#Override
public void onEvent(String channelName, String eventName, String data) {
System.out.println("desilo se");
}
});
// Bind to listen for events called "my-event" sent to "my-channel"
channel.bind("my-event", new SubscriptionEventListener() {
#Override
public void onEvent(String channel, String event, String data) {
System.out.println("Received event with data: " + data);
}
});
while(true){
try {
Thread.sleep(1000);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
}
}
Just found the answer: Initiate Pusher-object with PusherOptions-object.
Here is the PusherOptions-class: http://pusher.github.io/pusher-java-client/src-html/com/pusher/client/PusherOptions.html
Here is a simple example how I decreased my connection-timeout from 150s to 15s:
// Define timeout parameters
PusherOptions opt = new PusherOptions();
opt.setActivityTimeout((long)10000L);
opt.setPongTimeout((long)5000L);
// Create a new Pusher instance
Pusher pusher = new Pusher(PUSHER_KEY, opt);
ActivityTimeout defines how often a ping is sent out to check the connectivity, PongTimeout defines the waiting time until a response from the ping-signal is expected.
The minimum ActivityTimeout is 1000ms, however such a low value is strongly discouraged by Pusher, probably to decrease the server-traffic.

tomcat websocket servlet listening port

I'm trying to write a servlet that uses org.apache.catalina.websocket.WebSocketServlet. I've found an example of websocket chat, but I can't figure out how can I specify the listening port for a websocket server (which is implemented in this servlet)? For example I need to listen for clients connection on port 11337. But how I can express this?
OK, here is the (simplified) code:
public class TestServlet extends WebSocketServlet {
private static final Logger logger = LoggerFactory.getLogger(TestServlet.class);
public TestServlet() {
logger.error("Initializing TestServlet");
}
#Override
protected StreamInbound createWebSocketInbound(String subProtocol, HttpServletRequest request) {
logger.error("New WS connection, subProtocol=" + subProtocol + ", request=" + request.getRequestURL());
return new TestConnection();
}
private class TestConnection extends MessageInbound {
#Override
protected void onBinaryMessage(ByteBuffer byteBuffer) throws IOException {
logger.error("onBinaryMessage");
}
#Override
protected void onTextMessage(CharBuffer charBuffer) throws IOException {
logger.error("onBinaryMessage: " + charBuffer);
sendMessage("Test message");
}
public void sendMessage(String message) {
WsOutbound outbound = this.getWsOutbound();
CharBuffer cb = CharBuffer.wrap(message);
try {
outbound.writeTextMessage(cb);
} catch (IOException e) {
logger.error("failed to write outbound");
}
}
}
}
I can't find where and how I can set listening port. Official websocket documentation also doesn't help much.
So I guess it can be set somewhere in servlet settings, but can't find where.
Does anyone have any ideas?
WebSocket is designed to work over HTTP protocol and so it won't have different listening port like normal TCP Socket but it use the same server port that it deployed on.
so here in your case, if you are using tomcat server than websocket may use port 8080 (if you haven't modified explicitly) for communication. You may need to override onOpen and onClose methods of MessageInbound class to get notified on Connection established and connection close. Refer below sample code for more details.
public class IncomingMessageHandler extends MessageInbound {
private WsOutbound myoutbound;
public IncomingMessageHandler() {
}
#Override
public void onOpen(WsOutbound outbound) {
logger.info("Open Client.");
this.myoutbound = outbound;
}
#Override
public void onClose(int status) {
logger.info("Close Client.");
}
/**
* Called when received plain Text Message
*/
#Override
public void onTextMessage(CharBuffer cb) throws IOException {
}
/**
* We can use this method to pass image binary data, eventually !
*/
#Override
public void onBinaryMessage(ByteBuffer bb) throws IOException {
}
public synchronized void sendTextMessage(String message) {
try {
CharBuffer buffer = CharBuffer.wrap(message);
this.getMyoutbound().writeTextMessage(buffer);
this.getMyoutbound().flush();
} catch (IOException e) {
}
}
/**
* Set timeout in milliseconds, -1 means never
*/
#Override
public int getReadTimeout() {
return -1;
}
public WsOutbound getMyoutbound() {
return myoutbound;
}
public void setMyoutbound(WsOutbound myoutbound) {
this.myoutbound = myoutbound;
}
}

Categories

Resources