I am trying to establish a WebSocket connection in my servlet. I receive some callback messages from the server, but only very few. I call a Thread.sleep(30000), so the servlet should wait 30 seconds for new messages, but it seems not wait for some reason.
This is the code in my Servlet:
try {
// open websocket
final WebsocketClientEndpoint clientEndPoint = new WebsocketClientEndpoint(new URI("wss://www.bitmex.com/realtime"));
// add listener
clientEndPoint.addMessageHandler(new WebsocketClientEndpoint.MessageHandler() {
public void handleMessage(String message) {
System.out.println(message);
logger.info("WEBSOCKET MSG: "+message);
}
});
// send message to websocket
clientEndPoint.sendMessage("{\"op\": \"subscribe\", \"args\": \"trade\"}");
// wait 30 seconds for messages from websocket
Thread.sleep(30000);
} catch (InterruptedException ex) {
System.err.println("InterruptedException exception: " + ex.getMessage());
} catch (URISyntaxException ex) {
System.err.println("URISyntaxException exception: " + ex.getMessage());
}
And this is my WebsocketClientEndpoint code:
import java.net.URI;
import javax.websocket.ClientEndpoint;
import javax.websocket.CloseReason;
import javax.websocket.ContainerProvider;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.WebSocketContainer;
#ClientEndpoint
public class WebsocketClientEndpoint {
Session userSession = null;
private MessageHandler messageHandler;
public WebsocketClientEndpoint(URI endpointURI) {
try {
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
container.connectToServer(this, endpointURI);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* Callback hook for Connection open events.
*
* #param userSession the userSession which is opened.
*/
#OnOpen
public void onOpen(Session userSession) {
System.out.println("opening websocket");
this.userSession = userSession;
}
/**
* Callback hook for Connection close events.
*
* #param userSession the userSession which is getting closed.
* #param reason the reason for connection close
*/
#OnClose
public void onClose(Session userSession, CloseReason reason) {
System.out.println("closing websocket");
this.userSession = null;
}
/**
* Callback hook for Message Events. This method will be invoked when a client send a message.
*
* #param message The text message
*/
#OnMessage
public void onMessage(String message) {
if (this.messageHandler != null) {
this.messageHandler.handleMessage(message);
}
}
public void addMessageHandler(MessageHandler msgHandler) {
this.messageHandler = msgHandler;
}
public void sendMessage(String message) {
this.userSession.getAsyncRemote().sendText(message);
}
public static interface MessageHandler {
public void handleMessage(String message);
}
}
What's the right way to do it? Or could this be some issue with App Engine (Standard Environment)?
Related
I made an alert function which gets price data from websocket and send alert if condition is fulfilled.
I only have "price condition" now, and I want to add "percentage Condition".
So What I'm trying to do is
Open a websocket
get the first data, calculate the limitation price
for Example) user wants to get alert when price is 5% down.
open the websocket, current price is 100$
So I need to send alert to user when price hits 95$(limitation price)
To do so, I need to compute limitation price when opening the websocket.
But I can't figure out "where and how" can I store limitation price..
This is my websocket code implementing price condition(not "percentage condition")
WebSocketClientEndPoint
#ClientEndpoint
public class WebsocketClientEndpoint {
Session userSession = null;
private MessageHandler messageHandler;
public WebsocketClientEndpoint() {
}
public Session connect(URI endpointURI) {
try {
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
userSession = container.connectToServer(this, endpointURI);
return userSession;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* Callback hook for Connection open events.
*
* #param userSession the userSession which is opened.
*/
#OnOpen
public void onOpen(Session userSession) {
System.out.println("opening websocket");
this.userSession = userSession;
}
/**
* Callback hook for Connection close events.
*
* #param userSession the userSession which is getting closed.
* #param reason the reason for connection close
*/
#OnClose
public void onClose(Session userSession, CloseReason reason) {
System.out.println("closing websocket");
this.userSession = null;
}
/**
* Callback hook for Message Events. This method will be invoked when a client send a message.
*
* #param message The text message
*/
#OnMessage
public void onMessage(String message) throws ParseException, IOException {
if (this.messageHandler != null) {
this.messageHandler.handleMessage(message);
}
}
#OnMessage
public void onMessage(ByteBuffer bytes) {
System.out.println("Handle byte buffer");
}
/**
* register message handler
*
* #param msgHandler
*/
public void addMessageHandler(MessageHandler msgHandler) {
this.messageHandler = msgHandler;
}
/**
* Send a message.
*
* #param message
*/
public void sendMessage(String message) {
this.userSession.getAsyncRemote().sendText(message);
}
/**
* Message handler.
*
* #author Jiji_Sasidharan
*/
public static interface MessageHandler {
public void handleMessage(String message) throws ParseException, IOException;
}
}
AlertUserByPrice
public void AlertUserByPrice(Long id) {
Alert alert = alertRepository.findById(id).orElseThrow(() -> new NoSuchElementException());
String type = alert.getAlertType().getKey();
double SetPrice = alert.getPrice();
String ticker = alert.getTicker();
JSONParser jsonParser = new JSONParser();
final NotificationRequest build;
if (type == "l_break") {
build = NotificationRequest.builder()
.title(ticker + " alert")
.message(SetPrice + "broke down")
.token(notificationService.getToken(userDetailService.returnUser().getEmail()))
.build();
}
else { // upper_break
build = NotificationRequest.builder()
.title(ticker + " alert")
.message(SetPrice + "pierced upward")
.token(notificationService.getToken(userDetailService.returnUser().getEmail()))
.build();
}
try {
final WebsocketClientEndpoint clientEndPoint = new WebsocketClientEndpoint();
Session session = clientEndPoint.connect(new URI("wss://ws.coincap.io/prices?assets=" + ticker));
WebsocketClientEndpoint.MessageHandler handler = new WebsocketClientEndpoint.MessageHandler() {
public void handleMessage(String message) throws ParseException, IOException {
Object obj = jsonParser.parse(message);
JSONObject jsonObject = (JSONObject) obj;
double price = Double.parseDouble(jsonObject.get(ticker).toString());
System.out.println("가격 : " + price);
if (type == "l_break") {
if (price < SetPrice) {
System.out.println("끝");
notificationService.sendNotification(build);
session.close();
}
} else {
if (price > SetPrice) {
System.out.println("끝");
notificationService.sendNotification(build);
session.close();
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
System.err.println("InterruptedException exception: " + ex.getMessage());
}
}
};
clientEndPoint.addMessageHandler(handler);
} catch (URISyntaxException ex) {
System.err.println("URISyntaxException exception: " + ex.getMessage());
}
}
what should I do to implement "alert by perentage condition"?? Someone please help..
Thanks in advance
double percent = 0.05;
if (price-(price*percent) < SetPrice) {
System.out.println("끝");
notificationService.sendNotification(build);
session.close();
}
if (price-(price*percent) > SetPrice) {
System.out.println("끝");
notificationService.sendNotification(build);
session.close();
}
Try if this helps
I am not able to connect to my websocket server through Java websocket client.Please help!
Apache Tomcat 8.0.26 is being used
Getting exception as "java.io.IOException: An operation was attempted on something that is not a socket.
Client Class
import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URL;
import java.util.concurrent.CountDownLatch;
import javax.websocket.*;
#ClientEndpoint
public class WebSocketClient {
private static Object waitLock = new Object();
protected Session userSession = null;
private MessageHandler messageHandler;
private static void wait4TerminateSignal() {
synchronized (waitLock) {
try {
waitLock.wait();
} catch (InterruptedException e) {
}
}
}
public void Connect(String sServer) throws InterruptedException {
try {
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
System.out.println("Connecting");
WebSocketClient webSocketClient = new WebSocketClient();
userSession = container.connectToServer(webSocketClient, URI.create(sServer));
wait4TerminateSignal();
System.out.println("Connected");
} catch (DeploymentException | IOException e) {
e.printStackTrace();
}
}
/**
* register message handler
*
* #param message
*/
public void addMessageHandler(MessageHandler msgHandler) {
this.messageHandler = msgHandler;
}
/**
* Send a message.
*
* #param user
* #param message
*/
public void sendMessage(String message) {
this.userSession.getAsyncRemote().sendText(message);
}
public void SendMessage(String sMsg) throws IOException {
userSession.getBasicRemote().sendText(sMsg);
}
#OnOpen
public void onOpen(Session session) {
System.out.println("Connected");
}
#OnClose
public void onClose(Session session, CloseReason closeReason) {
}
#OnMessage
public void onMessage(Session session, String msg) {
System.out.println(msg);
}
public void Disconnect() throws IOException {
userSession.close();
}
}
I'm trying to do a websocket communication with eclipse ide and when i run my code i get a NullPointerException. I've checked and the name in the getAttribute is the same as in the bean
package ws;
import java.io.IOException;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import javax.websocket.server.ServerEndpoint;
import fundstarter.model.ConnectToRMIBean;
import javax.servlet.http.HttpSession;
import javax.websocket.*;
#ServerEndpoint(value="/ws", configurator = HandShake.class)
public class WebSocketAnnotation {
private Session session;
private ConnectToRMIBean sessionUser;
private HttpSession httpSession;
private static final Set<WebSocketAnnotation> myConnections = new CopyOnWriteArraySet<WebSocketAnnotation>();
public WebSocketAnnotation() {
}
#OnOpen
public void start(Session session, EndpointConfig config) {
this.session = session;
this.httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
myConnections.add(this);
this.sessionUser = (ConnectToRMIBean) httpSession.getAttribute("RMIBean");
//sendMessage("New message");
}
#OnClose
public void end() {
// clean up once the WebSocket connection is closed
myConnections.remove(this);
}
#OnMessage
public void receiveMessage(String message) {
sendMessage(message);
}
#OnError
public void handleError(Throwable t) {
t.printStackTrace();
}
private void sendMessage(String text) {
try {
System.out.println("[WebSocketAnnot]RMIBean User Id -> " + this.sessionUser.getUserID());
this.session.getBasicRemote().sendText(text);
} catch (IOException e) {
try {
this.session.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
Can anyone tell me what is my error?
I found the error. It was a typo on the modifyHandshake method on the HandShake
How to close a websocket connection using Java WebSocket API? I have used Java websocket API for both server and client end points. The application is working fine. But I don't know how to close the websocket, before the main thread ends.
This is my ClientEndpoint
package websocket.client;
import java.io.IOException;
import javax.websocket.MessageHandler;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
#ClientEndpoint
public class EchoClient {
Session session;
//request
#OnOpen
public void onOpen(Session session, EndpointConfig config) {
System.out.println("Connected to endpoint: " + session.getBasicRemote());
this.session = session;
sendMessage("Welcome to WebSocket");
}
//response
#OnMessage
public void onMessage(String text) {
System.out.println("Received response in client from server: " + text);
}
#OnError
public void onError(Session session, Throwable t) {
t.printStackTrace();
}
private void sendMessage(String message) {
System.out.println("Sending message from client to server: " + message);
System.out.println(session);
try {
session.getBasicRemote().sendText(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
And I use the following code to start the ClientEndPoint
import java.io.IOException;
import java.net.URI;
import javax.websocket.ContainerProvider;
import javax.websocket.DeploymentException;
import javax.websocket.WebSocketContainer;
import websocket.client.EchoClient;
public class WebSocketDemo {
public static void main(String[] args) {
String uri = "ws://localhost:8080/websocket";
System.out.println("Connecting to " + uri);
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
try {
container.connectToServer(EchoClient.class, URI.create(uri));
} catch (DeploymentException | IOException e) {
e.printStackTrace();
}
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
PS : I haven't used JavaScript.
The WebSocketContainer's connectToServer method returns websocket Session object that has two close methods. That should do the trick.
I watched a tutorial on simple Java networking, and the tutorial showed the server and client application running on the same computer and it worked, I was wondering if there's a way to make it work on different computers in different homes using port forwarding or something else; Here is my code:
Server.java:
package com.cloud.server;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
/**
* The Server class extends JFrame and contains all of the code pertaining to the GUI and the server
*
* #author mcjcloud
*
*/
public class Server extends JFrame
{
private JTextField userInput;
private JTextArea convo;
private ObjectOutputStream output;
private ObjectInputStream input;
private ServerSocket server; // establishes server
private Socket connection; // establishes connection with other computer
/**
* Constructor (basically just sets up the GUI and actionListener(s)
*/
public Server()
{
super("Cloud Messenger");
userInput = new JTextField();
userInput.setEditable(false);
userInput.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
sendMessage(e.getActionCommand());
userInput.setText("");
}
});
add(userInput, BorderLayout.SOUTH);
// set up convo (JTextArea)
convo = new JTextArea();
add(new JScrollPane(convo));
setSize(500, 700);
setLocationRelativeTo(null);
setVisible(true);
}
/**
* startServer() method waits for connection, sets up connection and manages chat
*/
public void startServer()
{
try
{
server = new ServerSocket(6789, 100, InetAddress.getByName("0.0.0.0")); // (port number, backlog) backlog (aka qlength) = "how many people can connect at a time"
while(true) // infinite loop
{
try
{
waitForConnection(); // first set up the connection
setupStreams(); // set up the streams
chat(); // enable the chat and things
}
catch(EOFException eofe) // EOF = EndOfStream (meaning the input/output stream ended)
{
showMessage("Connection terminated.");
}
finally
{
cleanUpConnection();
}
}
}
catch(IOException io)
{
io.printStackTrace();
}
}
/**
* waitForConnection() method will wait for the connection, then display connection info
*
* #throws IOException
*/
private void waitForConnection() throws IOException
{
showMessage("Waiting for connection...");
connection = server.accept(); // listens for a connection
showMessage("Now connected to " + connection.getInetAddress().getHostName());
}
/**
* setupStream() method gets a stream to send/recieve data
*/
private void setupStreams() throws IOException
{
// setup output stream
output = new ObjectOutputStream(connection.getOutputStream()); // create pathway to allow us to connect to the computer the socket is connected to
output.flush();
// setup input stream
input = new ObjectInputStream(connection.getInputStream()); // create pathway to receive messages
showMessage("Stream setup success.");
}
/**
* chat() method code runs during conversation
*/
private void chat() throws IOException
{
String message = "Chatting enabled";
showMessage(message);
setCanType(true);
do
{
try
{
message = (String) input.readObject();
showMessage(message);
}
catch(ClassNotFoundException cnfe)
{
showMessage("Message recieve failed (Other person's problem)");
}
}
while(!message.equals("CLIENT - /terminate"));
}
/**
* cleanUpConnection() method cleans up the stream and things after the chat has ended
*/
private void cleanUpConnection()
{
showMessage("Closing connection...");
setCanType(false);
try
{
output.close();
input.close();
connection.close();
}
catch(IOException io)
{
io.printStackTrace();
}
}
/**
* sendMessage(String) method sends whatever message you type
*
* #param message is what is going to be shown
*/
private void sendMessage(String message)
{
try
{
output.writeObject("SERVER - " + message); // write the message to the outputstream
output.flush();
showMessage("SERVER - " + message);
}
catch(IOException io)
{
convo.append("ERROR: Message can't be sent.");
}
}
/**
* showMessage(String)shows whatever needs to be shown on the JTextArea
*/
private void showMessage(String message)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
convo.append(" " + message + "\n");
}
});
}
/**
* setCanType() method decides whether or not a user can type
*
* #param canType
*/
private void setCanType(boolean canType)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
userInput.setEditable(canType);
}
});
}
}
InvokeServer.java:
package com.cloud.server;
import javax.swing.JFrame;
public class InvokeServer
{
public static void main(String[] args)
{
Server server = new Server();
server.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
server.startServer();
}
}
Client.java:
package com.cloud.client;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ConnectException;
import java.net.InetAddress;
import java.net.Socket;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
/**
* Client class is the sister of the Server class in the server application, contains all the code to build GUI and send info to server and receive
*
* #author mcjcloud
*
*/
public class Client extends JFrame
{
private JTextField userInput;
private JTextArea convo;
private ObjectOutputStream output;
private ObjectInputStream input;
private String message = "";
private String serverIP; // connecting to a specific server
private Socket connection;
public Client(String host)
{
super("Cloud Messenger");
serverIP = host;
userInput = new JTextField();
userInput.setEditable(false);
userInput.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
sendMessage(e.getActionCommand());
userInput.setText("");
}
});
add(userInput, BorderLayout.SOUTH);
convo = new JTextArea();
add(new JScrollPane(convo));
setSize(500, 700);
setLocationRelativeTo(null);
setVisible(true);
}
/**
* startClient() method invokes the whole conversation
*/
public void startClient()
{
try
{
boolean connected = false;
showMessage("Connecting to server...");
while(!connected)
{
try
{
connected = connectToServer();
}
catch(ConnectException ce)
{
// do nothing
}
}
setupStreams();
chat();
}
catch(EOFException eofe)
{
sendMessage("Connection terminated.");
}
catch(IOException ioe)
{
ioe.printStackTrace();
}
finally
{
cleanUpConnection();
}
}
/**
* connectToServer() establishes connection with the server application
*
* #throws IOException
*/
private boolean connectToServer() throws IOException
{
connection = new Socket(InetAddress.getByName(serverIP), 6789);
showMessage("Now connected to " + connection.getInetAddress().getHostName());
return true;
}
/**
* setupStream() method gets a stream to send/recieve data
*/
private void setupStreams() throws IOException
{
// setup output stream
output = new ObjectOutputStream(connection.getOutputStream()); // create pathway to allow us to connect to the computer the socket is connected to
output.flush();
// setup input stream
input = new ObjectInputStream(connection.getInputStream()); // create pathway to receive messages
showMessage("Stream setup success.");
}
/**
* chat() method code runs during conversation
*/
private void chat() throws IOException
{
String message = "Chatting enabled";
showMessage(message);
setCanType(true);
do
{
try
{
message = (String) input.readObject();
showMessage(message);
}
catch(ClassNotFoundException cnfe)
{
showMessage("Message recieve failed (Other person's problem)");
}
}
while(!message.equals("SERVER - /terminate"));
}
/**
* cleanUpConnection() method cleans up the stream and things after the chat has ended
*/
private void cleanUpConnection()
{
showMessage("Closing connection...");
setCanType(false);
try
{
output.close();
input.close();
connection.close();
}
catch(IOException io)
{
io.printStackTrace();
}
}
/**
* sendMessage(String) method sends whatever message you type
*
* #param message is what is going to be shown
*/
private void sendMessage(String message)
{
try
{
output.writeObject("CLIENT - " + message); // write the message to the outputstream
output.flush();
showMessage("CLIENT - " + message);
}
catch(IOException io)
{
convo.append("ERROR: Message can't be sent.");
}
}
/**
* showMessage(String) shows whatever needs to be shown on the JTextArea
*/
private void showMessage(String message)
{
SwingUtilities.invokeLater(new Runnable() // USE THIS RUNNABLE TO UPDATE GUI
{
public void run()
{
convo.append(" " + message + "\n");
}
});
}
/**
* setCanType() method decides whether or not a user can type
*
* #param canType
*/
private void setCanType(boolean canType)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
userInput.setEditable(canType);
}
});
}
}
InvokeClient.java:
package com.cloud.client;
import javax.swing.JFrame;
public class InvokeClient
{
public static void main(String[] args)
{
Client client = new Client("99.25.233.116");
client.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
client.startClient();
}
}
Note:
I tried setting up port forwarding on my home network with the port 6789 to one of my laptops, and that's the laptop I run the server application on.
I solved it. I just undid and redid the port forwarding again and it worked with the public IP address. Thank you all for your help