smithy4play is a routing gernator for the play2 framework based on smithy4s. Just write your smithy API definition and the plugin will generate everything you need for play2 framework usage.
plugins.sbt
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.*.*")
addSbtPlugin("com.codecommit" % "sbt-github-packages" % "0.*.*")
addSbtPlugin(
"com.disneystreaming.smithy4s" % "smithy4s-sbt-codegen" % "0.*.*"
)
build.sbt
.enablePlugins(Smithy4sCodegenPlugin, PlayScala)
.settings(
githubSettings,
Compile / smithy4sInputDir := (ThisBuild / baseDirectory).value / "smithy-in",
Compile / smithy4sOutputDir := (ThisBuild / baseDirectory).value / "smithy-out",
libraryDependencies += "de.innfactory" %% "smithy4play" % "latestVersion")
- define your controllers in smithy files
- use smithy4s codegen (sbt compile)
Server
- create controller scala class
- extend your Controller with the generated Scala Type and smithy4play Type ContextRoute
@Singleton
class PreviewController @Inject(
)(implicit
cc: ControllerComponents,
ec: ExecutionContext
) extends PreviewControllerService[ContextRoute] {
override def preview(bye: PreviewBody): ContextRoute[PreviewResponse] =
Kleisli { rc =>
EitherT.rightT[Future, ContextRouteError](PreviewResponse(Some("Hello")))
}
}
Client
- import the EnhancedGenericAPIClient
import de.innfactory.smithy4play.client.GenericAPIClient.EnhancedGenericAPIClient
val previewControllerClient = PreviewControllerServiceGen.withClient(FakeRequestClient)
previewControllerClient.preview()
For a further examples take a look at the smithy4playTest project.
You can choose between autorouting or selfbinding.
- Annotate your controller with
@AutoRouting
- add
scalacOptions += "-Ymacro-annotations"
to your build.sbt settings to enable macro annotations - bind the smithy4play AutoRouter in the play routes file
-> / de.innfactory.smithy4play.AutoRouter
- add package name to configuration
smithy4play.autoRoutePackage = "your.package.name"
- Create a ApiRouter class and inject your controller
@Singleton
class ApiRouter @Inject()(
homeController: HomeController,
pizzaController: PizzaController
)(implicit
cc: ControllerComponents,
ec: ExecutionContext
) extends BaseRouter {
override val controllers: Seq[Routes] =
Seq(homeController, pizzaController)
}
- bind the ApiRouter in the play routes file
-> / api.ApiRouter
If you want Middlewares that run before the endpoint logic follow these steps:
- Implement Middlewares
@Singleton
class ExampleMiddleware @Inject() (implicit
executionContext: ExecutionContext
) extends MiddlewareBase {
override protected def skipMiddleware(r: RoutingContext): Boolean = false
override def logic(
r: RoutingContext,
next: RoutingContext => RouteResult[EndpointResult]
): RouteResult[EndpointResult] =
next(r)
}
- Implement a MiddlewareRegistry and register your middlewares
class MiddlewareRegistry @Inject() (
disableAbleMiddleware: DisableAbleMiddleware,
testMiddlewareImpl: TestMiddlewareImpl,
validateAuthMiddleware: ValidateAuthMiddleware
) extends MiddlewareRegistryBase {
override val middlewares: Seq[MiddlewareBase] = Seq(ExampleMiddleware)
}