# Receiving Messages

From an API perspective, sending WebSocket messages is much simpler because of it's dependency on a simple construct i.e. `javax.websocket.RemoteEndpoint` interface. For an understanding of how to receive messages, we need to take into account both annotated as well as programmatic styles

* Annotated endpoints: it's all about passing the right type of parameters in the method annotated with `@OnMessage`&#x20;
* Programmatic endpoints: implementation of the appropriate `javax.websocket.MessageHandler` (child) interface encapsulates the logic for receiving messages

## Receive modes: a quick primer

Here is an overview of the options available when receiving messages

| Mode      | Description                                                                                                                                                                                                              |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Complete  | The message is received in its entirety                                                                                                                                                                                  |
| Partial   | This works in conjunction with the partial send capability. If the sender sends messages in chunks, the message is received in chunks. The receiver will get a `true` boolean flag to notify it of the last message part |
| Streaming | Receive messages in form of Java `Reader`s and `InputStream`s                                                                                                                                                            |

Receving messages can also end up with a lot of permutations and combinations (just like the send APIs). So here is what we'll do in order to help tackle that

* Pick up a **message type** (thankfully there are just two of them - String and Binary!)&#x20;
* For each of the **endpoint styles** (Annotated and Programmatic), we will look at the possible receiving modes (as mentioned above)&#x20;
* Take a look at how Java objects and Pong messages are handled (separate sections)

## Receiving text messages

### Annotated endpoints

Receving text messages in annotated endpoints is all about having the appropriate method parameter type and the WebSocket runtime will automatically figure out the rest

**Complete**

```
...
@OnMessage
public void handleChatMsg(String chat) {
    System.out.println("Got message - " + chat);
}
...
```

**Partial**

```
...
@OnMessage
public void pushChunk(String partMsg, boolean last) {
    String chunkSeq = last ? "intermediate" : "last" ;
    System.out.println("Got " + chunkSeq + " chunk - "+ partMsg);
}
...
```

**Streaming**

```
...
@OnMessage
public void handleChatMsg(Reader charStream) {
    System.out.println("reading char stream");
}
...
```

### Programmatic endpoints

As mentioned earlier, Programmatic endpoints are inheritance based and thus need some more custom code to set them up as message receviers.

**Complete**

```
public class WholeTextMsgHandler extends MessageHandler.Whole<String> {
    @Override
    public void onMessage(String chat) {
        System.out.println("Got message - " + chat);
    }
}
```

**Partial**

```
public class PartialTextMsgHandler extends MessageHandler.Partial<String> {
    @Override
    public void onMessage(String partMsg, boolean last) {
    String chunkSeq = last ? "intermediate" : "last" ;
    System.out.println("Got " + chunkSeq + " chunk - "+ partMsg);
  }
}
```

**Streaming**

```
public class WholeStreamingTextMsgHandler extends MessageHandler.Whole<Reader> {
    @Override
    public void onMessage(Reader charStream) {
        System.out.println("Got stream message - " + charStream);
    }
}
```

## Receiving binary messages

When it comes to binary messages, the pattern (for both annotated and programmatic endpoints) is the same (except for the data type of course!). Binary messages support is available in the form of `byte[]` (array), `java.nio.ByteBuffer` and `java.io.InputStream`

### Annotated endpoints

**Complete**

```
...
@OnMessage
public void handleImage(ByteBuffer img) {
    System.out.println("Got message - " + chat);
}
...
```

**Partial**

```
...
@OnMessage
public void pushChunk(byte[] audioPart, boolean last) {
    String chunkSeq = last ? "intermediate" : "last" ;
    System.out.println("Got " + chunkSeq + " clip");
}
...
```

**Streaming**

```
...
@OnMessage
public void handleChatMsg(InputStream binaryStream) {
    System.out.println("reading binary stream");
}
...
```

### Programmatic endpoints

The concept remains the same apart from a change in the data types..

**Complete**

```
public class WholeBinaryMsgHandler extends MessageHandler.Whole<byte[]> {
    @Override
    public void onMessage(byte[] image) {
        System.out.println("Got image - " + image.length);
    }
}
```

**Partial**

```
public class PartialBinaryMsgHandler extends MessageHandler.Partial<ByteBuffer> {
    @Override
    public void onMessage(ByteBuffer clip, boolean last) {
    String chunkSeq = last ? "intermediate" : "last" ;
    System.out.println("Got " + chunkSeq + " chunk");
  }
}
```

**Streaming**

```
public class WholeStreamingBinaryMsgHandler extends MessageHandler.Whole<InputStream> {
    @Override
    public void onMessage(InputStream binaryStream) {
        System.out.println("Got stream binary message");
    }
}
```

## Receiving text, binary messages as Java objects

Text and binary messages sent by a WebSocket peer can be received as Java objects within your message handling logic (annotated or programmatic).

> But how would the on-wire format (text/binary) to Java object transformation take place ?

This is where **Decoders** come into the picture. An implementation of a `javax.websocket.Decoder` provides the necessary logic to convert a message from it's on-wire format into it's Java representation.

> #### WebSocket Decoders: the details
>
> Decoders are complementary to Encoders (which were discussed in the **Sending Messages** lesson). Take a look at the diagram below to visualize how they work at runtime

