Last active
March 23, 2017 06:35
-
-
Save Technius/4fddfc9e33b6c2fff13cbea5e4c67d53 to your computer and use it in GitHub Desktop.
Note Service in Akka-HTTP
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
package example | |
sealed trait ApiResult | |
object ApiResult { | |
/* Returns all notes */ | |
case class ListNotes(notes: Seq[Note]) extends ApiResult | |
/* Returns a specific note found */ | |
case class FoundNote(note: Note) extends ApiResult | |
/* Indicates when a specified note cannot be found */ | |
case class NoteNotFound(id: Int) extends ApiResult | |
/* Indicates when a note is successfully created */ | |
case class CreatedNote(note: Note) extends ApiResult | |
/* Indicates when a note is successfully updated */ | |
case class UpdatedNote(updatedNote: Note) extends ApiResult | |
/* Indicates when a note is sucessfully deleted. */ | |
case class DeletedNote(deletedNote: Note) extends ApiResult | |
} |
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
package example | |
import scala.concurrent.Future | |
import scala.concurrent.ExecutionContext.Implicits.global | |
class InMemoryNoteRepository extends NoteRepository { | |
private[this] val notes = scala.collection.concurrent.TrieMap[Int, Note]() | |
override def list(): Future[Seq[Note]] = Future(notes.values.toSeq) | |
override def find(id: Int) = Future(notes.get(id)) | |
override def create(title: String, content: String) = Future { | |
val id = notes.keys.foldLeft(0)(_ max _) + 1 | |
val n = Note(id, title, content) | |
notes(id) = n | |
n | |
} | |
override def update(id: Int, title: Option[String], content: Option[String]) = | |
Future { | |
val nOpt = notes.get(id).map { note => | |
note.copy(title = title.getOrElse(note.title), content = content.getOrElse(note.content)) | |
} | |
nOpt foreach { note => | |
notes(id) = note | |
} | |
nOpt | |
} | |
override def delete(id: Int) = Future(notes.remove(id)) | |
} | |
object Routes extends Routes { | |
val noteService = new NoteService { val repo = new InMemoryNoteRepository } | |
} |
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
package example | |
import scala.concurrent.Future | |
import scala.concurrent.ExecutionContext.Implicits.global | |
case class Note(id: Int, title: String, content: String) | |
// Don't mix model and behavior in the same file, please. I'm just being lazy. | |
trait NoteRepository { | |
def list(): Future[Seq[Note]] | |
def find(id: Int): Future[Option[Note]] | |
def create(title: String, content: String): Future[Note] | |
def update(id: Int, title: Option[String], content: Option[String]): Future[Option[Note]] | |
def delete(id: Int): Future[Option[Note]] | |
} | |
trait NoteService { | |
import ApiResult._ | |
def repo: NoteRepository | |
def list: Future[ApiResult] = | |
repo.list().map(ListNotes.apply _) | |
def find(id: Int): Future[ApiResult] = | |
repo.find(id).map(noteOp(id)(FoundNote.apply _)) | |
def create(title: String, content: String): Future[ApiResult] = | |
repo.create(title, content).map(CreatedNote.apply _) | |
def update(id: Int, title: Option[String], content: Option[String]): Future[ApiResult] = | |
repo.update(id, title, content).map(noteOp(id)(UpdatedNote.apply _)) | |
def delete(id: Int): Future[ApiResult] = | |
repo.delete(id).map(noteOp(id)(DeletedNote.apply _)) | |
/* | |
* Helper for returning NoteNotFound if an Option is None, or passing the | |
* found note to f otherwise. | |
*/ | |
private def noteOp[T](id: Int)(f: Note => ApiResult): Option[Note] => ApiResult = | |
opt => opt.map(f).getOrElse(NoteNotFound(id)) | |
} |
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
package example | |
import akka.http.scaladsl._ | |
import akka.actor.ActorSystem | |
import akka.stream.ActorMaterializer | |
object NoteServer { | |
def main(args: Array[String]) { | |
implicit val system = ActorSystem() | |
implicit val mat = ActorMaterializer() | |
val host = "0.0.0.0" | |
val port = 1234 | |
val fut = Http().bindAndHandle(Routes.notesRoute, host, port) | |
println("Started") | |
} | |
} |
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
package example | |
import scala.concurrent.ExecutionContext.Implicits.global | |
import akka.http.scaladsl.server.Directives._ | |
import upickle.default._ | |
trait Routes { | |
def noteService: NoteService | |
val notesRoute = | |
pathPrefix("notes") { | |
(path(IntNumber)) { id => | |
get { | |
complete { | |
noteService.find(id).map(write(_)) | |
} | |
} ~ | |
delete { | |
complete { | |
noteService.delete(id).map(write(_)) | |
} | |
} ~ | |
(post & parameters('title.?, 'content.?)) { (title, content) => | |
complete { | |
noteService.update(id, title, content).map(write(_)) | |
} | |
} | |
} ~ | |
pathEndOrSingleSlash { | |
get { | |
complete { | |
noteService.list.map(write(_)) | |
} | |
} ~ | |
(post & parameters('title, 'content)) { (title, content) => | |
complete { | |
noteService.create(title, content).map(write(_)) | |
} | |
} | |
} | |
} | |
} |
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
package example | |
import akka.http.scaladsl._ | |
import akka.actor.ActorSystem | |
import akka.stream.ActorMaterializer | |
object Server { | |
def main(args: Array[String]) { | |
implicit val system = ActorSystem() | |
implicit val mat = ActorMaterializer() | |
val host = "0.0.0.0" | |
val port = 1234 | |
val fut = Http().bindAndHandle(Routes.notesRoute, host, port) | |
println("Started") | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment