RSocket Java Client to access Binance websocket API - java

I am trying to connect to Binance websocket endpoint using RSocket with Spring, but I am getting the following exception.
java.lang.AssertionError: expectation "consumeNextWith" failed (expected: onNext(); actual: onError(java.nio.channels.ClosedChannelException))
Here is my testing code:
#SpringBootTest
#Slf4j
class RSocketClientIntegrationTest {
private static RSocketRequester requester;
#BeforeAll
public static void setupOnce(#Autowired RSocketRequester.Builder builder) {
// given
requester = builder
.connectWebSocket(URI.create("wss://stream.binance.com:9443/ws"))
.block();
}
#Test
void shouldRetrieveStockPricesFromTheService() {
//when
final Flux<String> aggregatedTradeStream = requester
.route("/bnbbtc#aggTrade")
.retrieveFlux(String.class)
.take(1)
.doOnError(e -> log.error(e.toString()));
// then
StepVerifier.create(aggregatedTradeStream)
.consumeNextWith(response -> {
assertThat(response).isNotNull();
})
.verifyComplete();
}
}
Can I connect straight into a WebSocket endpoint using RSocket or do I have to create a RSocket server that handles the websocket and then from this proxy server I connect to the websocket?

RSocket over WebSocket uses websocket as a transport to carry RSocket payloads. So you can't connect to a raw WebSocket and expect anything to work.
Try testing the above program against an endpoint like
wss://rsocket-demo.herokuapp.com/rsocket
See docs at https://rsocket-demo.herokuapp.com/

Related

How does Spring Boot RSocket detect disconnection?

everyone.
I want to make chatting server using RSocket.
The code below stores user information when the user accesses it.
private final List<RSocketRequester> CLIENTS = new ArrayList<>();
#ConnectMapping
public void onConnect(RSocketRequester reqer) {
log.info("RSocket Connect Mapping Start : reqer {}", reqer.hashCode());
reqer.rsocket()
.onClose()
.doFirst(() -> CLIENTS.add(reqer))
.doOnError(error -> log.info("RSocket Connect Error : error {}", error))
.doFinally(consumer -> {
CLIENTS.remove(reqer);
})
.subscribe();
log.info("RSocket Connect Mapping End : Clients {}", this.CLIENTS.size());
}
spring:
rsocket:
server:
port: 6565
transport: websocket
mapping-path: /rs
I want to get user information when the user disconnects.
Can the RSocket detect when the user disconnects?
help me please.
If you configured rsocket security you can access AuthenticationPrincipal at onConnect().
Simple example
#ConnectMapping
public void onConnect(RSocketRequester requester, #AuthenticationPrincipal Jwt principal) {
requester.rsocket()
.onClose()
.doFirst(() -> {
System.out.println(principal.getSubject());
System.out.println("-----------------CONNNEEEECTED-----------------");
})
.doOnError(error -> {
})
.doFinally(consumer -> {
System.out.println(principal.getSubject());
System.out.println("-----------------DISCONNNNNECTED-----------------");
})
.subscribe();
}

Is it possible to subscribe websocket session on multiple websocket streams and controll subscriptions

Want to realize functionality using Spring Web Flux. All application clients connect to client service via websocket. Then want to subscribe their sessions to websocket streams from another microservices and manage subscriptions according incoming messages.
#Component
public class ReactiveWebSocketHandler implements WebSocketHandler {
#Override
#NotNull
public Mono<Void> handle(#NotNull WebSocketSession session) {
final WebSocketClient client = new ReactorNettyWebSocketClient();
final URI url1 = URI.create("ws://another-service1");
final URI url2 = URI.create("ws://another-service2");
return session.receive()
.doOnNext(message -> {
final String command = message.getPayloadAsText();
if (command.equals("subscribe sevice1")) {
// client.execute(url1, ...
// get flux stream from client invoke and start sending it to current session
} else if (command.equals("subscribe sevice2")) {
// ...
} else if (command.equals("unsubscribe sevice1")) {
// ...
} else if (command.equals("unsubscribe sevice2")) {
// ...
}
})
.then();
}
Is it possible to realize such logic using webflux?

Spring - WebSocket - Origin 'null' is therefore not allowed access

I am currently developing a Web Socket for internal and external requests. However, while trying to test the bidirectional connection via a Chrome command I received the following error:
"Origin 'null' is therefore not allowed access."
Web Socket configuration:
#Configuration
#EnableWebSocketMessageBroker
public class SocketConfig implements WebSocketMessageBrokerConfigurer{
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/bidirectional");
}
public void registerStompEndpoints(StompEndpointRegistry registry) {
//register a new endpoint
registry.addEndpoint("/blueframe").setAllowedOrigins("/*");
registry.addEndpoint("/blueframe").setAllowedOrigins("/*").withSockJS();
}
}
JavaScript connection:
var socket = new SockJS('http://192.168.137.23:8080/blueframe');
stompClient = Stomp.over(socket);
stompClient.connect({}, function (frame) {
setConnected(true);
console.log('Connected: ' + frame);
});
I already tried to see other posts with no results.
First i quitted using Webservices, instead i start using RabbitMQ for a bidirectional communication.
Regarding Web Socket Configuration, i am not the only one having this problem so i found a parcial solution: Downgrade the Spring version or use Socket handlers instead of StompEndpointRegistry interface.

