Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Scala Frameworks for Web Application 2016

6,540 views

Published on

Scala Kansai Summit 2016 #scala_ks

Published in: Software

Scala Frameworks for Web Application 2016

  1. 1. Scala Frameworks for Web Application 2016 BizReach, Inc Scala Kansai Summit 2016 #scala_ks
  2. 2. Standard Frameworks for Web Application in Scala
  3. 3. Why we've used Play2 and Slick? ● Many users and developers ● Future prospects ● Supported by Typesafe
  4. 4. Dissatisfaction to Play2 ● Unnecessary features ○ View support ○ Assets management ○ Dependency injection ● Poor integration ○ Zipkin https://github.com/levkhomich/akka-tracing ○ Swagger https://github.com/swagger-api/swagger-play
  5. 5. Dissatisfaction to Slick ● Lerning curve ○ DBIO is hard for non-functional programmers ○ Asynchronous is not always needed ● Performance ○ Join makes subquery frequently ○ It causes performance issue with MySQL
  6. 6. Alternatives?
  7. 7. Alternatives ● Web Framework ○ Finagle ○ Akka HTTP ○ Skinny Micro ● Database Framework ○ Quill ○ doobie ○ Scalike JDBC
  8. 8. Finagle ● Pluggable asynchronous RPC framework based on Netty ● Client API with Circuit Breaker ● Zipkin integration ● Finatra or Finch for HTTP server ● Swagger 1.x support for Finatra (3rd party) ○ https://github.com/xiaodongw/swagger-finatra
  9. 9. Finagle val router = RoutingService.byPathObject[Request] { case Root => new Service[Request,Response] { def apply(req: Request): Future[Response] = { Future(Response( req.version, Status.Ok, Reader.fromBuf(Utf8("API is Ready.")) )) } } case Root / "hello"/ name => new Service[Request, Response] { def apply(req: Request): Future[Response] = { Future(Response( req.version, Status.Ok, Reader.fromBuf(Utf8(s"Hello ${name}!")) )) } } } Maybe Finatra or Finch is better choise for REST API server
  10. 10. Akka HTTP ● Actor-based toolkit for interacting web services and clients ● spray like routing DSL ● Reactive Streams ● Swagger 2.0 support (3rd party) ○ https://github.com/swagger-akka-http/swagger-akka-http ● Play 3.0 will move to Akka HTTP? ○ Experimental in Play 2.5 ○ https://www.playframework.com/documentation/2.5.x/AkkaHttpServer
  11. 11. Akka HTTP val route = get { pathEndOrSingleSlash { handleWith((request: HttpRequest) => "API is ready.") } } ~ path("hello" / ".+".r) { get { case (name) => complete { HelloResult(message = s"Hello, ${request.name}!") } } }
  12. 12. Skiny Micro ● Servlet-based micro framework ● Scalatra comparible routing DSL ● Future-wired async operation ● No Swagger and Zipkin support
  13. 13. Skiny Micro object Hello extends WebApp with JSONSupport { get("/") { "API is ready" } post("/hello/:name") { contentType = "application/json" toJSONString( HelloResult(message = s"Hello, ${params("name")}!") ) } }
  14. 14. Results Version View DI Routing Circuit Breaker Reactive Streams Zipkin Swagger Play2 2.5.8 Supported Guice Method + DSL - ※2 3rd party library 3rd party library Finagle 6.38.0 - ※1 DSL Supported - Supported 3rd party library Akka HTTP 2.4.10-exp erimantal - - DSL - Supported 3rd party library 3rd party library Skinny Micro 1.1.0 - - DSL - - - - ※1 Finatra is equipped Guice based dependency injection as same as Play2 ※2 There is an experimental module in Play 2.5 https://www.playframework.com/documentation/2.5.x/ReactiveStreamsIntegration
  15. 15. Quill ● Macro-based compile time SQL generation ○ No overhead in runtime ○ Compile time SQL validation is available ○ Some constraints in query building ● Development is very active ○ Many sub modules are available such as async, cassandra support and finagle integration ● Move to scala.meta in the future?
  16. 16. Quill val account: Option[Account] = ctx.run( quote { (mailAddress: String, includeRemoved: Boolean) => query[Account].filter { t => if(includeRemoved){ t.mailAddress == mailAddress } else { t.mailAddress == mailAddress && t.removed == false } } } )(mailAddress, includeRemoved).headOption
  17. 17. Quill val account: Option[Account] = ctx.run( quote { (mailAddress: String, includeRemoved: Boolean) => query[Account].filter { t => if(includeRemoved){ t.mailAddress == mailAddress } else { t.mailAddress == mailAddress && t.removed == false } } } )(mailAddress, includeRemoved).headOption Macro (expanded in compile time)
  18. 18. Quill val account: Option[Account] = ctx.run( quote { (mailAddress: String, includeRemoved: Boolean) => query[Account].filter { t => if(includeRemoved){ t.mailAddress == mailAddress } else { t.mailAddress == mailAddress && t.removed == false } } } )(mailAddress, includeRemoved).headOption Take variables as argument
  19. 19. Quill val account: Option[Account] = ctx.run( quote { (mailAddress: String, includeRemoved: Boolean) => query[Account].filter { t => if(includeRemoved){ t.mailAddress == mailAddress } else { t.mailAddress == mailAddress && t.removed == false } } } )(mailAddress, includeRemoved).headOption Assemble condition dynamically?
  20. 20. Quill SELECT ... FROM account t WHERE CASE WHEN ? THEN t.mail_address = ? ELSE (t.mail_address = ?) AND (t.removed = false) END No, translated to CASE expression
  21. 21. doobie ● A pure-functional JDBC layer for Scala ○ It is not an ORM ● Designed for people who are interested in: ○ typed ○ pure functional programming ● IO and monadic effects
  22. 22. doobie sql"select * from account where uid = $id" .query[Account] .option .transact(xa) .unsafePerformAsync { case -/(throwable) => ... case /-(account) => ... }
  23. 23. doobie sql"select * from account where uid = $id" .query[Account] // Query0[Account] .option // ConnectionIO[Option[Account]] .transact(xa) // Task[Option[Account]] .unsafePerformAsync { case -/(throwable) => … // Throwable case /-(account) => … // Option[Account] } Query0[Account] is all columns query that maps one returned row. Ultimately producing a value of type Option[Account].
  24. 24. doobie sql"select * from account where uid = $id" .query[Account] // Query0[Account] .option // ConnectionIO[Option[Account]] .transact(xa) // Task[Option[Account]] .unsafePerformAsync { case -/(throwable) => … // Throwable case /-(account) => … // Option[Account] } Task is scalaz.concurrent.Task!!
  25. 25. doobie ● Typechecking (experimental) ○ Validate queries against the database schema in runtime val q: Query0[Account] = sql"select * from account where uid = $id".query[Account] q.check.unsafePerformSync ✓ SQL Compiles and Typechecks ✕ C01 UID INTEGER (INTEGER) NOT NULL → String - INTEGER (INTEGER) is ostensibly coercible to String according to the JDBC specification but is not a recommended target type. Fix this by changing the schema type to CHAR or VARCHAR; or the Scala type to Int or JdbcType. ✓ C02 LOGIN_ID VARCHAR (VARCHAR) NOT NULL → String
  26. 26. ScalikeJDBC ● A tidy SQL-based DB access library for Scala ○ Naturally wrap JDBC APIs ○ easy-to-use ● QueryDSL is available (since 1.6)
  27. 27. ScalikeJDBC val id = 1 // QueryDSL val a = Account.syntax("a") val account: Option[Account] = DB readOnly { implicit s => withSQL { select.from(Account as a).where.eq(a.uid, id) }.map(Account(a)).single.apply() }
  28. 28. ScalikeJDBC val id = 1 case class Email(name: String, address: String) // basic SQL val email: Option[Email] = DB readOnly { implicit s => sql"select * from account where uid = ${id}" .map(rs => Email(rs.get("name"), rs.get("mail_address")) ).single.apply() }
  29. 29. Results Version Monad Async Mapping Typesafe DSL Genarated SQL Timing PlainSQL Slick 3.1.1 Required Always Required ※2 Supported Non-intuitiv e Runtime Supported Quill 0.10.0 Option ※1 - Supported ※3 Intuitive Compile time - doobie 0.3.0 Required Option - - - - Supported ※4 Scalike JDBC 2.4.2 - ※1 Required ※2 Supported Intuitive Runtime Supported ※1 Provides non-blocking API using postgresql-async or mysql-async ※2 A tool to generate table mappings from actual database schema is available ※3 Compile time SQL validation is available ※4 Runtime typechecking is available as experimental feature
  30. 30. Conclusion
  31. 31. Conclusion ● Web Fraemwork ○ All alternatives look good, but Play2 is not so bad as well ○ For servlet container, Skinny Micro would be good ● Database Framework ○ There is no de-facto standard library currently ○ ScalikeJDBC looks good for us and almost users

×