Skip to content

Understanding BroadcastFilter

jfarcand edited this page May 17, 2012 · 7 revisions

To begin, make sure you have read the Understanding Broadcaster document before reading this one.

BroadcastFilter and PerRequestBroadcastFilter are useful for transforming, accumulating or discarding broadcasted messages. BroadcastFilter are defined as:

    /**
     * Transform or Filter a message. Return BroadcastAction(ACTION.ABORT, message)
     * {@link Broadcaster} to discard the message, e.g to not broadcast it.
     *
     * @param originalMessage The original message which was {@link Broadcaster#broadcast(Object)};
     * @param message         Object a message
     * @return a transformed message.
     */
    BroadcastAction filter(Object originalMessage, Object message);

When invoking Broadcaster#broadcast, the list of BroadcastFilter are serialized invoked, giving an application a chance to play with the message before it gets delivered to the browser. The list of BroadcastFilter are always invoked first, followed by PerrequestBroadcastFilter. A BroadcastAction is used to tell the framework to deliver or not the message to the browser. As an example, the following BroadcastFilter accumulates String until it large enough, reducing the number of write operation:

public class StringFilterAggregator implements BroadcastFilter {

    private final int maxBufferedString;

    private final AtomicReference<StringBuilder> bufferedMessage = new AtomicReference<StringBuilder>(new StringBuilder());

    public StringFilterAggregator() {
        maxBufferedString = 256;
    }

    public StringFilterAggregator(int maxBufferedString) {
        this.maxBufferedString = maxBufferedString;
    }

    public BroadcastAction filter(Object originalMessage, Object message) {
        if (message instanceof String) {
            bufferedMessage.get().append(message);
            if (bufferedMessage.get().length() < maxBufferedString) {
                return new BroadcastAction(ACTION.ABORT, message);
            } else {
                message = bufferedMessage.toString();
                bufferedMessage.get().delete(0, bufferedMessage.get().length());
                return new BroadcastAction(ACTION.CONTINUE, message);
            }
        } else {
            return new BroadcastAction(message);
        }
    }
}

Until the maxBufferedString size is reached, messages will be buffered. BroadcastAction are simply defined as

    public class BroadcastAction {

        private final ACTION a;
        private final Object o;
        private Object originalMsg;

        public enum ACTION {
            CONTINUE, ABORT
        }

        public BroadcastAction(ACTION a, Object o) {
            this.a = a;
            this.o = o;
        }

        public BroadcastAction(Object o) {
            this.a = ACTION.CONTINUE;
            this.o = o;
        }

        public Object message() {
            return o;
        }

        public ACTION action() {
            return a;
        }

        public Object originalMessage() {
            return originalMsg;
        }

        void setOriginalMsg(Object originalMsg) {
            this.originalMsg = originalMsg;
        }
    }

The PerRequestBroadcastFilter extends BroadcastFilter by allowing to manipulate the AtmosphereResource associated with the Browser. This is useful when you need to customize message based on some headers, browsers (like user-agent), etc. The API is defined as:

public interface PerRequestBroadcastFilter extends BroadcastFilter {

    /**
     * Transform or Filter a message per request, with V as an indicator. Be careful when setting headers on the
     * {@link AtmosphereResponse} as the headers may have been already sent back to the browser.
     *
     *
     * @param atmosphereResource
     * @param message  Object a message
     * @param originalMessage The original message that was broadcasted.
     * @return a transformed message.
     */
    BroadcastAction filter(AtmosphereResource atmosphereResource, Object originalMessage, Object message);
}

As an example, the following PerRequestBroadcastFilter customizes the message using the JSONP technique

public class JSONPTransportFilter implements PerRequestBroadcastFilter {
    @Override
    public BroadcastAction filter(HttpServletRequest request, HttpServletResponse response, Object message) {

        String s = request.getParameter(HeaderConfig.JSONP_CALLBACK_NAME);
        if (s != null) {
            String jsonPMessage = s + "({"message" :  + message})";
            return new BroadcastAction(jsonPMessage);
        }

        return new BroadcastAction(message);
    }

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

BroadcastFilter and PerRequestBroadcastFilter can be added programmatically using the following:

   Broadcaster b = BroadcasterFactory.getDefault()....;
   b.getBroadcastConfig().addFilter(new BroadcastFilter());

or using web.xml

        <init-param>
            <param-name>org.atmosphere.cpr.broadcastFilterClasses</param-name>
            <param-value>//coma separated list of BroadcastFilter</param-value>
        </init-param>

or in atmosphere.xml

        <applicationConfig>
            <param-name>org.atmosphere.cpr.broadcastFilterClasses</param-name>
            <param-value>//coma separated list of BroadcastFilter</param-value>
        </applicationConfig>

When defined in web/atmosphere.xml, the list of BroadcastFilter are added to all new instance of Broadcaster.

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