Scala ◦ ScalaJS ◦ Scalatags & ScalaCSS by Li Haoyi ◦ UI: Routing, property binding, internationalization • Type safety continuous throughout the entire system ◦ Trait based client-server RPC ◦ Opaque-ish protocol • RPC based REST ◦ Well defined HTTP traffic ◦ Consumable by other systems in different languages
object UserApi extends DefaultRestApiCompanion[UserApi] case class UserId(id: Long) extends AnyVal object UserId extends RestDataWrapperCompanion[Long, UserId] case class User(id: UserId, name: String) object User extends RestDataCompanion[User] Data types
String): Future[User] = ??? } val serverHandle: HandleRequest = UserApi.asHandleRequest(new UserApiImpl) type HandleRequest = RestRequest => Async[RestResponse] type Callback[T] = Try[T] => Unit type Async[T] = Callback[T] => Unit
object UserApi extends DefaultRestApiCompanion[UserApi] case class UserId(id: Long) extends AnyVal object UserId extends RestDataWrapperCompanion[Long, UserId] case class User(id: UserId, name: String) object User extends RestDataCompanion[User] How does it work?
object UserApi extends DefaultRestApiCompanion[UserApi](ǽƝǗǠƹ) case class UserId(id: Long) extends AnyVal object UserId extends RestDataWrapperCompanion[Long, UserId](ǽƝǗǠƹ) case class User(id: UserId, name: String) object User extends RestDataCompanion[User](ǽƝǗǠƹ) How does it work? Companions with macros!
Problems: • runtime reflection, runtime proxies, Java serialization • annotations form a severely limited, dynamic, unsafe, untyped pseudolanguage • hard to understand and debug • usually blocking, difficult to work with async
provide AsReal and AsRaw instances • e.g. AsRaw for JsonValue could be defined based on Circe Encoder • and AsReal for JsonValue could be defined based on Circe Decoder Serialization
provide AsReal and AsRaw instances • e.g. AsRaw for JsonValue could be defined based on Circe Encoder • and AsReal for JsonValue could be defined based on Circe Decoder • Bake it all into the base companion class! Serialization
provide AsReal and AsRaw instances • e.g. AsRaw for JsonValue could be defined based on Circe Encoder • and AsReal for JsonValue could be defined based on Circe Decoder • Bake it all into the base companion class! • DefaultRestApiCompanion injects GenCodec based serialization (AVSystem’s own serialization library) Serialization
provide AsReal and AsRaw instances • e.g. AsRaw for JsonValue could be defined based on Circe Encoder • and AsReal for JsonValue could be defined based on Circe Decoder • Bake it all into the base companion class! • DefaultRestApiCompanion injects GenCodec based serialization (AVSystem’s own serialization library) • It’s easy to make your own version of base companion class, tailored for your needs, e.g. CirceRestApiCompanion to use Circe for serialization Serialization
Async[T] = Callback[T] => Unit trait AsyncEffect[F[_]] { def toAsync[A](fa: F[A]): Async[A] def fromAsync[A](async: Async[A]): F[A] } • not only Future s but any effects which capture asynchronous, possibly lazy, repeatable computation - Monix Task , Cats IO , ZIO , etc. • Future support is injected by DefaultRestApiCompanion , you can opt out
companion for User ? [error] problem with parameter user of method replaceUser: [error] Cannot deserialize User from HttpBody, because: [error] Cannot deserialize User from JsonValue, because: [error] No GenCodec found for User [error] @PUT @CustomBody def replaceUser(user: User): Future[Unit] [error] ^ @PUT @CustomBody def replaceUser(user: User): Future[Unit]
LibCodec not found for Int Implicits.infer[Codec[Int]] • requires custom Implicits.infer macro • is used automatically by macro-originated implicit searches • extensible
• can be accessed in macros as ASTs • we can implement our own annotation processing • selective reification into runtime • aggregation - Don’t Repeat Yourself for annotations
with given name") def createUser(name: String): Future[User] } class summary(summary: String) extends OperationAdjuster { def adjustOperation(operation: Operation): Operation = operation.copy(summary = summary) } Make your own annotations!
data types to define endpoints • type safety on many levels • pluggable native HTTP servers and clients • pluggable, extensible serialization • pluggable, extensible effects • superb error messages, also extensible • annotations on steroids • built using a powerful, generic metaprogramming engine