Commit bfd40f6f authored by Will Billingsley's avatar Will Billingsley
Browse files

Morphed the code into a starter for the project

I've added a couple of examples to the project -- some simple code calling Akka actors, and some code for calling web services.
parent 2b2c135e
package actors;
import akka.actor.ActorRef;
import akka.actor.Props;
import akka.actor.UntypedActor;
/**
* A rather trivial Actor that just plays FizzBuzz
*/
public class FizzBuzzActor extends UntypedActor {
int nextNum = 0;
/**
* The marshall. We'll also send them the messages
*/
ActorRef marshallActor;
/**
*
*/
public static Props props = Props.create(FizzBuzzActor.class);
@Override
public void onReceive(Object message) {
if (message.equals("Marshall")) {
/*
* We're given the marshall's ActorRef by a message saying "Marshall". The Marshall will appear
* to be the sender (even though it's actually been sent by Setup)
*/
marshallActor = getSender();
} else if (message instanceof ActorRef) {
// If we're sent an ActorRef, that's the marshall telling us who our opponent is and to get started
((ActorRef) message).tell(1, getSelf());
marshallActor.tell(1, getSelf());
} else if (message instanceof Integer) {
nextNum = (Integer) message + 1;
reply();
} else {
nextNum = nextNum + 2;
// Stop at 1000 so we don't blow the heap by writing forever into a StringBuilder
if (nextNum < 1000) {
reply();
}
}
}
void reply() {
if (nextNum % 15 == 0) {
getSender().tell("fizzbuzz", getSelf());
marshallActor.tell("fizzbuzz", getSelf());
} else if (nextNum % 5 == 0) {
getSender().tell("buzz", getSelf());
marshallActor.tell("buzz", getSelf());
} else if (nextNum % 3 == 0) {
getSender().tell("fizz", getSelf());
marshallActor.tell("fizz", getSelf());
} else {
getSender().tell(nextNum, getSelf());
marshallActor.tell(nextNum, getSelf());
}
// Put this Actor to sleep for 250ms before it checks its next message
try {
Thread.sleep(250);
} catch (InterruptedException ex) {
// do nothing
}
}
}
package actors;
import akka.actor.ActorSystem;
import akka.actor.Props;
import akka.actor.UntypedActor;
import javax.inject.Inject;
/**
* You might or might not want this actor in the end. In this example, its role is to be the central point of
* contact between your web app and the actor system that might be receiving outside events.
*/
public class MarshallActor extends UntypedActor {
StringBuilder messages = new StringBuilder();
public static Props props = Props.create(MarshallActor.class);
public MarshallActor() {
}
@Override
public void onReceive(Object message) {
if (message.equals("Report!")) {
getSender().tell(messages.toString(), getSelf());
} else {
messages.append(getSender().toString());
messages.append(" said ");
messages.append(message);
messages.append("\n");
}
}
}
package actors;
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import javax.inject.Inject;
import javax.inject.Singleton;
/**
* Holds all the "famous" Actors in our system. This hopefully makes things convenient, because if you @Inject Setup,
* you'll then be able to look up ActorRefs to all the actors just by Setup.marshallActor, etc.
*
* It's a Singleton, so Google Guice will only create one of these for us.
*/
@Singleton
public class Setup {
/**
* This is a reference to an Actor
*/
public final ActorRef marshallActor;
@Inject
public Setup(ActorSystem system) {
marshallActor = system.actorOf(MarshallActor.props);
ActorRef fb1 = system.actorOf(FizzBuzzActor.props, "Player1");
ActorRef fb2 = system.actorOf(FizzBuzzActor.props, "Player2");
fb1.tell("Marshall", marshallActor);
fb2.tell("Marshall", marshallActor);
fb1.tell(fb2, fb2);
}
}
\ No newline at end of file
package controllers;
import model.BCryptExample;
import model.Captcha;
import actors.Setup;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import play.mvc.Controller;
import play.mvc.Result;
import scala.compat.java8.FutureConverters;
import play.libs.ws.*;
import java.util.Arrays;
import java.util.concurrent.CompletionStage;
import static akka.pattern.Patterns.ask;
@Singleton
public class Application extends Controller {
public static Result index() {
int arrayLength = 5;
int[] indexes = new int[arrayLength];
for (int i = 0; i < arrayLength; i++) {
indexes[i] = (int)(Captcha.numPhotos() * Math.random());
}
Setup actorSetup;
return ok(views.html.application.index.render(indexes));
}
WSClient wsClient;
private static int countBeagles(String[] indexes) {
int i = 0;
for (String s : indexes) {
if (Captcha.isCorrect(Integer.valueOf(s))) {
i++;
}
}
return i;
@Inject
public Application(Setup actorSetup, WSClient wsClient) {
this.actorSetup = actorSetup;
this.wsClient = wsClient;
}
public static Result matches() {
String[] sent = request().body().asFormUrlEncoded().get("sent");
String[] beagles = request().body().asFormUrlEncoded().get("beagle");
int numBeagles = countBeagles(sent);
int numFound = countBeagles(beagles);
return ok(views.html.application.matches.render(numBeagles, numFound));
/**
* Play framework suppors asynchronous controller methods -- that is, methods that instead of returning a Result
* return a CompletionStage, which will produce a Result some time in the future
*/
public CompletionStage<Result> index() {
/*
* This code might look a little complex.
*
* ask sends a message to an ActorRef, and then returns a Future that will eventually contain the response.
* But Future is a Scala class, so FutureConverters.toJava converts it into a CompletionStage, which is Java's equivalent.
* thenApply is a method on CompletionStage that means "when you get the result, do this with it, and return a new CompletionStage"
*/
return FutureConverters.toJava(ask(actorSetup.marshallActor, "Report!", 1000))
.thenApply(response -> ok(response.toString()));
}
/**
* This controller method uses Play's Web Service client to make another HTTP call, and do something with the
* response
*/
public CompletionStage<Result> whatDidGitLabSay() {
return wsClient.url("http://www.une.edu.au/foo").get().thenApply(r -> ok(r.getStatusText()));
}
}
......@@ -2,10 +2,14 @@ name := "chirper"
version := "1.0"
scalaVersion := "2.11.6"
scalaVersion := "2.11.7"
lazy val root = (project in file(".")).enablePlugins(PlayJava)
routesGenerator := InjectedRoutesGenerator
libraryDependencies ++= Seq(
javaWs,
"org.mindrot" % "jbcrypt" % "0.3m"
)
......@@ -3,7 +3,7 @@
# ~~~~
GET / controllers.Application.index()
POST /matches controllers.Application.matches()
GET /ws controllers.Application.whatDidGitLabSay()
# Map static resources from the /public folder to the /assets URL path
GET /assets/*file controllers.Assets.versioned(path="/public", file: Asset)
\ No newline at end of file
// Use the Play sbt plugin for Play projects
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.4.2")
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.5.4")
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment