播放1.3事件流实现

时间:2015-01-20 14:25:47

标签: java playframework playframework-1.x server-sent-events

所以我一直在尝试使用Play Framework 1.3实现正确的EventStream解决方案,但是我无法让它正常工作。一个例外不断被抛出,但我不确定原因是什么。

任何人都可以提供示例实现或指向我吗?

这是我控制器中的方法。

public static void stream() {
    response.contentType = "text/event-stream";
    response.encoding = "UTF-8";
    response.status = 200;
    response.chunked = true;

    // a record of the last ID that this request... requested
    Long lastId = 0L;

    // since this request has only been initiated, the first thing to do is return a list of whats in the queue
    List<F.IndexedEvent> archive = StreamQueue.getRecentNotifications(lastId);
    if (!archive.isEmpty()) {
        // write that list out in the response
        response.writeChunk(//a string representing the entire list as a single event);
        // update out internal reference to the lastId
        lastId = archive.get(archive.size() - 1).id;
    }

    // keep this connection alive
    while (true) {
        // await the promise of more notifications for the stream
        List<F.IndexedEvent<StreamQueue.Notification>> notifications = await(StreamQueue.getNextNotification(lastId));
        // for each notification, write it out as a separate event
        for (int i = 0; i < notifications.size(); i++) {
            response.writeChunk(//a string representing a single event using notifications.get(i));
            // update out internal reference to the lastId
            lastId = notifications.get(i).id;
        }
    }
}

这是我对队列StreamQueue.java的实现:

public class StreamQueue {
    final ArchivedEventStream<StreamQueue.Notification> notifications = new ArchivedEventStream<StreamQueue.Notification>(100);
    static StreamQueue instance = null;

    public static StreamQueue get() {
        if(instance == null) {
            instance = new StreamQueue();
        }
        return instance;
    }

    // the method to call when I want to send an event
    public static void alert(Notification.Type type, Object... args){
        get().addMessage((String) args[0]);
    }

    public static F.Promise<java.util.List<F.IndexedEvent<Notification>>> getNextNotification(Long lastId) {
        return get().getNotificationsStream().nextEvents(lastId);
    }

    public static java.util.List<F.IndexedEvent> getRecentNotifications(Long lastId) {
        return get().getNotificationsStream().availableEvents(lastId);
    }

    public ArchivedEventStream<StreamQueue.Notification> getNotificationsStream() {
        return notifications;
    }

    private void addMessage(String message){
        notifications.publish(new StreamQueue.MessageEvent(message));
    }


    public static abstract class Notification extends F.IndexedEvent {
        public enum Type {
            ISSUE,
            MESSAGE;
        }

        final public Type type;
        final public Long timestamp;

        public Notification(Type type) {
            super(type);
            this.type = type;
            this.timestamp = System.currentTimeMillis();
        }

        public Long getId() {
            return this.id;
        }

        public String toJson() {
            return new JSONSerializer().exclude("class").serialize(this);
        }
    }

    public static class MessageEvent extends StreamQueue.Notification {
        public final String message;

        public MessageEvent(String message) {
            super(Type.MESSAGE);
            this.message = message;
        }

        public String toJson() {
            return new JSONSerializer().include("message").exclude("*").serialize(this);
        }
    }

}

最后,我得到了例外:

Internal Server Error (500) for request GET /stream

Execution exception
InvocationTargetException occured : null

play.exceptions.JavaExecutionException
    at play.mvc.ActionInvoker.invoke(ActionInvoker.java:230)
    at Invocation.HTTP Request(Play!)
Caused by: java.lang.reflect.InvocationTargetException
    at play.mvc.ActionInvoker.invokeWithContinuation(ActionInvoker.java:524)
    at play.mvc.ActionInvoker.invoke(ActionInvoker.java:475)
    at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:451)
    at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:446)
    at play.mvc.ActionInvoker.invoke(ActionInvoker.java:160)
    ... 1 more
Caused by: java.lang.ClassCastException: java.lang.Long cannot be cast to java.util.Map
    at controllers.StreamController.stream(StreamController.java)
    ... 6 more

ArchivedEventStream.nextEvents(...)呼叫的StreamQueue.getNextNotification(...)似乎引发了异常。原因似乎是Long被投射到Map,但我决不尝试这样做。

提前感谢您的帮助!

更新 所以我在Play 1.2.5中尝试了我的项目,并且流媒体工作完美。但是,该项目要求我们使用Play 1.3。

1 个答案:

答案 0 :(得分:0)

原因位于堆栈跟踪的底部:

Caused by: java.lang.ClassCastException: java.lang.Long cannot be cast to java.util.Map

我认为您正在尝试将Notification.timestamp投射到地图StreamController