I use ZLayer and Sttp Client(async to create simple http requester application but I found type mismatch error that I couldn't solve it. Can anyone tell me why I'm getting the type mismatch error?
I use these versions of scala & libraries.
java -> 8.282.08.1-amzn
scala -> s.13.5
dev.zio -> 1.0.7
com.softwaremill.sttp.client3 -> 3.3.0
type mismatch;
found : zio.ZLayer[sttp.client3.asynchttpclient.zio.SttpClient,Nothing,ZlayerAndSttp.HttpBin]
(which expands to) zio.ZLayer[zio.Has[sttp.client3.SttpBackend[zio.Task,sttp.capabilities.zio.ZioStreams with sttp.capabilities.WebSockets]],Nothing,zio.Has[ZlayerAndSttp.HttpBin.Service]]
required: zio.ZLayer[ZlayerAndSttp.HttpBin,?,?]
(which expands to) zio.ZLayer[zio.Has[ZlayerAndSttp.HttpBin.Service],?,?]
program.provideCustomLayer((AsyncHttpClientZioBackend.layer() >>> HttpBin.live) >>> HttpBin.live)
Here's the whole code
import zio._
import sttp.client3._
import sttp.client3.circe._
import sttp.client3.asynchttpclient.zio._
import io.circe.generic.auto._
import zio.console.Console
object ZlayerAndSttp extends App {
case class HttpBinResponse(origin: String, headers: Map[String, String])
type HttpBin = Has[HttpBin.Service]
object HttpBin {
trait Service {
def sendRequest: ZIO[HttpBin with SttpClient, Throwable, HttpBinResponse]
}
val live: ZLayer[SttpClient, Nothing, HttpBin] = ZLayer.succeed(new Service {
override def sendRequest: ZIO[HttpBin with SttpClient, Throwable, HttpBinResponse] = {
val request = basicRequest
.get(uri"https://httpbin.org/get")
.response(asJson[HttpBinResponse])
sendR(request).map(_.body).absolve.map(res => HttpBinResponse(res.origin, res.headers))
}
})
def sendRequest: ZIO[HttpBin with SttpClient, Throwable, HttpBinResponse] = ZIO.accessM(_.get.sendRequest)
}
val request = basicRequest
.get(uri"https://httpbin.org/get")
.response(asJson[HttpBinResponse])
override def run(args: List[String]): URIO[zio.ZEnv, ExitCode] = {
val program = for {
result <- HttpBin.sendRequest
_ <- console.putStrLn(s"${result.origin}, ${result.headers}")
} yield ()
program.provideCustomLayer((AsyncHttpClientZioBackend.layer() >>> HttpBin.live) >>> HttpBin.live) // type mismatch
.exitCode
// ↓these lines of code run with no errors but I can't understand why
// val program: ZIO[Console with SttpClient, Throwable, Unit] = for {
// response <- send(request)
// _ <- console.putStrLn(s"${response.body.toString}")
// } yield ()
// program.provideCustomLayer(AsyncHttpClientZioBackend.layer()).exitCode
}
}
You seem to be making your life a bit more complicated than needed.
What the end code looks like depends on what you want to achieve here. If you are trying to hide the use of
Sttp
behind theHttpBin
interface, then your layer definition should instead look like:Then your accessor method becomes:
And you can use it with:
The thing to note here is that with layer composition I am using just the vertical operator because
HttpBin.live
depends on a layer withSttpClient
but we are "hiding" that fact from the calling method so you could create atest
variant ofHttpBin
that didn't require Sttp if needed.If you don't need the information hiding you can instead remove the intermediate layer altogether and just treat your
sendRequest
as a stand alone method.Then you can just call this method and all you need to do is provide the
SttpClient
layer.