'Vertx v4.2.5 returns null instead of future from someFuture.onSuccess()

I'm trying to work through with vertx 4.2.5 promises and futures, but I keep getting tripped up on odd things

I have a very simple groovy script like this, where I create a new promise, get a future from it and set the onSuccess() and onError() in chained fashion

Promise promise = Promise.promise()
Future sf = promise.future()
sf.onSuccess{Object res -> println "-> script: got object $res" }.onFailure(Throwable::printStackTrace)
sleep (300)
assert promise.tryComplete("object completed with OK")

this fails with

Caught: java.lang.NullPointerException: Cannot invoke method onFailure() on null object
java.lang.NullPointerException: Cannot invoke method onFailure() on null object
    at scripts.promisesAndFutures.run(promisesAndFutures.groovy:123)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

Which is odd as onSuccess() is supposed to return a Future

So I tried to break the call up like this

Promise promise = Promise.promise()
Future sf = promise.future()
sf.onSuccess{Object res -> println "-> script: got object $res" }
sf.onFailure(Throwable::printStackTrace)
sleep (300)
assert promise.tryComplete("object completed with OK")

Now the assertion on tryComplete() fails with

Caught: Assertion failed: 

assert promise.tryComplete("object completed with OK")
       |       |
       |       false
       Future{result=scripts.promisesAndFutures$_run_closure3@6981f8f3}

Assertion failed: 

assert promise.tryComplete("object completed with OK")
       |       |
       |       false
       Future{result=scripts.promisesAndFutures$_run_closure3@6981f8f3}

    at scripts.promisesAndFutures.run(promisesAndFutures.groovy:126)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

If I use complete() (instead of tryComplete()), the error says the future is complete - which it can't be as I have just set the answer on the promise from which the future was derived!

Caught: java.lang.IllegalStateException: Result is already complete
java.lang.IllegalStateException: Result is already complete

However, if I replace the onSuccess/onError options and use onComplete(), it works every time!

Promise promise = Promise.promise()
Future sf = promise.future()
//sf.onSuccess{Object res -> println "-> script: got object $res" }
//sf.onFailure(Throwable::printStackTrace)
sf.onComplete{ar ->
    println "sf completed with ${ar.result()}"
}
sleep (300)
promise.complete("object completed with OK")

Why does onSuccess() return null, and processing fails with 'already complete' etc problems, - whilst the onComplete() option always works fine?

Is this a bug, or am I missing something important in futures chaining?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source