I have a websocket setup using javax.websocket, it seems to connect, but wont work, it keeps giving a java.lang.IllegalStateException: Binary message handler not found
final WebSocketContainer webSocketContainer = ContainerProvider.getWebSocketContainer();
Session session = webSocketContainer.connectToServer(new Endpoint() {
#Override
public void onError(Session session, Throwable thr) {
// TODO Auto-generated method stub
super.onError(session, thr);
System.out.println("checkerWindow.DownloadMessages().new Endpoint() {...}.onError()");
thr.printStackTrace();
}
#Override
public void onOpen(Session session, EndpointConfig EndpointConfig) {
System.out.println("checkerWindow.DownloadMessages().new Endpoint() {...}.onOpen()");
try {
//send login details
//login:<deviceid>:<secret>\n
session.getBasicRemote().sendText("login:"+deviceid+":"+secret+"\n");
}
catch(Exception ex){
System.err.println("Exception=" + ex.toString());
ex.printStackTrace();
}
}
#OnMessage
public void onMessage(String message) {
System.out.println("Received message: "+message);
}
#Override
public void onClose(Session session, CloseReason closeReason) {
System.out.println("checkerWindow.DownloadMessages().new Endpoint() {...}.onClose()");
}
}, ClientEndpointConfig.Builder.create().build(), URI.create("wss://client.pushover.net/push"));
I have tried the ByteBuffer but the compiler doesnt like that.
You should define a method to receive binary messages. For example,
#OnMessage
public void onMessage(byte[] message) {
......
}
See the JavaDoc of OnMessage annotation for details.
Related
I have created a spring boot Messaging endpoint and need to create an android chat app and am wondering how I can manage to call those endpoints using okttp Websocket client which does not seem to have a way to add api endpoints like this javascript code.
And here is my spring boot endpoints
#Configuration
#EnableWebSocketMessageBroker
public class WebMessageConfig implements WebSocketMessageBrokerConfigurer {
#Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker( "/user");
config.setApplicationDestinationPrefixes("/app");
config.setUserDestinationPrefix("/user");
}
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry
.addEndpoint("/ws")
.withSockJS()
.setAllowedOrigins("*");
}
}
And here is my OkHttp client code
public class StompWs {
private String SERVER_PATH="ws://mydomain.com:8443/MyContex/ws";
public static void main(String[] args) {
try {
new StompWs().run();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private WebSocket webSocket;
public void run() throws Exception {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(SERVER_PATH).build();
webSocket = client.newWebSocket(request, new SocketListener());
}
private String getData()
{
MessageModel message=new MessageModel();
message.setMessage("Hello");
message.setRecipientId("1");
message.setSenderId("2");
return new Gson().toJson(message);
}
private class SocketListener extends WebSocketListener {
#Override
public void onOpen(WebSocket webSocket, Response response) {
super.onOpen(webSocket, response);
try {
webSocket.send(getData());
/**I need equivalent of this
stompClient.subscribe(
"/user/1/queue/messages",// I need java code to do this
onMessageReceived
*/
}
catch(Exception e)
{
e.printStackTrace();
}
System.out.println("succesfully connected:"+response.toString());//this message execute well
}
#Override
public void onMessage(WebSocket webSocket, String text) {
super.onMessage(webSocket, text);
System.out.println("on message:"+text);
}
#Override
public void onFailure(WebSocket webSocket, Throwable t,
Response response) {
// TODO Auto-generated method stub
super.onFailure(webSocket, t, response);
System.out.println("on message:"+t.toString());
}
}
}
I'm trying to set up a simple application using Spring and websockets and have problem setting up the connection.
I have looked around for examples but almost all searches lead to the chat sample which is not what I am trying to do.
My app is a task/monitoring scenario. I want to be able to send a request to the server and then monitor the progress
of the task on the same connection.
I have seen the chat sample, portfolio sample and various other comments on SO but I'm not sure what I'm missing.
I'm new to Spring and websockets.
The logging appears to show a successful connection for the /info path but then the call to stompClient.connect() fails to return.
14:02:26.330 [main] DEBUG org.springframework.web.socket.sockjs.client.RestTemplateXhrTransport - Executing SockJS Info request, url=http://localhost:9080/Vault713MQServer/websocket/info
14:02:26.480 [main] DEBUG org.springframework.web.client.RestTemplate - Created GET request for "http://localhost:9080/Vault713MQServer/websocket/info"
14:02:26.559 [main] DEBUG org.springframework.web.client.RestTemplate - GET request for "http://localhost:9080/Vault713MQServer/websocket/info" resulted in 200 (OK)
14:02:26.578 [main] DEBUG org.springframework.web.socket.sockjs.client.WebSocketTransport - Starting WebSocket session url=ws://localhost:9080/Vault713MQServer/websocket/369/ee89fc87489842af868c0f0452aacf13/websocket
14:02:26.578 [main] DEBUG org.springframework.web.socket.client.standard.StandardWebSocketClient - Connecting to ws://localhost:9080/Vault713MQServer/websocket/369/ee89fc87489842af868c0f0452aacf13/websocket
14:02:26.693 [WebSocketClient-AsyncIO-1] DEBUG org.springframework.web.socket.sockjs.client.WebSocketClientSockJsSession - Processing SockJS open frame in WebSocketClientSockJsSession[id='ee89fc87489842af868c0f0452aacf13, url=ws://localhost:9080/Vault713MQServer/websocket]
14:02:26.693 [WebSocketClient-AsyncIO-1] DEBUG org.springframework.messaging.simp.stomp.DefaultStompSession - Connection established in session id=07e2d0cc-6f99-95d5-7014-614aad3e0f13
If I connect to 'http://localhost:9080/Vault713MQServer/websocket/info' in a browser it returns:
{"entropy":1894449220,"origins":["*:*"],"cookie_needed":true,"websocket":true}
On the server side I have:
/* WebSocketConfig.java */
#Configuration
#EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer
{
#Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry)
{
registry.addHandler(myHandler(), "/websocket").withSockJS();
}
#Bean
public ServerHandler myHandler()
{
return new ServerHandler();
}
}
/* ServerHandler.java */
public class ServerHandler extends TextWebSocketHandler
{
private final Logger logger = Logger.getLogger(this.getClass().getName());
#Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
// TODO Auto-generated method stub
logger.log(Level.INFO, "Connection clodes with websocket server: session id {0}", session.getId());
super.afterConnectionClosed(session, status);
}
#Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
// TODO Auto-generated method stub
logger.log(Level.INFO, "Connected user with websocket server: session id {0}", session.getId());
super.afterConnectionEstablished(session);
}
#Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
// TODO Auto-generated method stub
super.handleMessage(session, message);
}
#Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
// TODO Auto-generated method stub
super.handleTransportError(session, exception);
}
}
On the client side I have:
/* Clientside - Vault713MQClient.java */
public class Vault713MQClient
{
static public class MyStompSessionHandler
extends StompSessionHandlerAdapter
{
private String userId;
public MyStompSessionHandler(String userId)
{
this.userId = userId;
}
private void showHeaders(StompHeaders headers)
{
for (Map.Entry<String, List<String>> e : headers.entrySet())
{
System.err.print(" " + e.getKey() + ": ");
boolean first = true;
for (String v : e.getValue())
{
if (!first)
{
System.err.print(", ");
}
System.err.print(v);
first = false;
}
System.err.println();
}
}
private void sendJsonMessage(StompSession session)
{
session.send("/websocket", "hello from spring");
}
private void subscribeTopic(String topic, StompSession session)
{
session.subscribe(topic, new StompFrameHandler()
{
#Override
public Type getPayloadType(StompHeaders headers)
{
return String.class;
}
#Override
public void handleFrame(StompHeaders headers,
Object payload)
{
System.err.println(payload.toString());
}
});
}
#Override
public void afterConnected(StompSession session,
StompHeaders connectedHeaders)
{
System.err.println("Connected! Headers:");
showHeaders(connectedHeaders);
// subscribeTopic("/topic/messages", session);
// sendJsonMessage(session);
}
}
public static void main(String args[]) throws Exception
{
WebSocketClient simpleWebSocketClient = new StandardWebSocketClient();
List<Transport> transports = new ArrayList<>(1);
transports.add(new WebSocketTransport(simpleWebSocketClient));
SockJsClient sockJsClient = new SockJsClient(transports);
WebSocketStompClient stompClient = new WebSocketStompClient(sockJsClient);
stompClient.setMessageConverter(new MappingJackson2MessageConverter());
String url = "ws://localhost:9080/Vault713MQServer/websocket";
String userId = "spring-" + ThreadLocalRandom.current().nextInt(1, 99);
StompSessionHandler sessionHandler = new MyStompSessionHandler(userId);
StompSession session = stompClient.connect(url, sessionHandler).get();
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
for (;;)
{
System.out.print(userId + " >> ");
System.out.flush();
String line = in.readLine();
if (line == null)
{
break;
}
if (line.length() == 0)
{
continue;
}
session.send("/websocket", line);
// ClientMessage msg = new ClientMessage(userId, line);
// session.send("/app/chat/java", msg);
}
}
}
Can anyone see what I have done wrong or does anyone have a simple complete example of what I am trying to do?
Many thanks.
KCM
I created a basic selfhosted SignalR server with the following code:
class Program
{
static void Main(string[] args)
{
// This will *ONLY* bind to localhost, if you want to bind to all addresses
// use http://*:8080 to bind to all addresses.
// See http://msdn.microsoft.com/en-us/library/system.net.httplistener.aspx
// for more information.
string url = "http://localhost:8080";
using (WebApp.Start(url))
{
Console.WriteLine("Server running on {0}", url);
Console.ReadLine();
}
}
}
class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseCors(CorsOptions.AllowAll);
app.MapSignalR();
}
}
public class MyHub : Hub
{
public void Send(string name, string message)
{
Clients.All.addMessage(name, message);
}
}
Which is taken from: https://learn.microsoft.com/en-us/aspnet/signalr/overview/deployment/tutorial-signalr-self-host and works with the Javascript client.
I am now trying to create a Java client and got the following code that is simply supposed to send a message to the server:
String host = "http://localhost:8080";
HubConnection connection = new HubConnection(host);
HubProxy proxy = connection.createHubProxy("MyHub");
connection.start();
try {
System.out.println("Sendng message...");
proxy.invoke( "Send", "Client", "Hello world!" ).get();
System.out.println("Message sent!");
} catch (InterruptedException e) {
System.out.println("err1");
// Handle ...
} catch (ExecutionException e) {
System.out.println("err2");
// Handle ...
}
The problem that im having is that the message is not received by the server, it seems like the code is stuck at the invoke call and doesn't print the Hello world! message. Does someone know what im doing wrong?
hubProxy.invoke("sendMessageByUser", Message, WebApiToken).done(new Action<Void>() {
#Override
public void run(Void aVoid) {
if (aVoid != null)
handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(MyApplicationService.this, "Mesaj gönderildi", Toast.LENGTH_SHORT).show();
}
});
}
}).onError(new ErrorCallback() {
#Override
public void onError(final Throwable error) {
handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(MyApplicationService.this.getApplicationContext(), "Bir hata oluştu" + error.toString(), Toast.LENGTH_SHORT).show();
}
});
}
});
SparkJava web sockets won't work. Whenever I attempt to connect to it with a websocket tester, at 'ws://localhost:4567/echo' it gets an error 'undefined' and never connects, nor do any of the sout's or printStackTrace get called.
#WebSocket
public class EchoWebSocket {
private static final Queue<Session> sessions = new ConcurrentLinkedQueue<>();
#OnWebSocketConnect
public void connected(Session session) {
System.out.println("Client connected");
//sessions.add(session);
}
#OnWebSocketClose
public void closed(Session session, int statusCode, String reason) {
System.out.println("Client disconnected");
//sessions.remove(session);
}
#OnWebSocketMessage
public void message(Session session, String message) throws IOException {
System.out.println("Got: ");// + message); // Print message
//session.getRemote().sendString(message); // and send it back
}
#OnWebSocketError
public void throwError(Throwable error) {
error.printStackTrace();
}
}
how I call it
Spark.webSocket("/echo", new EchoWebSocket());
Spark.init();
You need to define the class, not create an object.
Spark.webSocket("/echo", EchoWebSocket.class);
What I want?
I am trying to write an application where client sends a query and based on the query server gets twitter-stream and pushes to client.
What I have?
I have a simple structure in place where client can connect to server and server responds back
TweetStreamServer
package com.self.tweetstream;
import javax.websocket.OnMessage;
import javax.websocket.server.ServerEndpoint;
#ServerEndpoint("/tweets")
public class TweetStreamServer {
#OnMessage
public String tweets(final String message) {
return message;
}
}
TweetStreamClient
#ClientEndpoint
public class TweetStreamClient {
public static CountDownLatch latch;
public static String response;
#OnOpen
public void onOpen(Session session) {
try{
session.getBasicRemote().sendText("Hello World!");
} catch (IOException e) {
e.printStackTrace();
}
}
#OnMessage
public void printTweets(final String tweet) {
System.out.println("Tweet:" + tweet);
response = tweet;
latch.countDown();
}
}
TweetStreamTest
#Test
public void test() throws URISyntaxException, IOException, DeploymentException, InterruptedException {
System.out.println("URI: " + getEndpointUrl());
TweetStreamClient.latch = new CountDownLatch(1);
Session session = connectToServer(TweetStreamClient.class, "tweets");
assertNotNull(session);
assertTrue(TweetStreamClient.latch.await(10, TimeUnit.SECONDS));
assertEquals("Hello World!", TweetStreamClient.response);
}
Question
I am confused how can I now send continuous tweets that I receive from Twitter because my server method as per API is
#OnMessage
public String tweets(final String message) {
return message;
}
This means it expects a message in order return anything.
How can I send on-coming data from Twitter send to client?
This worked for me
#OnMessage
public void tweets(final String message, Session client) throws IOException, InterruptedException {
int i = 0;
for (Session peer : client.getOpenSessions()) {
while (i < 10) {
System.out.println("sending ...");
peer.getBasicRemote().sendText("Hello");
Thread.sleep(2000);
i++;
}
}
}
Thanks to Arun Gupta for helping through his tweets :)