Skip to content

Multiple messages arrive as single response body or message received are incomplete

Jeanfrancois Arcand edited this page Oct 31, 2013 · 4 revisions

Multiple messages arrive as single response body or are incomplete

If you broadcast multiple messages and the underlying server buffer them in memory, your atmopshere.js callback or function can be invoked with multiple messages instead of a single message. It may not be an issue if you are using text, but if you are using JSON the parsing may fail because your callback/function gets invoked with multiple JSON messages. To prevent that, just add the following TrackMessageSizeInterceptor and your callback will be invoked only with a single message

        <init-param>
          <param-name>org.atmosphere.cpr.AtmosphereInterceptor</param-name>
          <param-value>org.atmosphere.client.TrackMessageSizeInterceptor</param-value>
        </init-param>

Be careful when using the TrackMessageSizeInterceptor because all write operations will be manipulated by the interceptor. If you are using the Jersey extension and serving pages using a Resource, it is recommended to use the TrackMessageSizeFilter instead, in which case the manipulation will only happen to the message broadcasted using Broadcaster.broadcast(String):

        <init-param>
          <param-name>org.atmosphere.cpr.broadcastFilterClasses</param-name>
          <param-value>org.atmosphere.client.TrackMessageSizeFilter</param-value>
        </init-param>

Be careful as well when using the TrackMessageSizeInterceptor and Jersey. If you write a chunk larger than the default Jersey's internal buffer, the interceptor will not be able to properly work and will wrongly mark the message as smaller. The solution in that case is to increase the Jersey's internal buffer.

If you need to broadcast object instead of String, the TrackMessageSizeFilter won't work because it only support String. In that case you can write your own BroadcasterFilter or use a Serializer, as described here:

import org.atmosphere.cpr.AtmosphereRequest;
import org.atmosphere.cpr.AtmosphereResource;
import org.atmosphere.cpr.PerRequestBroadcastFilter;
import org.codehaus.jackson.map.ObjectMapper;

import java.io.IOException;

import static org.atmosphere.cpr.HeaderConfig.X_ATMOSPHERE_TRACKMESSAGESIZE;

public class ResponseSizeFilter implements PerRequestBroadcastFilter {

    private final static ObjectMapper mapper = new ObjectMapper();

    @Override
    public BroadcastAction filter(AtmosphereResource r, Object originalMessage, Object message) {
        AtmosphereRequest request = r.getRequest();
        if ("true".equalsIgnoreCase(request.getHeader(X_ATMOSPHERE_TRACKMESSAGESIZE))) {

            String msg = null;
            try {
                msg = mapper.writeValueAsString(message);
                r.getResponse().write(msg.length() + "\r\n".length() + "|" );
            } catch (IOException e) {
            }
        }
        return new BroadcastAction(BroadcastAction.ACTION.CONTINUE, message);
    }

    @Override
    public BroadcastAction filter(Object originalMessage, Object message) {
        return new BroadcastAction(message);
    }
}

On the client side, just set trackMessageLength : true

    var request = { url: document.location.toString() + 'chat',
                    contentType : "application/json",
                    logLevel : 'debug',
                    transport : 'sse' ,
                    trackMessageLength : true,
                    fallbackTransport: 'long-polling'};

Step by Step Tutorials

Concepts & Architecture

15 Minutes Tutorial

Advanced Topics

API

Known WebServer Issues

References

External Documentations

githalytics.com alpha

Clone this wiki locally