Skip to content

Instantly share code, notes, and snippets.

@wbspry
Created August 11, 2014 03:09
Show Gist options
  • Save wbspry/d6649cd643505c819ea9 to your computer and use it in GitHub Desktop.
Save wbspry/d6649cd643505c819ea9 to your computer and use it in GitHub Desktop.
Playframework付属のサンプル'websocket-chat'を見てみる(4/4) ref: http://qiita.com/yyyske/items/a6f5090f555038d6ff01
package models;
import play.mvc.*;
import play.libs.*;
import play.libs.F.*;
import scala.concurrent.Await;
import scala.concurrent.duration.Duration;
import akka.actor.*;
import static akka.pattern.Patterns.ask;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import java.util.*;
import static java.util.concurrent.TimeUnit.*;
/**
* A chat room is an Actor.
*/
public class ChatRoom extends UntypedActor {
// Default room.
static ActorRef defaultRoom = Akka.system().actorOf(Props.create(ChatRoom.class));
// Create a Robot, just for fun.
static {
new Robot(defaultRoom);
}
/**
* Join the default room.
*/
public static void join(final String username, WebSocket.In<JsonNode> in, WebSocket.Out<JsonNode> out) throws Exception{
// Send the Join message to the room
String result = null;
result = (String)Await.result(ask(defaultRoom,new Join(username, out), 1000), Duration.create(1, SECONDS));
if("OK".equals(result)) {
// For each event received on the socket,
in.onMessage(new Callback<JsonNode>() {
public void invoke(JsonNode event) {
// Send a Talk message to the room.
defaultRoom.tell(new Talk(username, event.get("text").asText()), null);
}
});
// When the socket is closed.
in.onClose(new Callback0() {
public void invoke() {
// Send a Quit message to the room.
defaultRoom.tell(new Quit(username), null);
}
});
} else {
// Cannot connect, create a Json error.
ObjectNode error = Json.newObject();
error.put("error", result);
// Send the error to the socket.
out.write(error);
}
}
// Members of this room.
Map<String, WebSocket.Out<JsonNode>> members = new HashMap<String, WebSocket.Out<JsonNode>>();
public void onReceive(Object message) throws Exception {
if(message instanceof Join) {
// Received a Join message
Join join = (Join)message;
// Check if this username is free.
if(members.containsKey(join.username)) {
getSender().tell("This username is already used", getSelf());
} else {
members.put(join.username, join.channel);
notifyAll("join", join.username, "has entered the room");
getSender().tell("OK", getSelf());
}
} else if(message instanceof Talk) {
// Received a Talk message
Talk talk = (Talk)message;
notifyAll("talk", talk.username, talk.text);
} else if(message instanceof Quit) {
// Received a Quit message
Quit quit = (Quit)message;
members.remove(quit.username);
notifyAll("quit", quit.username, "has left the room");
} else {
unhandled(message);
}
}
// Send a Json event to all members
public void notifyAll(String kind, String user, String text) {
for(WebSocket.Out<JsonNode> channel: members.values()) {
ObjectNode event = Json.newObject();
event.put("kind", kind);
event.put("user", user);
event.put("message", text);
ArrayNode m = event.putArray("members");
for(String u: members.keySet()) {
m.add(u);
}
channel.write(event);
}
}
// -- Messages
public static class Join {
final String username;
final WebSocket.Out<JsonNode> channel;
public Join(String username, WebSocket.Out<JsonNode> channel) {
this.username = username;
this.channel = channel;
}
}
public static class Talk {
final String username;
final String text;
public Talk(String username, String text) {
this.username = username;
this.text = text;
}
}
public static class Quit {
final String username;
public Quit(String username) {
this.username = username;
}
}
}
package models;
import play.*;
import play.mvc.*;
import play.libs.*;
import scala.concurrent.duration.*;
import akka.actor.*;
import com.fasterxml.jackson.databind.JsonNode;
import static java.util.concurrent.TimeUnit.*;
public class Robot {
public Robot(ActorRef chatRoom) {
// Create a Fake socket out for the robot that log events to the console.
WebSocket.Out<JsonNode> robotChannel = new WebSocket.Out<JsonNode>() {
public void write(JsonNode frame) {
Logger.of("robot").info(Json.stringify(frame));
}
public void close() {}
};
// Join the room
chatRoom.tell(new ChatRoom.Join("Robot", robotChannel), null);
// Make the robot talk every 30 seconds
Akka.system().scheduler().schedule(
Duration.create(30, SECONDS),
Duration.create(30, SECONDS),
chatRoom,
new ChatRoom.Talk("Robot", "I'm still alive"),
Akka.system().dispatcher(),
/** sender **/ null
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment