Are there other ways to synchronize operations other than vertx-sync?

494 views
Skip to first unread message

Psycho Punch

unread,
Nov 18, 2016, 5:14:24 AM11/18/16
to vert.x
My project is using Spring MVC for Web components, but I have Vert.x taking care of internal passing of messages among clusters of services. In my Web controller I need to wait for Vert.x (event bus) to send, and process response and I can't just rely on the handler passed to it because the Controller code returns immediately; I need to wait for the event bus. I discovered that there's the Vert.x Sync module for that but I'm having difficulties setting up instrumentation between my IDE, and build system (Gradle), especially since none of my efforts to add javaagent arg for running just unit tests in either has worked. The official documentation from Quasar has a section on instrumentation with Gradle, but it doesn't work for my build.

Are there other ways to achieve synchronization without relying on this extra instrumentation steps?

Julien Viet

unread,
Nov 18, 2016, 5:30:38 AM11/18/16
to ve...@googlegroups.com
Hi,

with Kotlin 1.1, you will be able to achieve a similar experience than Vert.x Sync but handled at the compiler level (i.e officially supported by Kotlin).

I have done a few experiments last summer, as research interest (https://github.com/vietj/kotlin-coroutines/blob/master/src/main/kotlin/vietj/coroutines/TheTest.kt)

Kotlin will be officially supported in Vert.x 3.4 with Kotlin 1.0.x for the moment.

However I believe that the POC I have created  could be used in addition, as the Vert.x stack with Kotlin I think could be used with Kotlin 1.1 milestones by just changing the dependency.

Julien


On Nov 18, 2016, at 11:14 AM, Psycho Punch <rdg...@gmail.com> wrote:

My project is using Spring MVC for Web components, but I have Vert.x taking care of internal passing of messages among clusters of services. In my Web controller I need to wait for Vert.x (event bus) to send, and process response and I can't just rely on the handler passed to it because the Controller code returns immediately; I need to wait for the event bus. I discovered that there's the Vert.x Sync module for that but I'm having difficulties setting up instrumentation between my IDE, and build system (Gradle), especially since none of my efforts to add javaagent arg for running just unit tests in either has worked. The official documentation from Quasar has a section on instrumentation with Gradle, but it doesn't work for my build.

Are there other ways to achieve synchronization without relying on this extra instrumentation steps?

--
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.
Visit this group at https://groups.google.com/group/vertx.
To view this discussion on the web, visit https://groups.google.com/d/msgid/vertx/92e6aa9f-7ee7-408a-9585-e35da6ca2724%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Psycho Punch

unread,
Nov 18, 2016, 5:56:20 AM11/18/16
to vert.x
Hi Julien,

Thanks for that. While I'm still not familiar with Kotlin, I think your example code is easy to understand, and to follow. However, right now, I'm under constraint that I can't use languages other than Java in the project. If there aren't any other choice, I will have to weigh between trying to resolve the issues I'm having with Vert.x sync, or convincing that we add a bit of Kotlin in our project, both of which will take some time (and we don't really have much of that at the moment). I just remember there's a RxJava integration module for Vert.x. Are there features in there that you think can offer some alternatives? I have a very general understanding of RxJava at the moment, but I think it's a more viable solution for my project...

Julien Viet

unread,
Nov 18, 2016, 6:21:36 AM11/18/16
to ve...@googlegroups.com
Hi,

gotcha

RxJava is also a very good choice imho (but does not have the same continuation semantics than “sync” like solutions), it is quite popular in the Vert.x ecosystem and you can get help on this forums.

Besides we are working on new features that will improve RxJava further more in 3.4 (such as a better HttpClient), this is a current topic on the vertx-dev list at the moment.

Julien

On Nov 18, 2016, at 11:56 AM, Psycho Punch <rdg...@gmail.com> wrote:

Hi Julien,

Thanks for that. While I'm still not familiar with Kotlin, I think your example code is easy to understand, and to follow. However, right now, I'm under constraint that I can't use languages other than Java in the project. If there aren't any other choice, I will have to weigh between trying to resolve the issues I'm having with Vert.x sync, or convincing that we add a bit of Kotlin in our project, both of which will take some time (and we don't really have much of that at the moment). I just remember there's a RxJava integration module for Vert.x. Are there features in there that you think can offer some alternatives? I have a very general understanding of RxJava at the moment, but I think it's a more viable solution for my project...

--
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.
Visit this group at https://groups.google.com/group/vertx.

Jez P

