Created
August 11, 2014 03:09
-
-
Save wbspry/d6649cd643505c819ea9 to your computer and use it in GitHub Desktop.
Playframework付属のサンプル'websocket-chat'を見てみる(4/4) ref: http://qiita.com/yyyske/items/a6f5090f555038d6ff01
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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