BTCMarkets / API

API
119 stars 30 forks source link

Building a Java Spring WebSocket client #97

Closed surenw closed 5 years ago

surenw commented 6 years ago

Hi,

I'm looking to integrate to the WebSocket API from a Java backend application.

I'm using the Spring Framework SockJSClient but am getting the following error when attempting to connect to your service :

2018-01-07 15:15:07.314 DEBUG [main] org.springframework.web.socket.sockjs.client.RestTemplateXhrTransport : Executing SockJS Info request, url=https://socket.btcmarkets.net/info 2018-01-07 15:15:07.484 DEBUG [main] org.springframework.web.client.RestTemplate : Created GET request for "https://socket.btcmarkets.net/info" 2018-01-07 15:15:07.705 DEBUG [main] org.springframework.web.client.RestTemplate : GET request for "https://socket.btcmarkets.net/info" resulted in 403 (Forbidden); invoking error handler 2018-01-07 15:15:07.711 ERROR [main] org.springframework.web.socket.sockjs.client.SockJsClient : Initial SockJS "Info" request to server failed, url=https://socket.btcmarkets.net

org.springframework.web.client.HttpClientErrorException: 403 Forbidden

Any assistance would be appreciated.

justin-ngin commented 6 years ago

Hi @surenw ,

Can I ask, why are you using the url of https://socket.btcmarkets.net/info? I believe the url to open the connection is just https://socket.btcmarkets.net.

Regards, Justin

surenw commented 6 years ago

Hi,

The /info it seems is a default behaviour of the SockJS protocol : https://stackoverflow.com/questions/35052020/why-does-sockjs-add-a-info-to-a-given-websocket-url-path

I am getting the same issue without "/info".

Perhaps my issue is SockJS - let me try a different way.

duplessisc commented 6 years ago

Hi, @surenw I am having a similar problem but only when I try to join the channel.

I am using io.socket.client. My sample program is connecting and receiving the "connected", "error" and "disconnected" event but whenever I try to connect to the channel by using socket.emit('join",channelName); but I get the java.io.IOException: 403 thrown.

Did you end up finding a different way?

duplessisc commented 6 years ago

Hi guys, I have built a working model as part of the xchangestream API (yet to be published). What I found was that the socket.io client does two things: It uses the XHRPolling class to establish a https connection then upgrades to a websocket. The issue you may be experiencing is that the Polling transport falls over the websocket transport and causes the server side to dump the connection. If you just do a simple connection and wait for the "pong" even (create a listener) then within 5 minutes (so far it has not taken longer) you will see this event, at this point emit the "join" event to the channel/room and you will start receiving data for that channel (took me two weeks to figure this out and it happened by pure coincidence whilst debugging).

I believe there is either a bug in the socket. io engine class (not pausing the polling in time) or the btcmarkets server side is not handling the polling extraneous polling requests properly (i.e. ignoring them whilst performing the upgrade to a websocket).

Hope this helps. Will be sending a pull request to xchangestream once I have completely tested. This will then make connecting a breeze.

Some sample code to show the above:


final Socket socket;
final String channelName = new String("Ticker-BTCMarkets-BTC-AUD");

try {
    socket = IO.socket("https://socket.btcmarkets.net");
    socket.on(Socket.EVENT_PONG, new Emitter.Listener() {
            public void call(Object... args) {
                 LOG.trace("event: {} args: {}", Socket.EVENT_PONG, args);
                if (pongTracker.add() == 1) {   //just a counter to only do this on the first pong
                    LOG.debug("event: {} first pong received, emitting join", Socket.EVENT_PONG);
                         socket.emit("join", "Ticker-BTCMarkets-ETH-AUD");
                         socket.emit("join", "Orderbook_BTCAUD");
                         socket.emit("join", "TRADE_BTCAUD");
                     }
                 }
            });
    socket.on("newTicker", new Emitter.Listener() {
        public void call(Object... args) {
            LOG.trace("event: {} args: {}",  "newTicker", args);
            final ObjectMapper mapper = new ObjectMapper();
              mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

            try {
                BTCMarketsWebSocketTicker ticker = mapper.readValue(args[0].toString(), BTCMarketsWebSocketTicker.class);
                            LOG.debug("Ticker Object created: {}", ticker );
            } catch (IOException e) {
                    e.printStackTrace();
            }
                socket.disconnect();
              }
    });
} catch (URISyntaxException e) {
    e.printStackTrace();
}
socket.connect();
martin-nginio commented 5 years ago

Hi @surenw

Thanks for your feedback.

Our team is releasing a new version of WebSocket feed which improves many aspect of the existing solution so please feel free to take a look at the Java sample client here: https://github.com/ngin-io/websocket-client-java

Also, documentation can be found here: https://github.com/BTCMarkets/API/wiki/WebSocket-v2-%28beta%29

Thanks.

martin-nginio commented 5 years ago

Hi @surenw

I'm closing this ticket and would encourage you also to take a look at our latest API as it delivers several improvements and new features: https://api.btcmarkets.net/doc/v3#section/Introduction

Thanks.

Regards, Martin