unread,
Nov 18, 2016, 8:48:10 AM11/18/16
to vert.x
Hi Julien,

That's awesome news (speaking as someone who's rapidly converting to Kotlin). I haven't yet played with the coroutines stuff, but I'll take a look at what you've done. 

Cheers

Jez

Jez P

unread,
Nov 18, 2016, 8:52:14 AM11/18/16
to vert.x
Back to the original post, is the thread that puts a message onto the eventbus in the first place a vert.x event loop thread or is it managed by your container? If the latter, you can wrap your eventbus write in a CompletableFuture (completed by the response) and block until it completes (or fails), returning the value with which it completed, or throwing an appropriate exception if it fails. Obviously if on an eventloop thread you can't block, but reading your initial post it looks like you should be on your own thread.

Psycho Punch

unread,
Nov 18, 2016, 10:29:22 AM11/18/16
to vert.x
Hey Jez,

Thanks for your suggestion. It's the first time I've heard of CompleteableFuture but at least I know the general concept of a Future in the context of Java concurrency, so this is what I'm looking into more closely at the moment. As for your question about which thread initiates event bus operations, I'm not really sure how to answer that. The assumption is that the Spring MVC controller works in single thread per request. I have a Verticle injected into the controller, which is also deployed to the embedded Vert.x in the MVC application. The controller refers to this Verticle for anything it needs from any other member of the (Vert.x) cluster, sending and receiving messages via the Vert.x event bus. So unless I deploy the Verticle as a worker, it means that if I have to block, I will be blocking the event loop, correct?

Jez P

unread,
Nov 18, 2016, 10:41:17 AM11/18/16
to vert.x

Why use a verticle to write to the eventbus? Why not use a vertx instance directly injected as a bean? Then you can write to its eventbus from your Spring-owned thread (presumably really taken from a thread pool in whatever container it's actually running in). All your eventbus listeners should be deployed via verticles, but I don't think that your interface to write to the eventbus needs to be (unless one of the core team thinks otherwise). As long as the verticles are deployed by the same vertx instance that your eventbus-writing code uses I think you should be fine.

Jez P

unread,
Nov 18, 2016, 10:48:36 AM11/18/16
to vert.x
Are you deploying your SpringMVC code using Spring Boot? If so, if I get a little free time over the weekend I'll see if I can mock up what I'm talking about for you in Spring Boot just to show you what i mean, but basically I don't think your external interface to the eventbus needs to be through a verticle (nor does it require writes to be on vertx event loop threads). 

Would this be an adequate demonstration?

Inbound request hits Spring MVC controller?
MVC controller puts processing request on eventbus via adapter which blocks awaiting response from eventbus (possibly with a timeout for convenience)
Verticle picks up processing request on eventbus, does some processing and replies to the message after some period of time
MVC controller receives processing reply and responds to the original request.

(With logging of the thread performing work at each stage so you can see what I mean about being off the event loop for the interface)?

Cheers,

Jez

On Friday, November 18, 2016 at 3:29:22 PM UTC, Psycho Punch wrote:

Psycho Punch

unread,
Nov 18, 2016, 11:06:42 AM11/18/16
to vert.x
Yes, I'm using Spring Boot. I guess the primary reason I have separate Verticles interacting with the Vert.x event bus is that, that's just how I learned how to code in Vert.x. Instead of wiring the Vertx instance into my beans directly, I just have them wired to the Verticles instead because those the ones who have access to Vertx directly (via vertx field of AbstractVerticle). Admittedly, I'm still not very familiar with the what Verticles are meant to do. Another point, however, is that I define service interfaces that can be used generally, with client code not having to care whether they're implemented using Vert.x, Spring REST client, or internal Repository, etc. I implement some of them as AbstractVerticle if I need access to a Vertx instance, something like:

@Service
public class BookVerticle extends AbstractVerticle implements BookService {
   
//method implementation here
}

In my controller code, I wire an instance of BookService (which is a BookVerticle instance actually). However, if I understand what you're saying correctly, you are suggesting something like:

@Service
public class BookServiceImplementation implements BookService {

   
@Autowired
   
private Vertx vertx;

   
//method implementation here using Vert.x instace
   
/*something like
    vertx.eventBus.send(...)
    */

}


Jez P

unread,
Nov 18, 2016, 11:24:47 AM11/18/16
to vert.x
Yep, been a while since I did much Spring in anger, but what you're doing looks like what I had in mind. The primary advantage of a verticle is that all its eventloop-driven processing (for a given instance) can only happen on one thread, so you can write your in-verticle code as single-threaded. However, there is a caveat around this. If you call code in a verticle directly from an external thread, then you are breaking an underlying assumption about that "single-threadedness" because you've just started executing its code from a non-eventloop thread, which means that an eventloop thread could also access its state. However, messages from the eventbus are always handled by verticles using an eventloop thread, so reading from the eventbus is clean. 

My understanding is that writing to the eventbus is thread-safe and you can write from any thread, including a non-vertx thread, and as I mentioned before if you directly invoke a verticle method which writes to the eventbus from an external thread, then you are writing to the eventbus from that thread). So personally for clarity I would take the eventloop writes out of the verticle, and make your BookServiceImplementation wrap the send/reply in a completable future, blocking on it for what you consider a reasonable timeout). You can probably then abstract into a BlockingVertxService the send/reply/block semantics to give a blocking API as expected by your client code but allow everything on the other (verticle) side of the eventbus to be non-blocking and asynchronous, making it easier to change the underlying implementation (simply by extending a different class which reflects different semantics for communicating with that type of service).

Cheers,

Jez

Psycho Punch

unread,
Nov 18, 2016, 12:25:38 PM11/18/16
to vert.x
Hi Jez,

Can you give an example on how to wrap event bus call inside a CompletableFuture? I have something like:

Response response = new Response();
vertx
.eventBus().send("service.name", "{}", result -> {
   
//process result
    response
.update(processedResult);
})
return response;

So in the first line, I have an instance of Response, which I update inside the event bus handler with the data I receive. My problem is that the method returns instantly without waiting for event bus handler. I'm not quite sure how CompletableFuture figures into this...

Psycho Punch

unread,
Nov 18, 2016, 12:32:39 PM11/18/16
to vert.x
Oh wait, I think I figured it out:

CompletableFuture<Response> future = new CompletableFuture<>();
vertx
.eventBus().send("service.name", "{}", result -> {
   
//process result
   
future.complete(processedResult);
})
return future.get(); //handle exception here

Jez P

unread,
Nov 18, 2016, 1:14:33 PM11/18/16
to vert.x
If your send is returning an async result you may want to check for success and either return the body or fail the future with an exception:-

public int invoke() throws Exception { // Ugly hack to throw exception and probably needs better consideration
final CompletableFuture<Integer> future = new CompletableFuture<>();
vertx.eventBus().<Integer>send("vertx.demo", "Latest", result -> {
if (result.succeeded()) {
future.complete(result.result().body());
} else {
future.completeExceptionally(result.cause());
}
});
return future.get(2, TimeUnit.SECONDS);
}

Jez P

unread,
Nov 18, 2016, 1:47:56 PM11/18/16
to vert.x
I think you've already pretty much nailed it but here's a demo with some logging in to show you what's going on with the threading


(log at INFO level should show the thread names, and you should see that the blocked thread is the one one which your controller code is being carried out, the vert.x stuff carries on regardless).

I did some searching about the async servlet stuff to see if there was a way of just returning some kind of future to the controller which Spring MVC could directly interpret but I didn't get much luck. The async stuff appears to be more about passing long-running code to a worker pool, but I will do some more reading, because i meant to read up on the Spring MVC async support earlier but never got round to it.

Jez P

unread,
Nov 18, 2016, 1:52:05 PM11/18/16
to vert.x
Also looked at DeferredResult which might solve the problem (but is tightly coupled to async processing, meaning it may not be nice for you)

Psycho Punch

unread,
Nov 20, 2016, 10:52:04 PM11/20/16
to vert.x
Hi Jez,

Actually, DeferredResult (async controller) was what I was about to look into next until I read your suggestion on CompletableFuture. The thing with DeferredResult though is that I have to make the service interface explicitly async, which was ok if I didn't really have much choice. For now, based on the project's state, I guess CompletableFuture works just fine.

Thanks for all your help. I really appreciate it.

Jez P

unread,
Nov 21, 2016, 2:28:20 PM11/21/16
to vert.x
I think for what you want to do, the completable future approach is probably most appropriate. Anything else does tightly couple your API to async behaviour (and specifically the Spring expression of the async behaviour) which feels a bit clunky to me. If you want to make everything non-blocking end to end, you're kind of stuck with that approach (though you could write a simple adapter which adapts a CompletableFuture to a deferred result, then internally all your services could return a CompletableFuture, and you could offer a sync wrapper which awaits completion on the calling thread, and an async wrapper which converts the CompletableFuture to a DeferredResult then returns it). That would enable some mixing and matching of async/sync interfaces. Candidly though, it doesn't feel like you need that at present, which means IMO it would be over engineering. 

