Exchanging messages over WebSockets in the default desktop client NewChat
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Fri, 22 Apr 2016 18:13:09 +0200
branchNewChat
changeset 24258596208d06d
parent 241 6a59fdb91011
Exchanging messages over WebSockets in the default desktop client
chat/client/src/main/java/org/apidesign/demo/chat/ChatClient.java
chat/server/src/main/java/org/apidesign/demo/chat/server/ChatServerResource.java
chat/shared/src/main/java/org/apidesign/demo/chat/shared/MessageImpl.java
     1.1 --- a/chat/client/src/main/java/org/apidesign/demo/chat/ChatClient.java	Fri Apr 22 08:58:08 2016 +0200
     1.2 +++ b/chat/client/src/main/java/org/apidesign/demo/chat/ChatClient.java	Fri Apr 22 18:13:09 2016 +0200
     1.3 @@ -57,21 +57,23 @@
     1.4          Message msg = new Message();
     1.5          msg.setUser(m.getUser());
     1.6          msg.setComment(m.getComment());
     1.7 -        m.socket(m.getUrl(), new Query().assignPost(msg));
     1.8 +        m.socket(m.getUrl(), new Query().requestPost(msg));
     1.9      }
    1.10      
    1.11      static void cantChat(ChatModel model, Exception err) {
    1.12          model.getMsgs().add(new Message("System", err.getMessage(), 0));
    1.13      }
    1.14      
    1.15 -    
    1.16      @OnReceive(url = "{url}/chat", method = "WebSocket", data = Query.class, onError = "cantChat")
    1.17      static void socket(ChatModel m, Reply reply) {
    1.18          if (reply == null) {
    1.19              m.getMsgs().add(new Message("System", "Connected to server at " + m.getUrl() + "/chat!", 0));
    1.20 +            m.socket(m.getUrl(), new Query().requestAll(true).requestPost(null));
    1.21              return;
    1.22          }
    1.23 -        m.getMsgs().clear();
    1.24 +        if (reply.isAll()) {
    1.25 +            m.getMsgs().clear();
    1.26 +        }
    1.27          m.getMsgs().addAll(reply.getMessages());
    1.28      }
    1.29      
     2.1 --- a/chat/server/src/main/java/org/apidesign/demo/chat/server/ChatServerResource.java	Fri Apr 22 08:58:08 2016 +0200
     2.2 +++ b/chat/server/src/main/java/org/apidesign/demo/chat/server/ChatServerResource.java	Fri Apr 22 18:13:09 2016 +0200
     2.3 @@ -26,12 +26,16 @@
     2.4  import java.io.ByteArrayInputStream;
     2.5  import java.io.IOException;
     2.6  import java.util.ArrayList;
     2.7 +import java.util.HashSet;
     2.8  import java.util.List;
     2.9 +import java.util.Set;
    2.10  import java.util.logging.Logger;
    2.11  import net.java.html.BrwsrCtx;
    2.12  import net.java.html.json.Models;
    2.13  import org.apidesign.demo.chat.shared.Message;
    2.14  import org.apidesign.demo.chat.shared.Query;
    2.15 +import org.apidesign.demo.chat.shared.Reply;
    2.16 +import org.glassfish.grizzly.websockets.DataFrame;
    2.17  import org.glassfish.grizzly.websockets.WebSocket;
    2.18  import org.glassfish.grizzly.websockets.WebSocketApplication;
    2.19  
    2.20 @@ -50,8 +54,8 @@
    2.21      }
    2.22  
    2.23  
    2.24 +    private final Set<WebSocket> connected = new HashSet<>();
    2.25  /*
    2.26 -    private final Map<AsyncResponse, Long> awaiting = new IdentityHashMap<>();
    2.27      
    2.28      @Produces(MediaType.APPLICATION_JSON)
    2.29      @GET public synchronized void getResources(
    2.30 @@ -70,38 +74,45 @@
    2.31              awaiting.put(ar, since);
    2.32          }
    2.33      }
    2.34 -    
    2.35 -    private void handleAwaiting(long newest) {
    2.36 +    */
    2.37 +    private void handleAwaiting(Message msg) {
    2.38          assert Thread.holdsLock(this);
    2.39 -        AGAIN: for (;;) {
    2.40 -            for (Map.Entry<AsyncResponse, Long> entry : awaiting.entrySet()) {
    2.41 -                AsyncResponse ar = entry.getKey();
    2.42 -                Long since = entry.getValue();
    2.43 -                if (since <= newest) {
    2.44 -                    awaiting.remove(ar);
    2.45 -                    getResources(since, ar);
    2.46 -                    continue AGAIN;
    2.47 -                }
    2.48 -            }
    2.49 -            return;
    2.50 +        Reply reply = new Reply();
    2.51 +        reply.getMessages().add(msg);
    2.52 +        String txt = reply.toString();
    2.53 +        for (WebSocket webSocket : connected) {
    2.54 +            webSocket.send(txt);
    2.55          }
    2.56      }
    2.57 -    
    2.58 -    @POST @Consumes(value = MediaType.APPLICATION_JSON)
    2.59 -    public synchronized Message publish(Message msg) {
    2.60 +
    2.61 +    private synchronized Message publish(Message msg) {
    2.62          msg.setSince(System.currentTimeMillis() - started);
    2.63          msgs.add(msg);
    2.64 -        handleAwaiting(msg.getSince());
    2.65 +        handleAwaiting(msg);
    2.66          return msg;
    2.67      }
    2.68 -*/
    2.69 +
    2.70 +    @Override
    2.71 +    public void onConnect(WebSocket socket) {
    2.72 +        connected.add(socket);
    2.73 +    }
    2.74 +
    2.75 +    @Override
    2.76 +    public void onClose(WebSocket socket, DataFrame frame) {
    2.77 +        connected.remove(socket);
    2.78 +    }
    2.79  
    2.80      @Override
    2.81      public void onMessage(WebSocket socket, String text) {
    2.82          try {
    2.83              ByteArrayInputStream is = new ByteArrayInputStream(text.getBytes("UTF-8"));
    2.84              Query q = Models.parse(BrwsrCtx.findDefault(ChatServerResource.class), Query.class, is);
    2.85 -            super.onMessage(socket, text);
    2.86 +            if (q.getPost() != null) {
    2.87 +                publish(q.getPost());
    2.88 +            }
    2.89 +            if (q.isAll()) {
    2.90 +                socket.send(new Reply(true, msgs.toArray(new Message[0])).toString());
    2.91 +            }
    2.92          } catch (IOException ex) {
    2.93              throw new IllegalStateException(ex);
    2.94          }
     3.1 --- a/chat/shared/src/main/java/org/apidesign/demo/chat/shared/MessageImpl.java	Fri Apr 22 08:58:08 2016 +0200
     3.2 +++ b/chat/shared/src/main/java/org/apidesign/demo/chat/shared/MessageImpl.java	Fri Apr 22 18:13:09 2016 +0200
     3.3 @@ -51,15 +51,15 @@
     3.4          return delta + "min";
     3.5      }
     3.6  
     3.7 -    @Model(className = "Query", builder = "assign", properties = {
     3.8 -        @Property(name = "since", type = int.class),
     3.9 +    @Model(className = "Query", builder = "request", properties = {
    3.10 +        @Property(name = "all", type = boolean.class),
    3.11          @Property(name = "post", type = Message.class),
    3.12      })
    3.13      class QueryCntrl {
    3.14      }
    3.15      
    3.16      @Model(className = "Reply", properties = {
    3.17 -        @Property(name = "since", type = int.class),
    3.18 +        @Property(name = "all", type = boolean.class),
    3.19          @Property(name = "messages", type = Message.class, array = true)
    3.20      })
    3.21      class ReplyCntrl {