Last active
August 29, 2015 14:20
-
-
Save xasima/56e5fe7c841199475f5c to your computer and use it in GitHub Desktop.
finagle-finch with argonaut-json implicit conversion
This file contains hidden or 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
| // These are snippets based on the recent finch demo package. | |
| // Some modification are added to eliminate usage of ToJson trait, | |
| // but use argonaut Json via implicits instead. | |
| // The purpose of ToJson trait removal is to bypass compilers errors on | |
| // Service[AuthRequest, Seq[argonaut.Json]] to Service[AuthRequest, Json]] | |
| // conversion. | |
| // See current compilers errors at the bottom of the gist | |
| // model.scala snippet | |
| // ----- Domain classes and utils ------------------------------------------- | |
| case class User(val id: Long, val name: String) // No extends of ToJson | |
| object User { | |
| implicit def decodeJson: DecodeJson[User] = DecodeJson(hcursor => | |
| for { | |
| name <- (hcursor --\ "name").as[String] | |
| id <- (hcursor --\ "id").as[Long] | |
| } yield new User( id, name)) | |
| implicit def encodeJson: EncodeJson[User] = | |
| EncodeJson((a: User) => | |
| ("id" := a.id) ->: ("name" := a.name) ->: jEmptyObject) | |
| } | |
| /** | |
| * An implicit class that converts a service that returns a sequence of `Json` | |
| * objects into a service that returns `Json` object. | |
| */ | |
| implicit class SeqToJson[A](s: Service[A, Seq[Json]]) extends Service[A, Json] { | |
| private[server] def seqToJson(seq: Seq[Json]) = | |
| Json.array(seq: _*) | |
| def apply(req: A): Future[Json] = s(req) map seqToJson | |
| } | |
| // ----- / Domain classes and utils ------------------------------------------- | |
| // service.scala snippet | |
| // ----- REST Service methods impl ------------------------------------------- | |
| case class GetUser(userId: Long) extends Service[AuthRequest, User] { | |
| def apply(req: AuthRequest): Future[User] = Db.select(userId) flatMap { | |
| case Some(user) => user.toFuture | |
| case None => UserNotFound(userId).toFutureException[User] | |
| } | |
| } | |
| case class GetUsers() extends Service[AuthRequest, Seq[User]] { | |
| def apply(req: AuthRequest): Future[Seq[User] ] = | |
| Seq(User(1, "foo"), User(2, "bar")).toFuture | |
| } | |
| // ----- / REST Service methods impl ------------------------------------------- | |
| // ----- Endpoints ------------------------------------------- | |
| // endpoint.scala | |
| import model._ | |
| import io.finch.route._ | |
| // Not sure why this is needed since we do have User.encodeJson implicit, | |
| // and SeqToJson implicit already | |
| implicit def anyToJson[A](a: A)(implicit e: EncodeJson[A]): Json = e(a) | |
| // User endpoint. | |
| val restEndpoint: Endpoint[AuthRequest, Json] = | |
| // It is supposed that the following GetUser of the | |
| // Service[AuthRequest, User] type would be converted to Service[AuthRequest, Json] via | |
| // User.encodeJson implicit | |
| (Get / "users" / long /> GetUser ) | | |
| // and GetUsers of the Service[AuthRequest, Seq[User]] type would be converted to | |
| // Service[AuthRequest, Seq[Json]] | |
| // via the same User.encodeJson implicit, and later the conversion | |
| // Service[AuthRequest, Seq[Json]] to Service[AuthRequest, Json] occurs via | |
| // SeqToJson implicit | |
| (Get / "users" /> GetUsers ) | |
| // But compiler error occurs on GetUsers | |
| // Error:(38, 61) type mismatch; | |
| // found : com.xxx.xxx.server.service.GetUsers.type | |
| // required: com.twitter.finagle.Service[com.xxx.xxx.internals.AuthRequest,argonaut.Json] | |
| // (Get / "users" / long /> GetUser ) | (Get / "users" /> GetUsers ) | |
| ^ | |
| // It the later GetUsers part of endpoint is commented out, then the mismatch occurs on plain GetUser | |
| // Error:(38, 31) type mismatch; | |
| // found : com.xxx.xxx.server.service.GetUser.type | |
| // required: Long => com.twitter.finagle.Service[com.xxx.xxx.internals.AuthRequest,argonaut.Json] | |
| // (Get / "users" / long /> GetUser ) | |
| ^ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment