on 04-03-2013 4:33 PM
I'm trying to get Web Socket working on a Java Web Application, running on HANA Cloud (former NetWeaver Cloud).
I'm already able to establish a socket and keep it open. Also, on the SAP HANA Cloud local runtime it works perfectly!
However, on HANA Cloud the communication currently works only one-way (from server to client, but not from client to server). In my eyes, this is the last problem - anything else works perfectly fine.
To simplify things, I started with an easy implementation of WebSocket and haven't used any framework, yet.
On the server I created a "websocket" servlet which I mapped to a URL.
<servlet>
<description></description>
<display-name>WebSocket</display-name>
<servlet-name>WebSocket</servlet-name>
<servlet-class>projectName.WebSocket</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>WebSocket</servlet-name>
<url-pattern>/WebSocket</url-pattern>
<url-pattern>/websocket</url-pattern>
</servlet-mapping>
package projectName;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.util.concurrent.CopyOnWriteArraySet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import org.apache.catalina.websocket.MessageInbound;
import org.apache.catalina.websocket.StreamInbound;
import org.apache.catalina.websocket.WebSocketServlet;
import org.apache.catalina.websocket.WsOutbound;
/**
* Servlet implementation class WebSocket
*/
public class WebSocket extends WebSocketServlet {
private static final long serialVersionUID = 1L;
@Override
public void init() throws ServletException {
super.init();
}
@Override
protected StreamInbound createWebSocketInbound(String subProtocol, HttpServletRequest request) {
return new WebSocketMessageInbound();
}
private static final class WebSocketMessageInbound extends MessageInbound {
private static final CopyOnWriteArraySet<WebSocketMessageInbound> connections = new CopyOnWriteArraySet<WebSocketMessageInbound>();
@Override
protected void onBinaryMessage(ByteBuffer message) throws IOException {
throw new UnsupportedOperationException("Binary message not supported");
}
@Override
protected void onTextMessage(CharBuffer message) throws IOException {
broadcast(message.toString());
}
@Override
protected void onOpen(WsOutbound outbound) {
connections.add(this);
broadcast("Client has opened a connection");
}
@Override
protected void onClose(int status) {
connections.remove(this);
broadcast("Client has closed the connection");
}
private void broadcast(String message) {
for(WebSocketMessageInbound client : connections) {
try {
CharBuffer buffer = CharBuffer.wrap(message);
client.getWsOutbound().writeTextMessage(buffer);
}
catch (IOException e) {
System.err.println("Caught IOException: " + e.getMessage());
}
}
}
}
}
The client simply calls the url, in my case when I run it on local: http://localhost:8080/websocket.html and then JavaScript code is executed automatically.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<title>Websocket Test</title>
<script>
var connection = new WebSocket('ws://' + location.host + '/websocket');
// When the connection is open, log it
connection.onopen = function () {
console.log('Client: Web Socket connection established');
};
// Log errors
connection.onerror = function (error) {
console.log('WebSocket Error: ' + error);
};
// Log messages from the server
connection.onmessage = function (e) {
console.log('Server: ' + e.data);
};
// Send a message to the server every 10 seconds
function sendMessage() {
var message = 'Hi from Client';
connection.send(message);
console.log("Client: " + message);
setTimeout("sendMessage()", 10000);
}
setTimeout("sendMessage()", 5000);
</script>
</head>
<body>
</body>
</html>
Everything works. Opening a Web Socket connection, sending a message to the server as well as vice versa.
Great! If there wouldn't be the problem with HANA Cloud...
On HANA Cloud
First a notice: When I deploy the solution to HANA Cloud I change the ws://... URL to wss://... since HANA opens a secure SSL/TLS connection.
If I run the same code on HANA Cloud I can open a connection and get also respond from the server that the Web Socket connection is opened. But then any further messages which I want to send to the server somehow don't get through.
However, the WebSocket connection stays open. I realized that when I accessed the same URL from another device (Laptop, iPhone, doesn't matter). Then I got the message from the server that another Client has opened a connection as shown in the image above (as mentioned above, I implemented the functionality that if a client connects or disconnects the server tells this every other client). This is proof that the WebSocket connection stays definitely open.
I also checked if this is maybe a proxy-related problem. But I also get the same behavior when I try this on "public" internet without any proxy.
To isolate the problem I also checked if the onTextMessage method (line 43 in WebSocket.java) is called on the server when I send a message: On HANA Cloud the method never gets called.
My guess is, that either the message doesn't even get to the server, but since I don't know any way how to debug HANA Cloud I am not sure about that. Also the HTTP logs are not very useful in that case: Once a Web Socket connection is established client and server switch from HTTP to WebSocket, so this communication won't be recorded in the HTTP log anymore.
Another guess would be that the server somehow only accepts a special encoding but doesn't tell this the client on the handshake. So the server could receive messages from the client, but discards all the messages since the encoding is incorrect.
That's the point where I'm currently kind of stuck - but it feels like I'm close to get WebSocket running on HANA Cloud. Would be great if someone can help me.
Best regards,
Simon
Hi Simon,
The HANA Cloud currently does not support websocket traffic - any non-HTTP traffic to applications is filtered. The initial connection succeeds because the websocket handshake is done over HTTP - a GET is sent to which the server responds with 101 "Sitching Protocols" (for more information see http://en.wikipedia.org/wiki/WebSocket). After that any traffic over the connection is packaged as websocket frames, which the HANA Cloud infrastructure filters. That's why you don't receive any response from the server.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Petar,
thanks for your reply!
So it seems the HANA Cloud infrastructure only filters inbound traffic. Because once a WebSocket connection is established it stays open and the server can continue sending messages via WebSocket (which definitely arrive on the client-side as shown above).
Is there any way to change the filter on HANA Cloud that also inbound WebSocket-traffic comes through? There are many use-cases for using WebSocket connections and I found some other posts here on SCN of users trying to get WebSocket running - so there is probably demand for WebSocket support on HANA Cloud.
User | Count |
---|---|
67 | |
8 | |
7 | |
6 | |
6 | |
5 | |
5 | |
5 | |
4 | |
4 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.