diff --git a/sbt/build.sbt b/sbt/build.sbt index 61f73bf..e6f3256 100644 --- a/sbt/build.sbt +++ b/sbt/build.sbt @@ -34,7 +34,7 @@ libraryDependencies <<= scalaVersion { scala_version => "io.spray" % "spray-routing" % sprayVersion, "io.spray" % "spray-httpx" % sprayVersion, "io.spray" % "spray-util" % sprayVersion, - "io.spray" % "spray-json_2.9.2" % "1.2.2" + "io.spray" % "spray-json" % "1.2.2" cross CrossVersion.full ) } @@ -62,3 +62,5 @@ testOptions := Seq(Tests.Filter(s => /** Console */ initialCommands in console := "import org.cakesolutions.akkapatterns._" + +EclipseKeys.withSource := true diff --git a/sbt/project/plugins.sbt b/sbt/project/plugins.sbt index 90bcf24..12a3c35 100644 --- a/sbt/project/plugins.sbt +++ b/sbt/project/plugins.sbt @@ -2,4 +2,5 @@ resolvers += "Sonatype snapshots" at "http://oss.sonatype.org/content/repositori addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.2.0-SNAPSHOT") -addSbtPlugin("com.github.gseitz" % "sbt-release" % "0.6") \ No newline at end of file +addSbtPlugin("com.github.gseitz" % "sbt-release" % "0.6") + diff --git a/sbt/src/main/scala/org/cakesolutions/akkapatterns/api/boot.scala b/sbt/src/main/scala/org/cakesolutions/akkapatterns/api/boot.scala index e69de29..993e6e7 100644 --- a/sbt/src/main/scala/org/cakesolutions/akkapatterns/api/boot.scala +++ b/sbt/src/main/scala/org/cakesolutions/akkapatterns/api/boot.scala @@ -0,0 +1,42 @@ +package org.cakesolutions.akkapatterns.api + +import akka.actor.{ActorRef, Props} +import spray._ +import routing._ +import http.{StatusCodes, HttpResponse} +import org.cakesolutions.akkapatterns.core.Core +import akka.util.Timeout + +trait Api { + this: Core => + + val routes = + new HomeService().route :: + new CustomerService().route :: + new UserService().route :: + Nil + + def rejectionHandler: PartialFunction[scala.List[Rejection], HttpResponse] = { + case (rejections: List[Rejection]) => HttpResponse(StatusCodes.BadRequest) + } + + // FIXME: HttpService is now a trait + // @see http://spray.io/documentation/spray-routing/key-concepts/big-picture/#the-httpservice + // this file should probably be rewritten to use the new API + val svc: Route => ActorRef = route => + actorSystem.actorOf(Props(new HttpService(route, rejectionHandler))) + + val rootService = actorSystem.actorOf( + props = Props(new RootService( + svc(routes.head), + routes.tail.map(svc):_* + )), + name = "root-service" + ) + +} + +trait DefaultTimeout { + final implicit val timeout = Timeout(3000) + +} \ No newline at end of file diff --git a/sbt/src/main/scala/org/cakesolutions/akkapatterns/api/customer.scala b/sbt/src/main/scala/org/cakesolutions/akkapatterns/api/customer.scala index e69de29..c5798e2 100644 --- a/sbt/src/main/scala/org/cakesolutions/akkapatterns/api/customer.scala +++ b/sbt/src/main/scala/org/cakesolutions/akkapatterns/api/customer.scala @@ -0,0 +1,44 @@ +package org.cakesolutions.akkapatterns.api + +import akka.actor.ActorSystem +import spray.httpx.SprayJsonSupport._ +import spray.routing.Directives +import org.cakesolutions.akkapatterns.domain.Customer +import org.cakesolutions.akkapatterns.core.application._ +import akka.pattern.ask +import org.cakesolutions.akkapatterns.core.application.RegisterCustomer +import org.cakesolutions.akkapatterns.domain.Customer +import org.cakesolutions.akkapatterns.core.application.Get +import org.cakesolutions.akkapatterns.core.application.FindAll +import spray.httpx.SprayJsonSupport +import spray.httpx.marshalling.MetaMarshallers + +/** + * @author janmachacek + */ +class CustomerService(implicit val actorSystem: ActorSystem) extends Directives with Marshalling with MetaMarshallers with DefaultTimeout { + def customerActor = actorSystem.actorFor("/user/application/customer") + + val route = + path("customers" / JavaUUID) { id => + get { + complete { + import scala.concurrent.ExecutionContext.Implicits.global + (customerActor ? Get(id)).mapTo[Option[Customer]] + } + } + } ~ + path("customers") { + get { + complete{ + val bob = (customerActor ? FindAll()).mapTo[List[Customer]] + bob + } + } ~ + post { + content(as[RegisterCustomer]) { rc => + complete((customerActor ? rc).mapTo[Either[NotRegisteredCustomer, RegisteredCustomer]]) + } + } + } +} diff --git a/sbt/src/main/scala/org/cakesolutions/akkapatterns/api/home.scala b/sbt/src/main/scala/org/cakesolutions/akkapatterns/api/home.scala index e69de29..3aee467 100644 --- a/sbt/src/main/scala/org/cakesolutions/akkapatterns/api/home.scala +++ b/sbt/src/main/scala/org/cakesolutions/akkapatterns/api/home.scala @@ -0,0 +1,41 @@ +package org.cakesolutions.akkapatterns.api + +import akka.actor.ActorSystem +import spray.routing.Directives +import java.net.InetAddress +import akka.pattern.ask +import org.cakesolutions.akkapatterns.core.application.{ PoisonPill, GetImplementation, Implementation } +import spray.httpx.SprayJsonSupport +import spray.httpx.marshalling.MetaMarshallers + +case class SystemInfo(implementation: Implementation, host: String) + +class HomeService(implicit val actorSystem: ActorSystem) extends Directives with MetaMarshallers with Marshalling with DefaultTimeout { + + def applicationActor = actorSystem.actorFor("/user/application") + + val route = { + path(Slash) { + get { + complete { + import scala.concurrent.ExecutionContext.Implicits.global + val futureInfo = (applicationActor ? GetImplementation()).mapTo[Implementation].map { + SystemInfo(_, InetAddress.getLocalHost.getCanonicalHostName) + } + // how to get this to implicitly return as a future marshaller of a SystemInfo marshaller? + futureInfo + } + } + } ~ + path("poisonpill") { + post { + completeWith { + applicationActor ! PoisonPill() + + "Goodbye" + } + } + } + } + +}