0

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)
    }
Kamyar
  • 2,494
  • 2
  • 22
  • 33
  • The problem is probably not with this part, but with what you do in "PersistLayer" listener. Could you please post it too? – Alexey Soshin Dec 09 '17 at 19:26
  • @AlexeySoshin But the PersistLayer code is too simple to be problematic. I added the code. – Kamyar Dec 10 '17 at 12:49
  • Thanks. At a glance your code looks good. Maybe something in between Quasar->VertX Sync->Kotlin misbehaves then. I'll try to reproduce this in a day or two. – Alexey Soshin Dec 10 '17 at 21:16
  • [Vert.x supports Kotlin coroutines](http://vertx.io/docs/vertx-lang-kotlin-coroutines/kotlin/). Why use Vert.x Sync if not programming in Java? – tsegismont Dec 11 '17 at 09:29
  • @tsegismont Do u call it coroutine support? it is same as Sync with 'launch' function added! It is a very poor support! Leave it! Bullshit! – Kamyar Dec 11 '17 at 10:30

1 Answers1

1

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.

Alexey Soshin
  • 16,718
  • 2
  • 31
  • 40