Out of interest, in your use-case what's the benefit of using vert.x behind the blocking API? I'd normally say the big kickass win of vert.x is easy outward scalability, but if you're operating a thread pool where you're allowed to block while awaiting the behind-the-scenes processing, that seems a little lessened (though you could build a network of behind-the-scenes non-blocking microservices and just scale the bits that call into that network with more instances perhaps). Not asking you to justify your decisions, just trying to understand what you're getting out of it. I'm a fan of both Spring Boot and vert.x so interested in the use-cases where there is a case for using both :)

Pradyumna Achar

unread,
Dec 8, 2016, 2:23:07 AM12/8/16
to vert.x
Hi Jez,
I'm in this same situation (where a Spring-MVC controller needs to block while it gets work done through Vertx's eventbus) and found this discussion to be very informative. Thanks.

I have a small clarification to ask in this regard -- is it guaranteed that every thread that Vertx internally uses to run its event loops will be distinct from the thread that instantiated the Vertx instance (via Vertx.vertx())? 
(If it is not so, the thread using which Spring creates the bean-that-creates-the-Vertx-instance gets messy, as Vertx could use this thread it as one of its event loop threads as well)

[p.s.  -- although I'd like to change the whole thing to use Vertx, I haven't found enough time for the rewrites & testing -- gets especially complicated if there are multiple branches of the same codebase being worked on by different teams that'll have to merge into one in a few months]

Julien Viet

unread,
Dec 8, 2016, 2:27:59 AM12/8/16
to ve...@googlegroups.com
On Dec 8, 2016, at 8:23 AM, Pradyumna Achar <pradyum...@gmail.com> wrote:

Hi Jez,
I'm in this same situation (where a Spring-MVC controller needs to block while it gets work done through Vertx's eventbus) and found this discussion to be very informative. Thanks.

I have a small clarification to ask in this regard -- is it guaranteed that every thread that Vertx internally uses to run its event loops will be distinct from the thread that instantiated the Vertx instance (via Vertx.vertx())? 

yes, Vert.x manages its own event loop threads and you can change the number of event loops by configuration of the VertxOptions.

(If it is not so, the thread using which Spring creates the bean-that-creates-the-Vertx-instance gets messy, as Vertx could use this thread it as one of its event loop threads as well)

[p.s.  -- although I'd like to change the whole thing to use Vertx, I haven't found enough time for the rewrites & testing -- gets especially complicated if there are multiple branches of the same codebase being worked on by different teams that'll have to merge into one in a few months]

On Tuesday, 22 November 2016 00:58:20 UTC+5:30, Jez P wrote:
I think for what you want to do, the completable future approach is probably most appropriate. Anything else does tightly couple your API to async behaviour (and specifically the Spring expression of the async behaviour) which feels a bit clunky to me. If you want to make everything non-blocking end to end, you're kind of stuck with that approach (though you could write a simple adapter which adapts a CompletableFuture to a deferred result, then internally all your services could return a CompletableFuture, and you could offer a sync wrapper which awaits completion on the calling thread, and an async wrapper which converts the CompletableFuture to a DeferredResult then returns it). That would enable some mixing and matching of async/sync interfaces. Candidly though, it doesn't feel like you need that at present, which means IMO it would be over engineering. 

Out of interest, in your use-case what's the benefit of using vert.x behind the blocking API? I'd normally say the big kickass win of vert.x is easy outward scalability, but if you're operating a thread pool where you're allowed to block while awaiting the behind-the-scenes processing, that seems a little lessened (though you could build a network of behind-the-scenes non-blocking microservices and just scale the bits that call into that network with more instances perhaps). Not asking you to justify your decisions, just trying to understand what you're getting out of it. I'm a fan of both Spring Boot and vert.x so interested in the use-cases where there is a case for using both :)

On Monday, November 21, 2016 at 3:52:04 AM UTC, Psycho Punch wrote:
Hi Jez,

Actually, DeferredResult (async controller) was what I was about to look into next until I read your suggestion on CompletableFuture. The thing with DeferredResult though is that I have to make the service interface explicitly async, which was ok if I didn't really have much choice. For now, based on the project's state, I guess CompletableFuture works just fine.

Thanks for all your help. I really appreciate it.

-- 
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.
Visit this group at https://groups.google.com/group/vertx.
Reply all
Reply to author
Forward
0 new messages