Java based websocket client for Spring based websocket server

I have this websocket server developed using Spring Boot. The server is working fine with a js based client.
#Configuration
#EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
#Override
public void configureMessageBroker(final MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
#Override
public void registerStompEndpoints(final StompEndpointRegistry registry) {
registry.addEndpoint("/chat").withSockJS();
registry.addEndpoint("/chat");
}
}
The controller:
#Controller
public class ChatController {
#MessageMapping("/chat")
#SendTo("/topic/messages")
public OutputMessage send(final Message message) throws Exception {
final String time = new SimpleDateFormat("HH:mm").format(new Date());
return new OutputMessage(message.getFrom(), message.getText(), time);
}
}
This is the server side. Now, for the client, I have created a #ClientEndpoint and when I connect to the URI "ws://localhost:8080/spring-mvc-java/chat", I am able to establish a connection and I can see that the #OnOpen callback of #ClientEndpoint is triggered.
However, it seems that the userSession.getAsyncRemote().sendText(message) does not have any effect. I don't see the response from the server.
I can see the js client is:
Connecting to the server var socket = new SockJS('/spring-mvc-java/chat')
Subscribing stompClient.subscribe('/topic/messages',...
Send the message stompClient.send("/app/chat",...
I am able to achieve the first step. How to achieve the 2nd and the 3rd step in a Java based client?
Thanks
First of all you need a websocketclient and websocketstompclient
WebSocketClient client = new StandardWebSocketClient();
WebSocketStompClient stompClient = new WebSocketStompClient(client);
stompClient.setMessageConverter(new MappingJackson2MessageConverter());
You have to custom handler from StompSessionHandler for
getPayloadType
handleFrame
afterConnected
handleException
handleTransportError
methods
StompSessionHandler sessionHandler = new CustomStompSessionHandler();
You can connect your sockets like this. You can accomplish sending and receiving messages
StompSession stompSession=stompClient.connect("ws://localhost:8080/chat",sessionHandler).get();
This two trigger your websocket topic/messages give you messages through the sockets
/app/chat sending Message to sockets
stompSession.subscribe("/topic/messages", sessionHandler);
stompSession.send("/app/chat", new Message("Hi", "user"));
do you want like this?

Android Client for WebSocket Message Broker

I need to manage a single WebSocket connection in a Android application. For this I implemented a web application where set up a WebSocket Message Broker using Spring, as its quick start.
The problem is that I could not make a connection in my Android application. I'm using Autobahn Android, but I can not connect to subscribe and publish on topics (like SockJS with STOMP).
Server (Spring):
<websocket:message-broker application-destination-prefix="/app">
<websocket:stomp-endpoint path="/ws"></websocket:stomp-endpoint>
<websocket:simple-broker prefix="/topic"/>
</websocket:message-broker>
#Controller
public class MessageController {
#MessageMapping("/ws")
#SendTo("/topic/poc")
public MyEntity proofOfConcept(String message) throws Exception {
return new MyEntity(message);
}
}
Client (Autobahn Android):
final String wsuri = "ws://" + HOSTNAME + ":" + PORT + "/myapp/ws";
mConnection.connect(wsuri, new Wamp.ConnectionHandler() {
#Override
public void onOpen() {
mConnection.subscribe("/myapp/ws/topic/poc", MyEntity.class, new Wamp.EventHandler() {
#Override
public void onEvent(String topicUri, Object event) { }
});
}
#Override
public void onClose(int code, String reason) {
// ERROR: Could not connect to /HOSTNAME...
}
});
I managed to connect using simple handlers of spring instead of message broker, but that limits me to "listen" only one endpoint per connection... Could anyone help me please?
AutobahnAndroid implements WebSocket and WAMP, not STOMP. Different from STOMP, WAMP provides both Publish & Subcribe and Remote Procedure Calls.
For using WAMP, you will need a WAMP Router. You can find client and router implementations for WAMP here.

Categories

Resources