Search code examples
javawebsocketjettyembedded-jetty

Web Socket upload file and send json on the same endpoint


I'm using Jetty to implement JSR-356 Web socket for chat application. For managed conversations and sending different message types I'm using DTO object which are serialized from/to json using Jackson and TextDecoder

public class JsonDtoCodec implements Decoder.Text<Dto>,Encoder.Text<Dto>{
        ObjectMapper om = ... //some object mapper

        @Override
        public Dto decode(String json) throws DecodeException {
            Dto dto = null;
            try {
                dto = om.readValue(json,Dto.class);
            } catch (IOException e) {
                //ToDo add Log
            }
            return dto;
        }

        @Override
        public String encode(Dto dto) throws EncodeException {
            try {
                return om.writeValueAsString(dto);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

Now, In my endpoint I'm using direct Dto objects:

    @ServerEndpoint(value = "/{version}/{userType}/{token}",
            decoders =JsonDtoCodec.class,
            encoders = JsonDtoCodec.class)
    public class ChatServerEndPoint {

     @OnMessage
        public void onMessage(final @PathParam("userType") String userType,
                              final @PathParam("token") String token,
                              final @PathParam("version") String version,
                              final Session session,
                              Dto dto)
                throws IOException {

               //handling all DTO related object and sending response
               Dto response = .... // create some DTO
               session.getAsyncRemote().sendObject(dto);

    } 
}

Unfortunately, I need to handle uploading image files through web socket up to 100Kb size.

Can I use the same endpoint for handling both, DTOs and Binary Data? If not should I add new EndPoint and should I handle two separate connections one for binaries and one for Json content?


Solution

  • You most certainly can.

    You would have 2 @OnMessage annotated methods. (one handling TEXT, the other BINARY)

    Assuming that your JsonToDtoCodec extends Decoder.Text<Dto>, then your other method would be declared as ...

    @OnMessage(maxMessageSize=100000)
    public void onFileUpload(final Session session, final ByteBuffer buf)
    {
    }
    

    Since you said the files would be a maximum of 100kb, then having the method pass in the complete ByteBuffer is sufficient. If it were larger, you could use an InputStream approach instead. As for limiting the size of that buffer, your maxMessageSize annotation would keep that sane.

    Note: if a client attempts to send something over 100kb in size on binary, then the connection will be closed with close code 1009: Too Big.