Step 1 Make sure you have the Java 8 JDK (also known as 1.8)
Run javac -version
in the command line and make sure you see javac 1.8.___
If you don’t have version 1.8 or higher, install the JDK
Step 2 Install sbt
Step 3 cd to an empty folder.
Step 4 Run the following command sbt new scala/scala3.g8
. This pulls the ‘scala3’ template from GitHub. It will also create a target folder, which you can ignore.
Set up the dependencies
Put the following dependencies into the build.sbt file
val scala3Version = "2.12.10"
val Http4sVersion = "0.23.12"
val JwtHttp4sVersion = "1.2.0"
val JwtScalaVersion = "9.3.0"
val http4sDsl = "org.http4s" %% "http4s-dsl" % Http4sVersion
val emberServer = "org.http4s" %% "http4s-ember-server" % Http4sVersion
val jwtHttp4s = "dev.profunktor" %% "http4s-jwt-auth" % JwtHttp4sVersion
val jwtScala = "com.github.jwt-scala" %% "jwt-core" % JwtScalaVersion
val jwtCirce = "com.github.jwt-scala" %% "jwt-circe" % JwtScalaVersion
lazy val root = project
.in(file("."))
.settings(
name := "time-management",
version := "0.1.0-SNAPSHOT",
scalaVersion := scala3Version,
libraryDependencies ++=projectDependencies
)
val projectDependencies=Seq(
emberServer,
http4sDsl,
jwtHttp4s,
jwtScala,
jwtCirce,
"org.http4s" %% "http4s-blaze-server" % Http4sVersion,
"org.http4s" %% "http4s-blaze-client" % Http4sVersion,
)
In the Main.scala file
import cats.effect.IO
import cats.effect.unsafe.implicits.global
import org.http4s.HttpRoutes
import org.http4s.blaze.server.BlazeServerBuilder
import org.http4s.dsl.io._
import org.http4s.dsl.request.Root
import java.util.concurrent.Executors
import scala.concurrent.ExecutionContext
import scala.concurrent.duration.DurationInt
object Main {
def main(args: Array[String]): Unit = {
(for {
serverExecutionContext <- IO(
ExecutionContext.fromExecutor(Executors.newFixedThreadPool(1))
)
routes = HttpRoutes.of [IO] {
case GET -> Root / "welcome" / user =>
Ok(s"Welcome, ${user}")
}
serverIO <- BlazeServerBuilder[IO]
.withExecutionContext(serverExecutionContext)
.withIdleTimeout(180.seconds)
.bindHttp(port = 8080, host = "0.0.0.0")
.withHttpApp(routes.orNotFound)
.serve
.compile
.drain
} yield serverIO).unsafeRunSync()
}
}
import cats.effect.unsafe.implicits.global
When excute the .unsafeRunSync()
, it requires an IORuntime, which is provided by import cats.effect.unsafe.implicits.global
. It brings an implicit cats.effect.unsafe.IORuntime into scope. This IORuntime provides the necessary thread pools for executing IO computations.
In Cats Effect 3, IO operations require an IORuntime to run. This IORuntime includes a computation pool for CPU-bound tasks, a blocking pool for blocking I/O, and a scheduler for scheduling timed tasks.
=
instead of <-
when create routes?In Scala's for-comprehension, the <- symbol is used to extract values from a monadic context (e.g. Option
, List
, Future
, IO
, etc.). This is often called the "monadic bind" or "flatMap" operation.
In our code, HttpRoutes.of[IO] returns an HttpRoutes[IO], which is itself a value, not a monadic context, so you can't use <- to extract it. You should use = to assign a value, as you did in the first example.
If HttpRoutes.of[IO]
returned an IO[HttpRoutes[IO]]
or some other monadic context, then you could use <-
to extract HttpRoutes[IO]
. But in our case, HttpRoutes.of[IO]
returns an HttpRoutes[IO]
directly, so we should use =
to assign it.