At IDR Solutions I spend a lot of time working with Glassfish. We use it to showcase our BuildVu product in an online PDF to HTML5 converter so it is important for me to keep up to date with the latest technology.
I thought it might be useful to take a look at WebSockets which is a relatively new technology that promises to make websites more reactive by allowing lower latency interaction between users and the server. In this series of articles, I’ll show you some sample applications you can build using WebSockets and Java EE7.
What is WebSocket?
WebSocket is a protocol that allows for communication between the client and the server/endpoint using a single TCP connection. Sounds a bit like HTTP, doesn’t it? The advantage WebSocket has over HTTP is that the protocol is full-duplex (allows for simultaneous two-way communication) and its header is much smaller than that of an HTTP header, allowing for more efficient communication even over small packets of data.
The life cycle of a WebSocket is easy to understand as well:
- The client sends the Server a handshake request in the form of an HTTP upgrade header with data about the WebSocket it’s attempting to connect to.
- The Server responds to the request with another HTTP header, this is the last time an HTTP header gets used in the WebSocket connection. If the handshake was successful, they server sends an HTTP header telling the client it’s switching to the WebSocket protocol.
- Now a constant connection is opened and the client and server can send any number of messages to each other until the connection is closed. These messages only have about 2 bytes of overhead.
A Simple Example
The WebSocket API was introduced with Java EE7, in this example, we’ll create a client which will send a message to the server and the server will send it back.
For this example, I’ll be using the NetBeans 7.4 and the Glassfish 4 server, which comes bundled with NetBeans.
Setting up the Project
Open the New Project Wizard, choose Java Web and select Web Application. Select next, name your project and choose its save location and press next.
Make sure your chosen server is the name of your GlassFish server and that the Java EE version you’re working with is 7 or above and press finish.
Your project should now be generated. Now, we’ll build the Server Endpoint which will handle incoming WebSocket messages.
In your project go to “Source Packages” and create a new Java class. The server endpoint is a Plain Old Java Object (POJO) which uses Java’s annotations to define its methods (This can be done programmatically but looks much cleaner using annotation). This is the code for the endpoint:
import java.io.IOException;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
/**
* @ServerEndpoint gives the relative name for the end point
* This will be accessed via ws://localhost:8080/EchoChamber/echo
* Where "localhost" is the address of the host,
* "EchoChamber" is the name of the package
* and "echo" is the address to access this class from the server
*/@ServerEndpoint("/echo")
public class EchoServer {
/**
* @OnOpen allows us to intercept the creation of a new session.
* The session class allows us to send data to the user.
* In the method onOpen, we'll let the user know that the handshake was
* successful.
*/ @OnOpen
public void onOpen(Session session){
System.out.println(session.getId() + " has opened a connection");
try {
session.getBasicRemote().sendText("Connection Established");
} catch (IOException ex) {
ex.printStackTrace();
}
}
/**
* When a user sends a message to the server, this method will intercept the message
* and allow us to react to it. For now the message is read as a String.
*/ @OnMessage
public void onMessage(String message, Session session){
System.out.println("Message from " + session.getId() + ": " + message);
try {
session.getBasicRemote().sendText(message);
} catch (IOException ex) {
ex.printStackTrace();
}
}
/**
* The user closes the connection.
*
* Note: you can't send messages to the client from this method
*/ @OnClose
public void onClose(Session session){
System.out.println("Session " +session.getId()+" has ended");
}
}
And the code for the client, which goes into the index.html. In the project view navigate to Web Pages and open index.html this should be some generic HTML. I will be using HTML/Javascript to control the client-side. There is a standard API for WebSockets in JavaScript and is supported by most modern browsers. In index.html replace the code with the following:
edit: As pointed out in the comments, the undefined connection appears to be a bug in certain browsers.
All that’s left to do now is run the server. In NetBeans right-click the project directory and select run, this will start up Glassfish and deploy the application to the server. Your default browser should now open a new page where you can start using the client above. To open the connection press open, type something into the text box and press send. When your done press the close button.
Your client should look something like this:
And to prove it’s not just smoke and mirrors, here’s the output from the server, the hex string shown is the ID of the client:
And there you have it, how to create a simple Echo application using web sockets in Java EE7. In my next article, I’ll use WebSockets to transport more important information, images of our pets.
Got any comments or questions? Leave them below.
If you would like to read more articles on Servers you should try:
- How to use the Google App Engine with the NetBeans IDE
- How to set up Amazon Cloud/AWS Elastic Beanstalk on the NetBeans IDE
- How to use the Microsoft Azure Cloud on the NetBeans IDE
- Top 10 Open Source Java and JavaEE Application Servers
If you want to try running Java Software on the Amazon Cloud you can try following this handy tutorial:
We now have a series of articles on what is new in Java 9:
- Java 9 Modularity Explained in 5 minutes
- Java 9 jlink explained in 5 minutes
- Why HTTP/2 Client in Java 9 is important
- How HTML5 Javadocs in Java 9 will make your life easier
Our software libraries allow you to
Convert PDF files to HTML |
Use PDF Forms in a web browser |
Convert PDF Documents to an image |
Work with PDF Documents in Java |
Read and write HEIC and other Image formats in Java |
your brief tutorial would be even better if you explained other important details, like, for example, why the endpoint will be accessed on ws://localhost:8080/WebSocketTest/websocket
Thanks.
Thanks for the suggestion, I’ve added it to the article. I also noticed it should be /echo and not /websocket and updated it.
Hey, Simon, thanks for that answer. I have learned a few interesting things thanks to your tutorial.
Probably you have already seen this (but just in case):
http://stackoverflow.com/questions/12170230/why-do-i-get-two-connections-from-websocket-client-one-is-empty
I have been playing with your example (with minor modifications) and found that Chrome (Version 36.0.1985.125) opens two websocket connections (one undefined) but on Safari (Version 7.0.5 (9537.77.4)) it doesn’t do so, so you might have an explanation to what you were experiencing on your websocket.onopen (you were requesting a comment if anybody had a clue, so here might be a hint 🙂 ).
Thanks again for this tutorial.
That’s very interesting, thanks again 🙂
Does this work on Tomcat 7 or does it work only with Glassfish?
it should work on Tomcat too, if you are running java EE 6 or above
Not running with Tomcat 7 (J2EE 6), but works perfectly with Tomcat 8(J2EE 7)
// For reasons I can’t determine, onopen gets called twice
// and the first time event.data is undefined.
// Leave a comment if you know the answer.
it is undefined because that is no “event.data” for the json return from handle websocket.open.
you can use this
console.log(event);
to see what it is return. I test on chrome 38.0.2125.111 m
This is not working with Eclipse + Apache Tomcat , I Created dynamic project in eclipse , is there any configuration required for this , please help ? I’ve attached the war , you can directly import in eclipse and it works let me know .
https://www.dropbox.com/s/9fx8icah8v6kmsi/WebSocketWebApplication.war?dl=0
Dear Shashank
if you could let us know the version of apache tomcat server you are running then we can reproduce the problem and give you a solution
Can you please.
Give me a simple project client and server socket
Thank you
Dear Simon,
I’m trying out websockets and thought your samples are a good starting point. I could not get the html code, could you please fix the issue at your earliest convenience.
Thank you !!!
Dear Habib
what type of error you are experiencing? can’t you access the html code? have you tried in new browsers?
I am getting connection close error,I am using mozilla updated version
what server and java ee version you are running ?
what server and what java EE version you are running ?
Very clear tutorial but I’m also experiencing the connection closed problem using:
eclipse luna
Java 1.7
tomcat7
I tried some suggestions I found in doing some research with no luck:
1. set the connection timeout to -1 to keep it open
2. don’t use bio connector protocol, use nio instead
Here is the part of server.xml that accomplishes both yet it still doesn’t work:
<!– –>
Any help would be appreciated.
server.xml
————–
<!– –>
port=”8080″
protocol=”org.apache.coyote.http11.Http11NioProtocol”
connectionTimeout=”-1″
Hi Rocketfish, we will investigate this issue on Eclipse Luna and come back to you with a solution.
Great tutorial/example, but I run into some problems – can you please help me. I’m using Eclipse Luna. I created dynamic web project (what ever that is?). After that I had to manually add to build path “javaee-api-7.0.jar” lib. After that eclipse is not reporting me any errors. But when I run the project in console I get message:
Starting preview server on port 8080
Modules:
EchoChamber (/EchoChamber)
2015-02-21 11:06:04.996:INFO:oejs.Server:jetty-8.1.14.v20131031
2015-02-21 11:06:05.543:INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:8080
On front-end JS just says “Connection closed”. When I open “http://localhost:8080/” from browser I get:
Error 404 - Not Found
No context on this server matched or handled this request.
Contexts known to this server are:
EchoChamber(/EchoChamber)
Where last word is a link and when I click it I get new page:
Directory: /EchoChamber/
META-INF/ 0 bytes Feb 21, 2015 10:49:23 AM
WEB-INF/ 0 bytes Feb 21, 2015 10:49:23 AM
and both of those 2 dirs are empty..
I am afraid we use NetBeans and IDEA inhouse.
Installed Net Beans and it’s working well….So, don’t bother for me to solve this Eclipse problem. But in case you think it would be interested for other folks…
Thanks for the great tutorial!
How many connections can be supported by the “javax.websocket” at one time? I mean what is the maximum number of users can chat simultaneously?
As far as i know there is no limit ( the web socket connections are actually sessions ) but you can confine the connections and session limit in servers.
Hello Sir,
I follow your instructions and copy paste your code but I couldn’t get the server response. In HTML between 3 buttons (Open, Send, Close) only open is working and it only return “Connection close” whenever i pressed it.
Could you give us details such as : Server name and version, browser name and version
Hello sir,
Open should click “connection close” only work it. I’am using GlassFish Server 4.1 and JEE 7 to used.. Please give the solution. Thankyou…
Hi
I have a problem in creating connection.
i am using Glass Fish and Net Beans. When I press “open” button an error occur in “OnError” that say: “connection closed” and event.data is undefined!!!
Why Do I have this notification?
OK….
I got it….
Cheek the ws://localhost:8080/EchoChamber/echo in your HTML page
Cheek that the EchoChamber…. and your IP Address is correct…