![Decoders in action](/files/-M3y266flNAFzoEJ5aaF)

### Transforming native data types (Text, Binary) into Java objects

A summary of Decoders and their types

| Basic Decoder Type  | Description                                                                                              |
| ------------------- | -------------------------------------------------------------------------------------------------------- |
| `Decoder`           | The top level interface for different types of Decoders                                                  |
| `Decoder.Text<T>`   | Defines how a custom Java object (of type `T`) is produced from a text payload (`java.lang.String`)      |
| `Decoder.Binary<T>` | Defines how a custom Java object (of type `T`) is produced from a binary payload (`java.nio.ByteBuffer`) |

A sample to demonstrate how a `Decoder` which creates a `Subscription` object from a String

```
public class StockSubscriptionDecoder implements Decoder.Text<Subscription> {

    @Override
    public Subscription decode(String subscription){
        //client sends comma seperated list of subscription e.g. appl,goog,orcl 
        return new Subscription(Arrarys.asList(subscription.split(",")));
    }
    @Override
    public void willDecode(String subscription){
        return subscription!=null && subscription.split(",").length > 0;
    }

}
```

### Transforming Streaming inputs into Java objects

Native text and binary messages can be received as **streams** - as explained in the previous sections. Java objects can also be received in a streaming style

| Streaming Decoder Type    | Description                                                                                             |
| ------------------------- | ------------------------------------------------------------------------------------------------------- |
| `Decoder.TextStream<T>`   | Defines how a custom Java object (of type `T`) is produced from a character stream (`java.io.Reader`)   |
| `Decoder.BinaryStream<T>` | Defines how a custom Java object (of type `T`) is produced from a binary stream (`java.io.InputStream`) |

This example shows how you can handle data in a streaming form using a `Reader` which creates a `Conversation` object

```
public class ConversationDecoder implements Decoder.TextStream<Conversation> {

    @Override
    //handles new-line delimited content
    public Conversation decode(Reader content) {
        Conversation conversation = new Conversation();
        try(LineNumberReader lineByLineReader = new LineNumberReader(content)){
        String line = lineByLineReader.readLine();
        while(line != null) {
            conversation.add(line);
            line = lineByLineReader.readLine();
        }
      }
    return conversation;
  }
}
```

## Handling `Pong` objects

`Pong` messages were introduced in the **API Overview** chapter and were then discussed in the **Sending Messages** chapter as well. Receiving a health-check response message (a.k.a `javax.websocket.Pong`) is possible in both annotated and programmatic endpoints. Here are the examples

```
//annotated Pong handler
...
@OnMessage
public void healthCheckCallback(PongMessage pong) {
    System.out.println("Pong for Ping! "+ new String(pong.getApplicationData().array());
}
...
```

```
//programmatic Pong handler 
public class PongMsgHandler extends MessageHandler.Whole<PongMessage> {
    @Override
    public void onMessage(PongMessage pong) {
        System.out.println("Pong for Ping! "+ new String(pong.getApplicationData().array());
    }
}
```

## Common notes

### Using a `MessageHandler`

There are two basic steps involved (common to Programmatic endpoints)

* implement appropriate `MessageHandler` implementation based on data type and whole/partial message
* attach that implementation using `Session#addMessageHandler` methods (multiple combinations available)

> #### `addMessageHandler` permutations
>
> Couple of additional (overloaded) `addMessageHandler` methods were added to the `Session` interface as a part of WebSocket 1.1 release. In fact this was the only (minor) change in the 1.1 MR (maintenance release). For details, please check the [change log](https://jcp.org/aboutJava/communityprocess/maintenance/jsr356/websocket-1.1-changes.txt)

```
//attaching message handlers

public class ProgrammaticEndpoint extends Endpoint {

    @Override
    public void onOpen(Session session, EndpointConfig config) {
        session.addMessageHandler(new WholeBinaryMsgHandler()); //basic
        session.addMessageHandler(String.class, new WholeTextMsgHandler()); //specify class type for Whole message handler
        session.addMessageHandler(ByteBuffer.class, new PartialBinaryMsgHandler()); //specify class type for Partial message handler
    }
}
```

### Other possible parameters for `@OnMessage`

In addition to the message itself, a method annotated with `OnMessage` can also receive the following information (which will be injected by the implementation at runtime)

* zero or more `String` parameters annotated with `@javax.websocket.PathParam` (it is similar in spirit to the JAX-RS `@javax.ws.rs.PathParam` annotation)
* an instance of `Session`
* an instance of `EndpointConfig` (server or client side)

```
public void onMsgCallback(String theMsg, @PathParam("user") String username, Session peer, EndpointConfig condfig){
    System.out.println("I have everything I could possibly receive from the WebSocket implementation !");
}
```

### Handling Java primitives

A WebSocket implementation provides default decoders for Java primitive (int-Integer, long-Long, double-Double etc.) data types. It is possible to write a custom decoder for any of these in order to override the default ones

## Up next

We'll explore the **WebSocket Client API** in detail


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://abhishek-gupta.gitbook.io/java-websocket-api-handbook/receiving-messages.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
