Reputation: 2694
I am writing a web service project using Vertx web and verticles with Kotlin language. When I try to switch to Vertx Sync to stop getting into callback hell, some parts of my code run more than once without a reason. When using old callback structure there is no such problem. This is some sample code:
router.post("/layers").handler(fiberHandler { routingContext ->
val request = routingContext.request()
val response = request.response()
response.putHeader("content-type", "application/json")
val layer = gson.fromJson<Layer>(routingContext.bodyAsString, Layer::class.java)
val layerResult = awaitResult<Message<UUID>> { vert.eventBus().send("PersistLayer", layer, it) }
val viewResult = awaitResult<Message<Long>> { vert.eventBus().send("CreateView", layerResult.body(), it) }
response.isChunked = true
response.write(gson.toJson(viewResult.body()))
response.statusCode = 201
})
As soon as I put "PersisLayer" line the next line runs multiple times. When omitting this line, the next line runs once.
Here is PersistLayer code:
vert.eventBus().consumer<Layer>("PersistLayer").handler {
val layer = it.body()
layer.sid = Generators.timeBasedGenerator().generate()
entityManager.apply {
transaction.begin()
persist(layer)
transaction.commit()
}
it.reply(layer.sid)
}
Upvotes: 0
Views: 517
Reputation: 17731
I think I managed to reproduce and solve your problem.
Wonder why you didn't receive a lot of exceptions from Quasar though. It should have alerted that something is not instrumented.
The problem is in this line:
router.post("/layers").handler(fiberHandler { routingContext -> ...
fiberHandler
actually receives a handler, which you implement here implicitly.
// That's what you actually do
class SomeHandler : Handler<RoutingContext> {
override fun handle(event: RoutingContext?) {
}
}
But that class is missing @Suspendable
annotation on handle
method.
So, instead of specifying a block, create a separate class, preferably in a separate file, that looks something like this:
class MyHandler(private val vertx: Vertx) : Handler<RoutingContext> {
@Suspendable
override fun handle(req: RoutingContext?) {
val result = Sync.awaitResult<Message<String>>({
vertx.eventBus().send("someAddress", "Hi", it)
})
println("Got response")
val result2 = Sync.awaitResult<Message<String>>({
vertx.eventBus().send("someAddress", "Hi", it)
})
println("Got second response")
req?.response()?.end(result.body() + result2.body())
}
}
Not as nice as original one, but that should not confuse Quasar though.
Upvotes: 1