I am trying to play around with ZIO http using their simples hello world example. I have a Java-written service which does some logic, and it expecting a handler function, so it can call it when result is ready. How do I user it together with ZIO http ? I want something like this:
object HelloWorld extends App {
def app(service: JavaService) = Http.collect[Request] {
case Method.GET -> Root / "text" => {
service.doSomeStuffWIthCallback((s:String) => Response.text(s))
}
}
override def run(args: List[String]): URIO[zio.ZEnv, ExitCode] =
Server.start(8090, app(new JavaService)).exitCode
}
Basically I want to send ZIO HTTP response from the callback function, I am just not sure how to go about that. Thanks.
EDIT:
I coudn't get the right types from your code, so I decided to simplify the whole thing, and arrived to this:
val content: HttpData[Blocking, Throwable] = HttpData.fromStream {
ZStream.fromEffect(doSomeStuffWrapped)
}
def doSomeStuffWrapped = {
UIO.effectAsync[String] { cb =>
cb(
IO.succeed("TEST STRING")
)
}
}
However, the issue here is that types do not match, HttpData.fromStream requires ZStream of byte
Here is the link to my gist: https://gist.github.com/pmkyl/a37ff8b49e013c4e2e6f8ab5ad83e258
You should wrap your Java service with callback in an effect using effectAsync
:
def doSomeStuffWrapped(service: JavaService): Task[String] = {
IO.effectAsync[Throwable, String] { cb =>
service.doSomeStuffWithCallback((s: String) => {
// Success case
cb(IO.succeed(s))
// Optional error case?
// cb(IO.fail(someException))
})
}
}
def app(service: JavaService) = Http.collectM[Request] {
case Method.GET -> Root / "text" => {
doSomeStuffWrapped(service)
.fold(err => {
// Handle errors in some way
Response.text("An error occured")
}, successStr => {
Response.text(successStr)
})
}
}
You might want to see this article presenting different options for wrapping impure code in ZIO: https://medium.com/@ghostdogpr/wrapping-impure-code-with-zio-9265c219e2e