Spray(13)REST API Project - Integrate with Spray Client

Spray(13)REST API Project - Integrate with Spray Client

10. Integrate with Spray Client
10.1. Add the dependencies
in the build.sbt
"io.spray"            %   "spray-client"                      % "1.1-M7",

10.2. Initiate the Actor when Our system start 
import akka.actor.Actor
import akka.actor.ActorSystem
import akka.actor.Props
import akka.actor.actorRef2Scala
import spray.can.server.HttpServer
import spray.io.IOExtension
import spray.io.SingletonHandler
import com.typesafe.config.ConfigFactory
import spray.routing.directives.PathMatcher
import shapeless._
import spray.routing.HttpServiceActor
import spray.can.client.DefaultHttpClient
import spray.client.HttpConduit 


  implicit val system = ActorSystem("on-spray-can")
  val config = ConfigFactory.load()
 
  //initiate the spray client actor
  val httpClient = DefaultHttpClient(system)

  val analyticsServerAddress: String = config.getString("analytics.server.address")
  val analyticsServerPort: Int = config.getInt("analytics.server.port")

  //actor which holds the connection pool to analytics remote server
  val analyticsConduit = system.actorOf(
    props = Props(new HttpConduit(httpClient, analyticsServerAddress, analyticsServerPort)),
    name = "sillycat_conduit"
  )

So we will name the spray client as "sillycat_conduit".

When we wants to use this actor.
Get the actorRefFActory in the BaseService

val sillycatRESTTemplate: SillycatRESTTemplate = SillycatRESTTemplate.apply(actorRefFactory)

And in the Template Class, I will get the actorRefFactory like this>

import akka.actor.{ Props, Actor }
import spray.routing._
import spray.routing.directives._
import spray.util.LoggingContext
import spray.http.StatusCodes._
import spray.httpx.SprayJsonSupport._
import shapeless._
import akka.actor._
import spray.routing.authentication._
import spray.client.HttpConduit
import spray.http.HttpRequest
import spray.http.HttpMethods
import scala.util.{ Success, Failure }
import akka.actor.{ Props, ActorSystem }
import spray.can.client.DefaultHttpClient
import spray.client.HttpConduit
import spray.httpx.SprayJsonSupport
import spray.http._
import spray.util._
import scala.concurrent.Future
import scala.concurrent.Await
import scala.concurrent.duration._
import org.joda.time.Period
import scala.slick.session.Database.threadLocalSession
import spray.json._
import scala.Predef._


class SillycatRESTTemplate(actorRefFactory: ActorRefFactory) {
     val sillycat_conduit = actorRefFactory.actorFor("/user/sillycat_conduit") //actor name
     val default_timeout = 30 second

     …snip...
     val pipeline = HttpConduit.sendReceive(analytics_conduit)
     //post the data, prettyRequest is the JSON format data
     val responseFuture = pipeline(HttpRequest(method = HttpMethods.POST, entity = prettyRequest, uri = "/dashboard/sillycat"))
     //block result
     val result = Await.result(responseFuture, default_timeout)
     //I need to use block result here, because I need to put the response to client right now
     val result_str = result.entity.toOption.get.asString
     return result_str
}


11. Validation
I can add the validation everywhere if I want
require(List(7, 30, 90).contains(periodDays), "PeriodDays should be in List(7,30,90), but system gets periodDays = " + periodDays)

require(!stores.isEmpty, "There is no stores related to this tag, Tag = " + tag)

Because there is this kind of default handler there
  implicit def myExceptionHandler(implicit log: LoggingContext) =
    ExceptionHandler.fromPF {
      case e: java.lang.IllegalArgumentException => ctx =>
        log.warning("Request {} could not be handled normally", ctx.request)
        ctx.complete(BadRequest, e.getMessage)
    }

Actually when I dive into the source codes of scala, I saw the require is defined like this>
  @inline final def require(requirement: Boolean, message: => Any) {
    if (!requirement)
      throw new IllegalArgumentException("requirement failed: "+ message)
  } 

12. How to Work with Actor
come soon...

13. Plain SQL for click
come soon…

Tips
1. How to delete branch in github
delete local branch
>git branch -d :branchName

delete remote branch
>git push origin :branchName
or
>git push origin --delete :branchName

But since I delete the remote branch from the GUI of github, I got these error message:
Carls-MacBook-Pro:winner-seller-server carl$ git push origin --delete another_auth
error: unable to delete 'another_auth': remote ref does not exist
error: failed to push some refs to 'https://github.com/luohuazju/magic.git'

But actually, when I check the all branch on my local, I saw the remote branch
>git branch -a
* master
  remotes/origin/another_auth
  remotes/origin/master

Solution:
Then only thing I need to do is to prune my local
>git remote prune origin

prune remotes any branch that does not exist in the remote origin anymore.

2. Permission denied while sbt command
[warn] exception occurred while writing properties file /Users/carl/.ivy2/cache/commons-codec/commons-codec/ivydata-1.4.properties: /Users/carl/.ivy2/cache/commons-codec/commons-codec/ivydata-1.4.properties (Permission denied)

Solution:
I do not know why, some of the directory are root under the .ivy. I am going to change them.
>sudo chown -R carl .ivy2/cache

References:
Spray 1 ~ 9
http://sillycat.iteye.com/blog/1766558
http://sillycat.iteye.com/blog/1766568
http://sillycat.iteye.com/blog/1857105
http://sillycat.iteye.com/blog/1858282
http://sillycat.iteye.com/blog/1858298
http://sillycat.iteye.com/blog/1859025
spray(10)
http://sillycat.iteye.com/blog/1872476
spray(11 12)
http://sillycat.iteye.com/blog/1882919
http://sillycat.iteye.com/blog/1882963

猜你喜欢

转载自sillycat.iteye.com/blog/1885315