Java EE Websocket: How to send keep sending data without receiving message? - java

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 :)

Related

SparkJava websocket not working

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);

unable to subscribe paho mqtt java

I'm new to mqtt. Getting started I tried publishing and subscribing topics to mosquitto broker. I was able to publish messages. But my subscriber is not listening to the topic, it will start and stop without waiting/polling for messages.
Here is the subscriber code,
public class MqttSubscriber implements MqttCallback {
private static final String TOPIC = "iot/endpoint";
public static void main(String[] args) {
new MqttSubscriber().listen();
}
public void listen() {
MqttClient client = null;
try {
client = MqttClientGenerator.generateSubscriberClient();
client.connect();
System.out.println("Fetching messages...");
client.subscribe(TOPIC);
client.setCallback(this);
client.disconnect();
} catch (MqttException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
public void connectionLost(Throwable t) {
t.printStackTrace();
}
public void deliveryComplete(IMqttDeliveryToken arg0) {
}
public void messageArrived(String topic, MqttMessage message) throws Exception {
System.out.println("Message received from broker...");
System.out.println("Received Message: -- ");
System.out.println(message.getPayload().toString());
}
}
MqttClientGenerator :
public class MqttClientGenerator {
private static final String BROKER_URI = "tcp://localhost:1883";
private static final String CLIENT_ID = "pub";
private static final String SUBSCRIBER_ID = "sub";
private MqttClientGenerator () {}
public static MqttClient generatePublisherClient() throws MqttException{
//adding timestamp to make client name unique every time
return new MqttClient(BROKER_URI, CLIENT_ID+new Date().getTime());
}
public static MqttClient generateSubscriberClient() throws MqttException{
//adding timestamp to make client name unique every time
return new MqttClient(BROKER_URI, SUBSCRIBER_ID+new Date().getTime());
}
}
what am i missing here?
Try deleting the line where you disconnect the client.

How I create a simple Socket.io server for connecting with socket.io-java-client on android app?

I have a client-side java code running in my Android Activity using the Gottox/socket.io.-java-client implementation on Github. This is the client code that needs to simple connect to a server and receive messages from it from time to time. Please bear with me as I'm very new to this domain and might be understanding this completely wrong!
This is what my client code looks like right now:
package com.example.culami;
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 AcknowledgeExample implements IOCallback {
private SocketIO socket;
int connectionEstablished;
/**
* #param args
*/
/*public static void main(String[] args) {
try {
new AcknowledgeExample();
} catch (Exception e) {
e.printStackTrace();
}
}*/
public AcknowledgeExample() throws Exception
{
connectionEstablished = 0;
socket = new SocketIO();
socket.connect("http://192.168.0.108:3000/", this);
//socket.connect("http://localhost:3000/", 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"));
//socket.send("server says hello!");
// 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");
connectionEstablished = 1;
}
#Override
public void on(String event, IOAcknowledge ack, Object... args) {
System.out.println("Server triggered event '" + event + "'");
}
}
The server side code I'm currently trying to work with is taken from Socket.io's getting started tutorial page and looks as under:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', function(req, res)
{
//res.sendFile(__dirname + '/index.html');
res.send('<h1>Hello world</h1>');
});
io.on('connection', function(socket)
{
console.log('a user connected');
/*socket.on('chat message', function(msg)
{
io.emit('chat message', msg);
});*/
});
All I need is to figure out a way to make my client and server codes connect. The server side code needs to be java script as sends the client a string keyword/message from time to time. Any pointers/suggestions/fixes will be highly appreciated.

Howto add request header to Tyrus annotation based client

I'm trying to access a websocket server endpoint using a tyrus standalone client (tyrus-standalone-client-1.9) with an annotation based client endpoint. I was mainly following this example.
That is, my client endpoint currently looks like
#ClientEndpoint
public class MyClientEndpoint {
private static CountDownLatch latch;
private Logger logger = Logger.getLogger(this.getClass().getName());
#OnOpen
public void onOpen(Session session) throws Exception {
session.getBasicRemote().sendText("initialRequest")
}
#OnMessage
public void onMessage(String message, Session session) throws Exception {
// do something
}
#OnClose
public void onClose(Session session, CloseReason closeReason) {
logger.info(String.format("Session %s close because of %s", session.getId(), closeReason));
latch.countDown();
}
public static void main(String[] args) {
latch = new CountDownLatch(1);
ClientManager client = ClientManager.createClient();
try {
URI serverEndpointUri = new URI("ws://localhost/websockets/server/endpoint");
client.connectToServer(MyClientEndpoint.class, serverEndpointUri);
latch.await();
} catch (DeploymentException | URISyntaxException | InterruptedException e) {
throw new RuntimeException(e);
}
}
}
However I need to pass some session ID along with the request and I need to modify the origin header of the request to get my connection accepted by the server endpoint.
In a programmatic client endpoint I could do something like
final Builder configBuilder = ClientEndpointConfig.Builder.create();
configBuilder.configurator(new Configurator() {
#Override
public void beforeRequest(final Map<String, List<String>> headers) {
headers.put("Cookie", Arrays.asList("X-Session=0f822c8c-bf63-4ae7-9d2f-af263f86baad"));
headers.put("Origin", Arrays.asList("http://localhost"));
}
});
ClientEndpointConfig clientConfig = configBuilder.build();
ClientManager client = ClientManager.createClient();
URI serverEndpointUri = new URI("ws://localhost/websockets/server/endpoint");
client.connectToServer(new MyClientEndpoint(), clientConfig, serverEndpointUri);
But there doesn't seem to be any option to pass the configuration to an annotation based client.
Is there some other way to add/modify the request headers that I'm currently missing? I'd really like to stay with the annotation based approach as it seems to be much cleaner to me...
See ModifyRequestResponseHeadersTest.java:183
#ClientEndpoint(configurator = MyClientConfigurator.class)
public static class MyClientEndpoint {
public static final CountDownLatch messageLatch = new CountDownLatch(1);
public static volatile String receivedMessage;
#OnOpen
public void onOpen(Session session) throws IOException {
session.getBasicRemote().sendText(SENT_MESSAGE);
}
#OnMessage
public void onMessage(String message) {
receivedMessage = message;
messageLatch.countDown();
}
}
And MyClientConfigurator:
public static class MyClientConfigurator extends ClientEndpointConfig.Configurator {
static volatile boolean called = false;
#Override
public void beforeRequest(Map<String, List<String>> headers) {
called = true;
headers.put(HEADER_NAME, Arrays.asList(HEADER_VALUE));
headers.put("Origin", Arrays.asList("myOrigin"));
}
#Override
public void afterResponse(HandshakeResponse handshakeResponse) {
final Map<String, List<String>> headers = handshakeResponse.getHeaders();
assertEquals(HEADER_VALUE[0], headers.get(HEADER_NAME).get(0));
assertEquals(HEADER_VALUE[1], headers.get(HEADER_NAME).get(1));
assertEquals(HEADER_VALUE[2], headers.get(HEADER_NAME).get(2));
assertEquals("myOrigin", headers.get("origin").get(0));
}
}

Send message to single client in tomcat websockets

In tomcat-8 examples I have seen a example on chat using HTML5 web sockets.
The code is shown below
public class ChatAnnotation {
private static final Log log = LogFactory.getLog(ChatAnnotation.class);
private static final String GUEST_PREFIX = "Guest";
private static final AtomicInteger connectionIds = new AtomicInteger(0);
private static final Set<ChatAnnotation> connections =
new CopyOnWriteArraySet<>();
private final String nickname;
private Session session;
public ChatAnnotation() {
nickname = GUEST_PREFIX + connectionIds.getAndIncrement();
}
#OnOpen
public void start(Session session) {
this.session = session;
connections.add(this);
String message = String.format("* %s %s", nickname, "has joined.");
broadcast(message);
}
#OnClose
public void end() {
connections.remove(this);
String message = String.format("* %s %s",
nickname, "has disconnected.");
broadcast(message);
}
#OnMessage
public void incoming(String message) {
// Never trust the client
String filteredMessage = String.format("%s: %s",
nickname, HTMLFilter.filter(message.toString()));
broadcast(filteredMessage);
}
private static void broadcast(String msg) {
for (ChatAnnotation client : connections) {
try {
synchronized (client) {
client.session.getBasicRemote().sendText(msg);
}
} catch (IOException e) {
log.debug("Chat Error: Failed to send message to client", e);
connections.remove(client);
try {
client.session.close();
} catch (IOException e1) {
// Ignore
}
String message = String.format("* %s %s",
client.nickname, "has been disconnected.");
broadcast(message);
}
}
}
}
This code send a message to all the clients who connected to server .
But I want to send message to only "Guest1".
I think for loop has to be change.
How to send message to only "Guest1".
Convert connections from set into a map:
ConcurrentHashMap< String, ChatAnnotation> connections = new ConcurrentHashMap<>();
Keep user or whatever identifier you have to identify user as key in the map. They get the connection object from map using user key in broadcast method and send message only to that user, instead of iterating over all connection objects.

Categories