Promise.promise() being an anti-pattern?

285 views
Skip to first unread message

Olamide Kolawole

unread,
Apr 25, 2022, 9:36:37 AM4/25/22
to vert.x
I have read from varying GitHub issues and other sources that using Promise.promise() is an anti-pattern. The recommendation is to convert the Context object to a ContextInternal and get a promise tied to the context. This is a little clunky especially since there is no official documentation that i have seen that says that using Vert.x internal classes was a good move, or at least this specific one to get a valid promise that is tied to the current context.

Could a maintainer/core contributor state here why it is an anti-pattern and the correct approach for callback based methods? This will help me greatly in evangelizing this within my organization. Promise.promise() is used extensively in our source code.

Thomas SEGISMONT

unread,
Apr 25, 2022, 9:56:40 AM4/25/22
to ve...@googlegroups.com
Can you explain why it is considered an anti-pattern? I've never heard about this.

If you're writing an application with verticles, it is completely safe. It must be used with care only when invoked on a thread that is not the context thread.

Le lun. 25 avr. 2022 à 15:36, Olamide Kolawole <olam...@gmail.com> a écrit :
I have read from varying GitHub issues and other sources that using Promise.promise() is an anti-pattern. The recommendation is to convert the Context object to a ContextInternal and get a promise tied to the context. This is a little clunky especially since there is no official documentation that i have seen that says that using Vert.x internal classes was a good move, or at least this specific one to get a valid promise that is tied to the current context.

Could a maintainer/core contributor state here why it is an anti-pattern and the correct approach for callback based methods? This will help me greatly in evangelizing this within my organization. Promise.promise() is used extensively in our source code.

--
You received this message because you are subscribed to the Google Groups "vert.x" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vertx+un...@googlegroups.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/vertx/868c67e6-2749-4ce9-bcdc-23ea7cfcb79an%40googlegroups.com.

Julien Viet

unread,
Apr 27, 2022, 5:19:57 AM4/27/22
to vert.x
Hi,

I think also it stems from the fact that in Vert.x 4 you should not
create Promise object and instead obtain Future from Vert.x that are
properly created for you.

Perhaps that is something we should emphase more in the documentation.

Can you elaborate why you need to create promises this way ?

thanks

Julien
> To view this discussion on the web, visit https://groups.google.com/d/msgid/vertx/CACiEr_TAgCW4280j_m5D3zGSWu7CgMMPyxtwSRO_g_7scTq4Bw%40mail.gmail.com.

hegde...@gmail.com

unread,
Apr 27, 2022, 8:21:05 AM4/27/22
to vert.x
I feel bit of context here would help a lot.

In my case I have a data layer which is responsible for making the DB operations and it would return me the response via a Promise object. Below is the sample.

Screenshot (5).png
so the receiving end would do something like this
Screenshot (7).png

So even in this case creating a Promise using Promise.promise() is anti-pattern?

What could be the general way to achieve something like this?

Julien Ponge

unread,
Apr 28, 2022, 2:56:03 AM4/28/22
to hegde...@gmail.com, ve...@googlegroups.com
A promise is a "write view" on some result (value or failure) that will eventually be available, while a future is a "read view" on that eventual result.

So in your APIs a good pattern would be to return a Future<...>, not a Promise<...>.

Vert.x APIs return futures (not promises), so it should be very straightforward to do, say, your SQL query (which returns a Future), possibly do some map/flatMap operations to process data when it's available, then return the final Future of the call chain from your method.

You'd use a Promise when you do some async operations that do not necessarily provide you with a Vert.x Future, then return a Future from that Promise you just created. Eventually in your code you'd complete the Promise when your async operation is done, which would trigger processing for all Future objects derived from that Promise.

Does that make sense?

- Julien

Julien Viet

unread,
Apr 28, 2022, 4:28:38 PM4/28/22
to vert.x
your code should actually use the future returned by the JDBC query
operation and use a map operation:

return jdbcPool.query(...).map(rows ->
List<Employee> employees = new ();
for (Row row : rows) {
Employee employee = ...
}
return employees;
);

instead

HTH

Julien

On Wed, Apr 27, 2022 at 2:21 PM hegde...@gmail.com <hegde...@gmail.com> wrote:
>
> I feel bit of context here would help a lot.
>
> In my case I have a data layer which is responsible for making the DB operations and it would return me the response via a Promise object. Below is the sample.
>
>
> so the receiving end would do something like this
>
>
> To view this discussion on the web, visit https://groups.google.com/d/msgid/vertx/9baba9b4-fc9f-4afe-8e6b-cbd405ef8fe2n%40googlegroups.com.

hegde...@gmail.com

unread,
May 1, 2022, 8:53:36 AM5/1/22
to vert.x
Yes that helps. Had come across of this but misinterpreted it as Promise to be used on the Producer<T> side and Consumer would use Future<T> of the said Promise.

Olamide Kolawole

unread,
May 5, 2022, 8:22:42 PM5/5/22
to vert.x
Thank you for providing an alternative approach to the sample database code. It is clear from that interaction that Promise.promise() is used quite a bit in the wild. It would REALLY help if it was emphasized more in the official documentation, especially why it is not good to have Promise.promise()

I have put together a sample verticle below, forgive if it is too trivial. Is the "good" promise the best approach here? Why? What could happen if the bad promise is used?

public class MainVerticle extends AbstractVerticle {

public Future<String> greet(String name) {
Promise<String> badPromise = Promise.promise(); // BAD
Promise<String> goodPromise = ((ContextInternal) context).promise(); // Good??

vertx.setTimer(name.length() * 1000L, timerId -> {
String greeting = "Hello to you, " + name;
System.out.println(greeting);
badPromise.complete(greeting);
});

return badPromise.future();
}

@Override
public void start() {
List<String> people = Arrays.asList("Adam", "Ben", "Casey", "Dominic");
List<Future> futures = new ArrayList<>();
for (String person : people) {
futures.add(greet(person));
}
CompositeFuture.all(futures)
.onComplete(ar -> {
System.out.println("I will get out of your hair now!");
vertx.close();
});
}
}

Thomas SEGISMONT

unread,
May 6, 2022, 3:21:04 AM5/6/22
to ve...@googlegroups.com
Le ven. 6 mai 2022 à 02:22, Olamide Kolawole <olam...@gmail.com> a écrit :
Thank you for providing an alternative approach to the sample database code. It is clear from that interaction that Promise.promise() is used quite a bit in the wild. It would REALLY help if it was emphasized more in the official documentation

Can you file an issue in vert.x core repo? We could emphasize the duality promise/future in https://vertx.io/docs/vertx-core/java/#_future_results
 
, especially why it is not good to have Promise.promise()

It is totally fine to use Promise.promise() in a vert.x app designed with verticles.
 

I have put together a sample verticle below, forgive if it is too trivial. Is the "good" promise the best approach here? Why? What could happen if the bad promise is used?

public class MainVerticle extends AbstractVerticle {

public Future<String> greet(String name) {
Promise<String> badPromise = Promise.promise(); // BAD
Promise<String> goodPromise = ((ContextInternal) context).promise(); // Good??

See above, Promise.promise() is totally fine in a verticle.
 

Olamide Kolawole

unread,
May 6, 2022, 11:18:22 AM5/6/22
to vert.x
Yep! I will file an issue to emphasize in official documentation.

Thomas SEGISMONT

unread,
May 9, 2022, 4:30:37 AM5/9/22
to ve...@googlegroups.com
Reply all
Reply to author
Forward
0 new messages