From the course: WebSocket Programming with Java EE

Implement WebSocket lifecycles

From the course: WebSocket Programming with Java EE

Start my 1-month free trial

Implement WebSocket lifecycles

- [Instructor] Okay, so let's build a WebSocket server endpoint using the annotation methodology. We're going to implement the lifecycle methods OnOpen, OnMessage, OnClose, and OnError, and discuss how WebSocket sessions are managed. Okay, so you should open the ChatServerEndpoint class. And the first task is to add class level annotations, then mark the class as a WebSocket endpoint. And we do that here at the class level. So we start with @ServerEndpoint(value = and within the value, we're going to enter the endpoint. And the endpoint is going to be chat and then we're going to follow that with a variable, which is going to be roomName, which we then follow with another variable, which we're gonna be calling userName. Now, as you can see, in this case, we want a URI variable for the room name, and also, a URI variable for the username of the user. Now, this is an example of how to use multiple variables in a template URI. Next, we implement the lifecycle methods for each of the lifecycle states. OnOpen, OnMessage, OnClose, and OnError. So let's start with OnOpen. The annotation we use is called OnOpen, and I would also call the method OnOpen. You can actually call it whatever you like, but a descriptive name is much better. I'm gonna code this method down here. I'm gonna start with our annotation, @OnOpen. I'm gonna start with our method, which is gonna be public void method. Gonna call it onOpen, and there's our method. And now the parameters to this method are going to be the session, which all lifecycle methods accept, and in this case, two path parameters. One which captures the value of the room name, and one that captures the value of the username. These values are paths of the path parameter of this method. And we identify the parameter by annotating it @PathParam and specifying the path variable, room name, and username. So let's start by adding the session. So, it's gonna be final_Session, and let's call the session variable session, and now we're gonna add the path parameters. We use the annotation @PathParam and we parse it the name of the variable. So the first variable we want to capture is going to be the roomName, and then we create, and then we create a variable into which to store this value. I'm just gonna call it something simple, roomName. And we also need another one, we're just gonna capture the username, so again, path parameter, and we parse it the userName variable name. And again, we need a way of storing that, so we're gonna call that variable userName. I'm going to leave the method empty for the moment and continue implementing the other lifecycle methods. Now, we need a method that corresponds to the message receipt event. So we have an annotation appropriately named OnMessage, which we use to annotate the method that will handle this message. Let's create a method and call it OnMessage. This method has a parameter for session, but also a parameter for the message itself. So, just down here, we're going to do as before. I'm going to create our annotation, add an annotation like this, OnMessage, and then we're gonna create our method. It's gonna be another public void method. I'm gonna call it something sensible, onMessage. And of course, we're now going to parse in the variable, which is the message itself, plus the session. So it's gonna be session, like so. Now, the observant among you might have noticed that the message parameter here is a custom message class, and not a message class that is part of the javax.websocket package. This is because I want my own message encoders and decoders to control the format of the message. So I've created my own class called Message. Let's have a quick look at this class. As you can see, it's a very simple class. It just has three fields. Content field, which contains the content of the actual message, the sender, which is effectively the username, and then received, which is going to be the date that the message is received. I must also register the message encoder and decoder with the endpoint. And I do this by specifying the class name in the class level server endpoint annotation. So we get back up to here and we simply specify our encoders. In this case we just have an encoder for our message, which is called MessageEncoder, and we have to specify the precise class. And again, we have one for decoder. It's just going to be called MessageDecoder, and again, we specify the entire class. We'll look at message encoders and decoders in more detail later on in this course. Now, if I hadn't chosen to use a custom message class, the parameter will be a simple string. But as you already know, there are three message types, text, binary, and pong. So, for example, I could also have a method that handles binary types. So let's actually create one. So I'm gonna move down here, underneath my method, and I am going to create another method that handles binary types. So, again, @OnMessage is our annotation, and we create a public void. We're gonna call this one onBinaryMessage, and you simple parse it a ByteBuffer, which is going to be our message. And also, we have a session, like so. And also, I could have another method that handles pong messages. So again, we do the same thing as before. Creating a public method, void, this is gonna be onPongMessage. And again, the message type is PongMessage. I guess I can simply call this variable message. Again, we have Session, session, like so. I'm not gonna have all three of these methods at the same time running in my class. Each method will accept a message of that particular given type. At this point, I should probably mention what a pong message is. Essentially, it is a mechanism for checking that the connection is still alive. In this application, we're not going to deal with binary message types. But later on, you'll get a chance to implement a ping pong message endpoint as a challenge.

Contents