diff --git a/README b/README index 96a8d1d..e69de29 100644 --- a/README +++ b/README @@ -1,4 +0,0 @@ -This is your new Play 2.1 application -===================================== - -This file will be packaged with your application, when using `play dist`. diff --git a/app/Global.scala b/app/Global.scala deleted file mode 100644 index 27091b7..0000000 --- a/app/Global.scala +++ /dev/null @@ -1,11 +0,0 @@ -import play.api._ -import model._ - -object Global extends GlobalSettings { - override def onStart(app: Application) { - // LookupApplication.startup() - } - override def onStop(app: Application) { - // LookupApplication.shutdown() - } -} \ No newline at end of file diff --git a/app/controllers/Application.scala b/app/controllers/Application.scala index e08678d..2db19c4 100644 --- a/app/controllers/Application.scala +++ b/app/controllers/Application.scala @@ -15,10 +15,7 @@ import akka.util.Timeout import akka.pattern.ask import model._ - -import ca.polymtl.log4900.eval.Add -import ca.polymtl.log4900.eval.MathResult -import ca.polymtl.log4900.eval.AddResult +import ca.polymtl.log4900.api._ object Application extends Controller { implicit val timeout = Timeout(5 seconds) @@ -31,18 +28,14 @@ object Application extends Controller { val (enumerator, channel) = Concurrent.broadcast[JsValue] val in = Iteratee.foreach[JsValue](content => { - val op1 = (content \ "op1").as[Int] - val op2 = (content \ "op2").as[Int] - - (LookupApplication.actor ? Add(1, 1)).mapTo[MathResult] onComplete { - case(e) => println("fail") - } -// } onSuccess { -// case AddResult(o1,o2,res) => println(s"$o1 + $o2 = $res") -// } - }) - + val firstName = (content \ "firstName").as[String] + val lastName = (content \ "lastName").as[String] + + EvalService.client.hello(User(firstName, lastName)).map(r => { + println(r) + channel.push(JsObject(Seq("response" -> JsString(r)))) + }) + }) (in, enumerator) } - } \ No newline at end of file diff --git a/app/model/Calculator.scala b/app/model/Calculator.scala deleted file mode 100644 index e118860..0000000 --- a/app/model/Calculator.scala +++ /dev/null @@ -1,50 +0,0 @@ -package model; - -import scala.util.Random -import scala.concurrent.duration._ -import com.typesafe.config.ConfigFactory -import akka.actor.{ ActorRef, Props, Actor, ActorSystem } -import akka.actor.Identify -import akka.actor.ActorIdentity -import akka.kernel.Bootable -import akka.actor.ReceiveTimeout - -import ca.polymtl.log4900.eval._ - -object LookupApplication extends Bootable { - lazy val system = ActorSystem("LookupApplication", ConfigFactory.load.getConfig("remotelookup")) - lazy val remotePath = "akka.tcp://CalculatorApplication@127.0.0.1:2552/user/simpleCalculator" - lazy val actor = system.actorOf(Props(classOf[LookupActor], remotePath), "lookupActor") - - def doSomething(op: MathOp): Unit = actor ! op - - def startup() { } - def shutdown() { system.shutdown() } -} - -class LookupActor(path: String) extends Actor { - - context.setReceiveTimeout(3.seconds) - sendIdentifyRequest() - - def sendIdentifyRequest(): Unit = context.actorSelection(path) ! Identify(path) - - def receive = { - case ActorIdentity(`path`, Some(actor)) ⇒ - context.setReceiveTimeout(Duration.Undefined) - context.become(active(actor)) - case ActorIdentity(`path`, None) ⇒ println(s"Remote actor not availaible: $path") - case ReceiveTimeout ⇒ sendIdentifyRequest() - case _ ⇒ println("Not ready yet") - } - - def active(actor: ActorRef): Actor.Receive = { - case op: MathOp ⇒ actor ! op - case result: MathResult ⇒ result match { - case AddResult(n1, n2, r) ⇒ printf("Add result: %d + %d = %d\n", n1, n2, r) - case SubtractResult(n1, n2, r) ⇒ printf("Sub result: %d - %d = %d\n", n1, n2, r) - case MultiplicationResult(n1, n2, r) ⇒ printf("Multiplication result: %d + %d = %d\n", n1, n2, r) - case DivisionResult(n1, n2, r) ⇒ printf("Division result: %d - %d = %d\n", n1, n2, r) - } - } -} \ No newline at end of file diff --git a/app/model/EvalService.scala b/app/model/EvalService.scala new file mode 100644 index 0000000..ad3fe0e --- /dev/null +++ b/app/model/EvalService.scala @@ -0,0 +1,18 @@ +package model; + +import ca.polymtl.log4900.api._ + +import com.twitter.finagle._ +import builder.ClientBuilder +import thrift.ThriftClientFramedCodec + +object EvalService { + + private lazy val service = ClientBuilder() + .hosts(s"${Config.host}:${Config.port}") + .codec(ThriftClientFramedCodec()) + .hostConnectionLimit(1) + .build() + + lazy val client = new HelloUser.FinagledClient(service) +} \ No newline at end of file diff --git a/app/views/index.scala.html b/app/views/index.scala.html index ea2136f..9b221c9 100644 --- a/app/views/index.scala.html +++ b/app/views/index.scala.html @@ -2,9 +2,11 @@ @main("Hey") {
- + +

say hi

+ + - + result
}{ diff --git a/conf/application.conf b/conf/application.conf index e10f0ad..49ccba8 100644 --- a/conf/application.conf +++ b/conf/application.conf @@ -1,74 +1,5 @@ -# This is the main configuration file for the application. -# ~~~~~ - -# Secret key -# ~~~~~ -# The secret key is used to secure cryptographics functions. -# If you deploy your application to several instances be sure to use the same key! application.secret="8aM/[QwT<[40sWC;l^LXDMBDciBjC7inppKGfJkr?ffYDNd=ralJ9uUggtTBEC23" - -# The application languages -# ~~~~~ application.langs="en" - -# Global object class -# ~~~~~ -# Define the Global object class for this application. -# Default to Global in the root package. -# application.global=Global - -# Router -# ~~~~~ -# Define the Router object to use for this application. -# This router will be looked up first when the application is starting up, -# so make sure this is the entry point. -# Furthermore, it's assumed your route file is named properly. -# So for an application router like `my.application.Router`, -# you may need to define a router file `conf/my.application.routes`. -# Default to Routes in the root package (and conf/routes) -# application.router=my.application.Routes - -# Database configuration -# ~~~~~ -# You can declare as many datasources as you want. -# By convention, the default datasource is named `default` -# -# db.default.driver=org.h2.Driver -# db.default.url="jdbc:h2:mem:play" -# db.default.user=sa -# db.default.password="" - -# Evolutions -# ~~~~~ -# You can disable evolutions if needed -# evolutionplugin=disabled - -# Logger -# ~~~~~ -# You can also configure logback (http://logback.qos.ch/), by providing a logger.xml file in the conf directory . - -# Root logger: logger.root=ERROR - -# Logger used by the framework: logger.play=INFO - -# Logger provided to your application: -logger.application=DEBUG - -calculator { - include "common" - - akka { - # LISTEN on tcp port 2552 - remote.netty.tcp.port = 2552 - } -} - -remotelookup { - include "common" - - akka { - remote.netty.tcp.port = 2553 - } -} \ No newline at end of file +logger.application=DEBUG \ No newline at end of file diff --git a/conf/common.conf b/conf/common.conf deleted file mode 100644 index 3431218..0000000 --- a/conf/common.conf +++ /dev/null @@ -1,21 +0,0 @@ -akka { - - actor { - provider = "akka.remote.RemoteActorRefProvider" - } - - remote { - netty.tcp { - hostname = "127.0.0.1" - } - } - - # Uncomment the following four lines to employ the 'secure cookie handshake' - # This requires the client to have the known secure-cookie and properly - # transmit it to the server upon connection. Because both the client and server - # programs use this common.conf file, they will both have the cookie - #remote { - # secure-cookie = "0009090D040C030E03070D0509020F050B080400" - # require-cookie = on - #} -} diff --git a/conf/routes b/conf/routes index 794207d..fad5d51 100644 --- a/conf/routes +++ b/conf/routes @@ -1,6 +1,4 @@ GET / controllers.Application.index GET /eval controllers.Application.eval - - GET /assets/*file controllers.Assets.at(path="/public", file) GET /webjars/*file controllers.WebJarAssets.at(file) \ No newline at end of file diff --git a/modules/api/src/main/java/ca.polymtl.log4900.api/Config.java b/modules/api/src/main/java/ca.polymtl.log4900.api/Config.java new file mode 100644 index 0000000..61cc2f5 --- /dev/null +++ b/modules/api/src/main/java/ca.polymtl.log4900.api/Config.java @@ -0,0 +1,6 @@ +package ca.polymtl.log4900.api; + +public class Config { + public static final String host = "localhost"; + public static final int port = 8001; +} \ No newline at end of file diff --git a/modules/api/src/main/thrift/ca.polymtl.log4900.api/api.thrift b/modules/api/src/main/thrift/ca.polymtl.log4900.api/api.thrift new file mode 100644 index 0000000..ab00714 --- /dev/null +++ b/modules/api/src/main/thrift/ca.polymtl.log4900.api/api.thrift @@ -0,0 +1,10 @@ +namespace scala ca.polymtl.log4900.api + +struct User { + 1: string firstName, + 2: string lastName +} + +service HelloUser { + string hello(1: User user) +} \ No newline at end of file diff --git a/modules/eval/src/main/resources/application.conf b/modules/eval/src/main/resources/application.conf deleted file mode 100644 index e84cf87..0000000 --- a/modules/eval/src/main/resources/application.conf +++ /dev/null @@ -1,16 +0,0 @@ -calculator { - include "common" - - akka { - # LISTEN on tcp port 2552 - remote.netty.tcp.port = 2552 - } -} - -remotelookup { - include "common" - - akka { - remote.netty.tcp.port = 2553 - } -} \ No newline at end of file diff --git a/modules/eval/src/main/resources/common.conf b/modules/eval/src/main/resources/common.conf deleted file mode 100644 index 3431218..0000000 --- a/modules/eval/src/main/resources/common.conf +++ /dev/null @@ -1,21 +0,0 @@ -akka { - - actor { - provider = "akka.remote.RemoteActorRefProvider" - } - - remote { - netty.tcp { - hostname = "127.0.0.1" - } - } - - # Uncomment the following four lines to employ the 'secure cookie handshake' - # This requires the client to have the known secure-cookie and properly - # transmit it to the server upon connection. Because both the client and server - # programs use this common.conf file, they will both have the cookie - #remote { - # secure-cookie = "0009090D040C030E03070D0509020F050B080400" - # require-cookie = on - #} -} diff --git a/modules/eval/src/main/scala/ca.polymtl.log4900.eval/Server.scala b/modules/eval/src/main/scala/ca.polymtl.log4900.eval/Server.scala index 504ee72..2303747 100644 --- a/modules/eval/src/main/scala/ca.polymtl.log4900.eval/Server.scala +++ b/modules/eval/src/main/scala/ca.polymtl.log4900.eval/Server.scala @@ -1,49 +1,49 @@ -package ca.polymtl.log4900.eval - -import akka.kernel.Bootable -import akka.actor.{ Props, Actor, ActorSystem } -import com.typesafe.config._ - -class SimpleCalculatorActor extends Actor { - def receive = { - case Add(n1, n2) ⇒ - println("Calculating %d + %d".format(n1, n2)) - sender ! AddResult(n1, n2, n1 + n2) - case Subtract(n1, n2) ⇒ - println("Calculating %d - %d".format(n1, n2)) - sender ! SubtractResult(n1, n2, n1 - n2) - case Multiply(n1, n2) ⇒ - println("Calculating %d * %d".format(n1, n2)) - sender ! MultiplicationResult(n1, n2, n1 * n2) - case Divide(n1, n2) ⇒ - println("Calculating %.0f / %d".format(n1, n2)) - sender ! DivisionResult(n1, n2, n1 / n2) - } -} +package ca.polymtl.log4900 +package eval + +import api._ + +import com.twitter._ +import util.Future +import finagle._ +import thrift.ThriftServerFramedCodec +import builder.ServerBuilder +import builder.Server + +import org.apache.thrift.protocol.TBinaryProtocol +import java.net.InetSocketAddress + +object HelloServer { + var server = Option.empty[Server] + def start() { + val protocol = new TBinaryProtocol.Factory() + val serverService = new HelloUser.FinagledService(new HelloUserImpl, protocol) + val address = new InetSocketAddress(Config.host, Config.port) + + val s = ServerBuilder() + .codec(ThriftServerFramedCodec()) + .name("binary_service") + .bindTo(address) + .build(serverService) -class CalculatorApplication extends Bootable { - val system = ActorSystem("CalculatorApplication", ConfigFactory.load.getConfig("calculator")) - val actor = system.actorOf(Props[SimpleCalculatorActor], "simpleCalculator") + println("+++Server Started+++") + server = Some(s) + } - def startup() { } - def shutdown() { system.shutdown() } + def stop(){ + println("---Server Stoped---") + server.map(_.close()) + } } -object CalcApp { - def main(args: Array[String]) { - new CalculatorApplication - println("Started Calculator Application - waiting for messages") +class HelloUserImpl extends HelloUser.FutureIface { + def hello(user: User): Future[String] = { + val ret = "hello " + user + println(ret) + Future.value(ret) } } -trait MathOp -case class Add(nbr1: Int, nbr2: Int) extends MathOp -case class Subtract(nbr1: Int, nbr2: Int) extends MathOp -case class Multiply(nbr1: Int, nbr2: Int) extends MathOp -case class Divide(nbr1: Double, nbr2: Int) extends MathOp - -trait MathResult -case class AddResult(nbr: Int, nbr2: Int, result: Int) extends MathResult -case class SubtractResult(nbr1: Int, nbr2: Int, result: Int) extends MathResult -case class MultiplicationResult(nbr1: Int, nbr2: Int, result: Int) extends MathResult -case class DivisionResult(nbr1: Double, nbr2: Int, result: Double) extends MathResult \ No newline at end of file +object Main extends App { + HelloServer.start() +} \ No newline at end of file diff --git a/modules/eval/src/test/scala/ca.polymtl.log4900.eval/.keep b/modules/eval/src/test/scala/ca.polymtl.log4900.eval/.keep new file mode 100644 index 0000000..da2876d --- /dev/null +++ b/modules/eval/src/test/scala/ca.polymtl.log4900.eval/.keep @@ -0,0 +1 @@ +write some tests lazy you! \ No newline at end of file diff --git a/project/Build.scala b/project/Build.scala index 6a18b11..74f6b4f 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -6,17 +6,27 @@ object ApplicationBuild extends Build { import Dependencies._ - val eval = Project( - id = "eval", - base = file("modules/eval"), - settings = Settings.default ++ Project.defaultSettings ++ Seq( - libraryDependencies ++= akkaStack - ) + val api = Project( + id = "api", + base = file("modules/api"), + settings = Project.defaultSettings ++ Settings.default ++ Settings.scrooge ++ Seq( + name := "api" + ) ) - val main = play.Project( "ws", + val eval = Project( + id = "eval", + base = file("modules/eval"), + settings = Settings.default ++ Seq( + name := "eval", + libraryDependencies += finableOstrich + ) + ) dependsOn( api ) + + val main = play.Project( + "server", Settings.appVersion, - frontEnd + frontEnd ++ test ).settings(Settings.default: _*). - dependsOn(eval) -} + dependsOn(api) +} \ No newline at end of file diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 4a5f9c5..1ec69a5 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -3,22 +3,25 @@ import sbt._ object Dependencies { val akkaVersion = "2.2.1" val akka = "com.typesafe.akka" %% "akka-actor" % akkaVersion - val akkaRemote = "com.typesafe.akka" %% "akka-remote" % akkaVersion - val akkaKernel = "com.typesafe.akka" %% "akka-kernel" % akkaVersion - val akkaStack = Seq( - akka, - akkaRemote, - akkaKernel - ) + private val finagleVer = "6.5.0" + val finagleCore = "com.twitter" %% "finagle-core" % finagleVer + val finagleThrift = "com.twitter" %% "finagle-thrift" % finagleVer + val finableOstrich = "com.twitter" %% "finagle-ostrich4" % finagleVer + val scroogeRuntime = "com.twitter" %% "scrooge-runtime" % "3.9.0" - val webjars = "org.webjars" %% "webjars-play" % "2.2.0-RC1" - val bootstrap = "org.webjars" % "bootstrap" % "3.0.0" - val jquery = "org.webjars" % "jquery" % "2.0.3" + val scroogeStack = Seq( + finagleCore, + finagleThrift, + scroogeRuntime + ) val frontEnd = Seq( - webjars, - bootstrap, - jquery + "org.webjars" %% "webjars-play" % "2.2.0-RC1", + "org.webjars" % "bootstrap" % "3.0.0", + "org.webjars" % "jquery" % "2.0.3" ) + + val specs2 = "org.specs2" %% "specs2" % "2.2.2" % "test" + val test = Seq(specs2) } \ No newline at end of file diff --git a/project/Settings.scala b/project/Settings.scala index 2e33c84..2242d33 100644 --- a/project/Settings.scala +++ b/project/Settings.scala @@ -8,4 +8,12 @@ object Settings { organization := "ca.polymtl.log4900", version := appVersion ) + + // thrift + import com.twitter.scrooge._ + import ScroogeSBT._ + lazy val scrooge = ScroogeSBT.newSettings ++ Seq( + scroogeBuildOptions := Seq("--ostrich","--finagle"), + libraryDependencies ++= Dependencies.scroogeStack + ) } \ No newline at end of file diff --git a/project/build.properties b/project/build.properties index 0974fce..8cbb522 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=0.13.0 +sbt.version=0.13.0 \ No newline at end of file diff --git a/project/plugins.sbt b/project/plugins.sbt index e1aef47..f758a83 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,8 +1,9 @@ -// Comment to get more information during initialization logLevel := Level.Warn -// The Typesafe repository resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/" -// Use the Play sbt plugin for Play projects -addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.2.0") \ No newline at end of file +addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.2.0") + +//resolvers += "gui maven" at "http://masseguillaume.github.io/maven" + +addSbtPlugin("com.twitter" %% "scrooge-sbt-plugin" % "3.9.0") \ No newline at end of file diff --git a/public/javascripts/chat.js b/public/javascripts/chat.js index 6cd2b3f..4710747 100644 --- a/public/javascripts/chat.js +++ b/public/javascripts/chat.js @@ -8,15 +8,15 @@ $(function(){ chatSocket.send( JSON.stringify({ - op1: parseInt($("[name='op1']").val()), - op2: parseInt($("[name='op2']").val()) + firstName: $("[name='firstName']").val(), + lastName: $("[name='lastName']").val() }) ); return false; }); - chatSocket.onmessage = function(e){ + chatSocket.onmessage = function(event){ var data = JSON.parse(event.data) - $(".result").text(data.result || data.error); + $(".result").text(data.response); }; }); \ No newline at end of file diff --git a/test/IntegrationSpec.scala b/test/IntegrationSpec.scala index dbd5165..30b7d89 100644 --- a/test/IntegrationSpec.scala +++ b/test/IntegrationSpec.scala @@ -10,19 +10,12 @@ import play.api.test.Helpers._ * An integration test will fire up a whole play application in a real (or headless) browser */ class IntegrationSpec extends Specification { - "Application" should { - "work from within a browser" in { running(TestServer(3333), HTMLUNIT) { browser => - browser.goTo("http://localhost:3333/") - browser.pageSource must contain("Your new application is ready.") - } - } - + } } - } \ No newline at end of file