Wikipedia says "WebSocket is a protocol providing full-duplex communications channels over a single TCP connection", this means that in a client-server communication the client as the server can send a message leaving behind the request-response protocol, where the exchange is always initiated by the client (usually a browser) and the server cannot send any data without the client requesting it first.
It also says "WebSocket is designed to be implemented in web browsers and web servers, but it can be used by any client or server application", websockets was introduced in the clients or browsers since the html5 specification, and in the Java servers since the JEE 7 version and the specification JSR 356.
If you want to know more about websockets refer to the following links:
I'm going to use the wildfy 8 as server the open source version of jboss, you can download it from here http://wildfly.org/downloads/, and as for the IDE I'm going to use JBoss tools, you can download it from here http://tools.jboss.org/downloads/ .
To set up wildfly with eclipse you can use the following link for instructions: http://planet.jboss.org/post/getting_started_with_jboss_tools_and_wildfly_tech_tip_5
Once you have everything installed and integrated lets start creating a websocket application.
lets create a new project, select new project and from the options presented choose dynamic web project, set the name of the project as websockets and the target runtime to wildfy 8.
The Java API for WebSocket consists of the following packages.
Now lets create a new server endpoint class, this class will receive the messages from the client and also it could send messages to the client.
To set up wildfly with eclipse you can use the following link for instructions: http://planet.jboss.org/post/getting_started_with_jboss_tools_and_wildfly_tech_tip_5
Once you have everything installed and integrated lets start creating a websocket application.
lets create a new project, select new project and from the options presented choose dynamic web project, set the name of the project as websockets and the target runtime to wildfy 8.
The Java API for WebSocket consists of the following packages.
- The javax.websocket.server package contains annotations, classes, and interfaces to create and configure server endpoints.
- The javax.websocket package contains annotations, classes, interfaces, and exceptions that are common to client and server endpoints.
Now lets create a new server endpoint class, this class will receive the messages from the client and also it could send messages to the client.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package websockets; | |
import javax.annotation.Resource; | |
import javax.ejb.Stateless; | |
import javax.enterprise.concurrent.ManagedExecutorService; | |
import javax.websocket.CloseReason; | |
import javax.websocket.OnClose; | |
import javax.websocket.OnMessage; | |
import javax.websocket.OnOpen; | |
import javax.websocket.Session; | |
import javax.websocket.server.ServerEndpoint; | |
import org.jboss.logging.Logger; | |
@ServerEndpoint("/example") | |
public class WSEndpoint { | |
Logger log = Logger.getLogger(this.getClass()); | |
@OnMessage | |
public void receiveMessage(String message, Session session) { | |
log.info("Received : "+ message + ", session:" + session.getId()); | |
} | |
@OnOpen | |
public void open(Session session) { | |
log.info("Open session:" + session.getId()); | |
} | |
@OnClose | |
public void close(Session session, CloseReason c) { | |
log.info("Closing:" + session.getId()); | |
} | |
} |
From the class above notice the
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="UTF-8"> | |
<title>WebSocket Client</title> | |
<script type="text/javascript"> | |
var ws = new WebSocket("ws://localhost:8080/websockets/example"); | |
ws.onopen = function() | |
{ | |
alert("Web Socket is connected!!"); | |
}; | |
ws.onmessage = function (evt) | |
{ | |
var msg = evt.data; | |
alert("Message received:" + msg); | |
}; | |
ws.onclose = function() | |
{ | |
alert("Connection is closed..."); | |
}; | |
</script> | |
</head> | |
<body> | |
</body> | |
</html> |
In the previous html file the only thing to notice is the simple script that creates a connection to the endpoint, from the url "ws://localhost:8080/websockets/example" used check the name of the application and the URI of the endpoint.
If you open the html file on browser that supports web sockets you should see the message "Web Socket is connected!!" and in the server you should see in console the message "Open session:...". This indicates that the communication has been established between the client and the server.
To now more about the WebSocket javascript interface the following link will help:
http://www.w3.org/TR/2011/WD-websockets-20110419/
Let's create a message and send it from the client to the server. To do this let's just add the following function in the javascript section of the html file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function sendMessage() { | |
ws.send("Message to server from client"); | |
} |
With this function the ws variable calls the sends() method and sends the message to the server.
To call this function just add a html link and call it.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<a href="javascript:sendMessage()">Send message</a> |
Let's test it click on the link and you should see the following message on server's console: "Received : Message to server from client, session:..."
Now to simulate a request-response communication lets return a message from the @OnMessage method in the websocket endpoint in the server.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@OnMessage | |
public String receiveMessage(String message, Session session) { | |
log.info("Received : "+ message + ", session:" + session.getId()); | |
return "Response from the server"; | |
} |
Deploy it and test it, you should get the following sequence of messages:
- Browser displays "Web sockect is connected".
- After calling send(), server console diplays: Received : Message to server from client, session:
- Browser displays "Received, Response from the server"
To demonstrate full duplex communication lets send messages from the server without any request from the client. To do this, lets add and asynchronous task to send messages.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package websockets; | |
import java.io.IOException; | |
import javax.annotation.Resource; | |
import javax.ejb.Stateless; | |
import javax.enterprise.concurrent.ManagedExecutorService; | |
import javax.websocket.CloseReason; | |
import javax.websocket.OnClose; | |
import javax.websocket.OnMessage; | |
import javax.websocket.OnOpen; | |
import javax.websocket.Session; | |
import javax.websocket.server.ServerEndpoint; | |
import org.jboss.logging.Logger; | |
@ServerEndpoint("/example") | |
@Stateless | |
public class WSEndpoint { | |
Logger log = Logger.getLogger(this.getClass()); | |
@Resource | |
ManagedExecutorService mes; | |
@OnMessage | |
public String receiveMessage(String message, Session session) { | |
log.info("Received : "+ message + ", session:" + session.getId()); | |
return "Response from the server"; | |
} | |
@OnOpen | |
public void open(Session session) { | |
log.info("Open session:" + session.getId()); | |
final Session s = session; | |
mes.execute(new Runnable() { | |
@Override | |
public void run() { | |
try { | |
for (int i=0;i<3;i++) { | |
Thread.sleep(10000); | |
s.getBasicRemote().sendText("Message from server"); | |
} | |
} catch (InterruptedException | IOException e) { | |
e.printStackTrace(); | |
} | |
} | |
}); | |
} | |
@OnClose | |
public void close(Session session, CloseReason c) { | |
log.info("Closing:" + session.getId()); | |
} | |
} |
In the runnable we wait for 10 seconds and then sends a message to the client this is done without receiving any previous message and this is repeated 3 times so during 30 seconds, your browser should be receiving the message "Received, Message from server".
With this is demonstrated the full-duplex communication this is a message can be sent without any prior message or request.
Well this is basically a simple example that demonstrates how web sockets work, in further post I will keep showing more of their functionality.