compose with vertx for sequential code - vert.x

I have two operations step_1() and step_2() and want to execute step_2() AFTER step_1().
With normal java this would be:
step_1();
step_2();
With vertx I have to use vertx-compose(). Am I right?
According to https://groups.google.com/forum/#!topic/vertx/FuvlPLpoGOA, I dont need Futures for sequential code.
"If you want to do each request sequencially you dont need futures."
So how can I do that without using futures?
I dont know, if this matters: My Vertx from which this code is executed is a "Worker"-Verticle.
#Override
public void start(Future<Void> fut) throws IOException {
Future<Void> step_1 = Future.future();
step_1.compose(res -> {
// If the future succeeded
Future<Void> step_2 = step_1();
step_2.compose(res2 -> {
step_2();
}, Future.future().setHandler(handler -> {
// If the future failed
}));
//I dont need that
}, Future.future().setHandler(handler -> {
// If the future failed
}));
}
public void step_1(){
..
}
public void step_2(){
..
}
Is this the right and shortest (!) way?

Below is an example of chaining of Future, I have made the example very trivial nonetheless it showcases the concept.
#RunWith(VertxUnitRunner.class)
public class Chaining {
private Vertx vertx = Vertx.vertx();
#Test
public void futures_chaining(TestContext context) throws Exception {
Async async = context.async();
firstOperation()
.compose((outcome) -> {
System.out.println(outcome);
return secondOperation();
})
.compose(outcome -> {
System.out.println(outcome);
/*
For stopping unit test we are returning this future
for production use-case this would be Future.succeededFuture
or Future.failedFuture depending on your method outcomes
*/
return Future.future(handle -> async.complete());
});
}
private Future<String> firstOperation() {
Future<String> future = Future.future();
vertx.setTimer(1000, delay -> future.complete("First Operation Complete"));
return future;
}
private Future<String> secondOperation() {
Future<String> future = Future.future();
vertx.setTimer(1000, delay -> future.complete("Second Operation Complete"));
return future;
}
}

"If you want to do each request sequencially you dont need futures."
No, it's not. In asynchronous frameworks like Vert.x, input/output operations are non-blocking. It means, that if you call few asynchronous operations, they'll start working simultaneously. And if you want to do few requests sequentially, then you should use futures or callbacks to execute new request only after previous one finished successfully.
Check this code with futures, newer version with RxJava 2 and article about project.
#Override
public Future<Optional<Todo>> getCertain(String todoID) {
Future<Optional<Todo>> result = Future.future();
redis.hget(Constants.REDIS_TODO_KEY, todoID, res -> {
if (res.succeeded()) {
result.complete(Optional.ofNullable(
res.result() == null ? null : new Todo(res.result())));
} else
result.fail(res.cause());
});
return result;
}
#Override
public Future<Todo> update(String todoId, Todo newTodo) {
return this.getCertain(todoId).compose(old -> {
if (old.isPresent()) {
Todo fnTodo = old.get().merge(newTodo);
return this.insert(fnTodo)
.map(r -> r ? fnTodo : null);
} else {
return Future.succeededFuture();
}
});
}

RxJava exists specifically to compose async events: http://vertx.io/docs/vertx-rx/java/
Assuming both step_1() and step_1() aren't designed to return results (i.e. they effectively return void) then you could change them to return Observable or Single and chain them together similar to this:
step_1().doOnSuccess(this::step_2()).subscribe(/* control resumes here */);
RxJava (or rather, reactive programming in general) takes a little bit to wrap your head around it, but I would strongly recommend using it if you're planning to chain together async operations.

Pass step_2 as argument to step_1
#Override
public void start(Future<Void> fut) throws IOException {
step_1(step_2);
}
private void step_1(Runnable function){
someAsynccall("some-arg", response -> {
function.run();
}).end();
}
private void step_2(){
// do something
}

Related

RxJava: how to do a second api call if first is successful and then create a combinded response

This is what I want to do:
call first rest API
if first succeeds call seconds rest API
if both are successful -> create an aggregated response
I'm using RxJava2 in Micronaut.
This is what I have but I'm not sure it's correct. What would happen if the first or second API call fails?
#Singleton
public class SomeService {
private final FirstRestApi firstRestApi;
private final SecondRestApi secondRestApi;
public SomeService(FirstRestApi firstRestApi, SecondRestApi secondRestApi) {
this.firstRestApi = firstRestApi;
this.secondRestApi = secondRestApi;
}
public Single<AggregatedResponse> login(String data) {
Single<FirstResponse> firstResponse = firstRestApi.call(data);
Single<SecondResponse> secondResponse = secondRestApi.call();
return firstResponse.zipWith(secondResponse, this::convertResponse);
}
private AggregatedResponse convertResponse(FirstResponse firstResponse, SecondResponse secondResponse) {
return AggregatedResponse
.builder()
.something1(firstResponse.getSomething1())
.something2(secondResponse.getSomething2())
.build();
}
}
This should be as simple as
public Single<AggregatedResponse> login(String data) {
return firstRestApi.call(data)
.flatMap((firstResponse) -> secondRestApi.call().map((secondResponse) -> {
return Pair.create(firstResponse, secondResponse);
})
.map((pair) -> {
return convertResponse(pair.getFirst(), pair.getSecond());
});
}
In which case you no longer need zipWith. Errors just go to error stream as usual.

Android Room with RXJava2; onNext() of emitter is not properly triggered

I am switching from async tasks to rxjava2 and have some issues with my code tests.
I have a room table of elements that have a certain monetary amount. On a usercontrol that is called DisplayCurrentBudget, a sum of all amounts should be displayed. This number must refresh everytime a new element is inserted. I tackled the requirement in two ways, but both produce the same result: My code does not care if the database is updated, it only updates when the fragment is recreated (onCreateView).
My first attempt was this:
//RxJava2 Test
Observable<ItemS> ItemObservable = Observable.create( emitter -> {
try {
List<ItemS> movies = oStandardModel.getItemsVanilla();
for (ItemS movie : movies) {
emitter.onNext(movie);
}
emitter.onComplete();
} catch (Exception e) {
emitter.onError(e);
}
});
DisposableObserver<ItemS> disposable = ItemObservable.
subscribeOn(Schedulers.io()).
observeOn(AndroidSchedulers.mainThread()).
subscribeWith(new DisposableObserver<ItemS>() {
public List<ItemS> BadFeelingAboutThis = new ArrayList<ItemS>();
#Override
public void onNext(ItemS movie) {
// Access your Movie object here
BadFeelingAboutThis.add(movie);
}
#Override
public void onError(Throwable e) {
// Show the user that an error has occurred
}
#Override
public void onComplete() {
// Show the user that the operation is complete
oBinding.DisplayCurrentBudget.setText(Manager.GetBigSum(BadFeelingAboutThis).toString());
}
});
I already was uncomfortable with that code. My second attempt produces the exact same result:
Observable<BigDecimal> ItemObservable2 = Observable.create( emitter -> {
try {
BigDecimal mySum = oStandardModel.getWholeBudget();
emitter.onNext(mySum);
emitter.onComplete();
} catch (Exception e) {
emitter.onError(e);
}
});
DisposableObserver<BigDecimal> disposable = ItemObservable2.
subscribeOn(Schedulers.io()).
observeOn(AndroidSchedulers.mainThread()).
subscribeWith(new DisposableObserver<BigDecimal>() {
#Override
public void onNext(BigDecimal sum) {
// Access your Movie object here
oBinding.DisplayCurrentBudget.setText(sum.toString());
}
#Override
public void onError(Throwable e) {
// Show the user that an error has occurred
}
#Override
public void onComplete() {
// Show the user that the operation is complete
}
});
Any obvious issues with my code?
Thanks for reading, much appreciate it!
Edit:
I was asked what Manager.GetBigSum does, it actually does not do much. It only adds BigDecimal-Values of an Item list.
public static BigDecimal GetBigSum(List<ItemS> ListP){
List<BigDecimal> bigDList = ListP.stream().map(ItemS::get_dAmount).collect(Collectors.toList());
return bigDList.stream()
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
Further, I simplified the query. But it still does not care about DB updates, only about fragment recreation:
Single.fromCallable(() -> oStandardModel.getItemsVanilla())
.map(Manager::GetBigSum)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
e -> oBinding.DisplayCurrentBudget.setText(e.toString())
);
Your rx logic has no error. That should be internal error in your getWholeBudget.
But why you write rx so complex?
For your case, you can just write:
Single.fromCallable(() -> oStandardModel.getItemsVanilla())
.map(Manager::GetBigSum)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
e -> oBinding.DisplayCurrentBudget.setText(sum.toString()),
e -> log.error(e));
I solved it this way:
oStandardModel.getItemJointCatLive().observe(this, new Observer<List<ItemJointCat>>() {
#Override
public void onChanged(#Nullable final List<ItemJointCat> oItemSP) {
Single.fromCallable(() -> oStandardModel.getWholeBudget())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
e -> oBinding.DisplayCurrentBudget.setText(e.toString())
);
}
});
My mistake was that I assumed RXjava2 does not need an onchanged event...now i just use onchanged event of livedata observer to trigger a simple rxjava2 query.
Do you think there is anything wrong with that approach?

Vert.x: Verticle custom startFuture handler is always rewritten

Vert.x v3.5.1.
There is my custom start method of Verticle:
#Override
public void start(Future<Void> startFuture) throws Exception {
startFuture.setHandler(event -> {
if (event.succeeded()) {
logger.info("Server started on port: {}", 8080);
} else {
logger.warn("Failed to start: {}", event.cause());
}
});
vertx.createHttpServer()
.requestHandler(router()::accept)
.listen(8080, event -> {
if (event.succeeded()) {
startFuture.complete();
} else {
startFuture.fail(event.cause());
}
});
}
I expect that my custom handler will be invoked when future completes. But it doesn't!
In debug mode I see that FutureImpl::setHandler is called twice: once with my custom handler, and then with DeploymentManager's handler during doDeploy.
So the latest handler is applied.
The question is: is it possible to specify custom callback for Verticle start? If yes how can I do it?
Thank you in advance.
You're not supposed to change the handler of the startFuture, as it is owned by the caller. So simply, don't do that :) The future is used to signal that you're done with your start-code, and not to define what should be done, once you're done.
In your concrete example it'd be better to write the logs once the http server came up, and then indicate to the startFuture, that you're done with your code execution.
#Override
public void start(Future<Void> startFuture) throws Exception {
vertx.createHttpServer()
.requestHandler(router()::accept)
.listen(8080, event -> {
if (event.succeeded()) {
logger.info("Server started on port: {}", 8080);
startFuture.complete();
} else {
logger.warn("Failed to start: {}", event.cause());
startFuture.fail(event.cause());
}
});
}
At first, write your verticle as a AbstractVerticle extension. And do not override start(Future) method. Instead use start() method. It will be called from AbstractVerticle.start(Future), and you can specify that future in Vertx.deployVerticle(verticle, options, future) method.
For example:
You have some verticle. Do in it start() method only initialization tasks:
#Override
public void start() throws Exception {
vertx.eventbus().consume(address, m -> {
// consumer code skipped
});
}
and verticle registration:
final DeploymentOptions opts = new DeploymentOptions().setWorker(true);
vertx.deployVerticle(verticle, opts, event -> {
if (event.succeeded()) {
log.info("Verticle successfully deployed. DeploymentId: " + event.result());
} else {
log.error("Verticle failed to deploy. Cause: " + event.cause().getMessage(), event.cause());
}
});
That's all :)

Wrapping event listeners in Observables

I've seen a lot of examples of how to turn finite things like arrays or Iterables into Observables, but I'm not sure I understand how to make an Observable out of something live and effectively unbounded like an event receiver. I studied the RxJava2 docs and came up with this, using an Android LocationListener as an example.
Is there a simpler and/or more correct way to do this? I'm aware of the "RxBus" concept, but it seems like a way of clinging to the old event bus paradigm.
final Observable<Location> locationObservable = Observable.create(new ObservableOnSubscribe<Location>() {
final LocationManager mLocationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
#Override
public void subscribe(final ObservableEmitter<Location> emitter) throws Exception {
final LocationListener listener = new LocationListener() {
#Override
public void onLocationChanged(final Location location) {
emitter.onNext(location);
}
#Override
public void onStatusChanged(final String s, final int i, final Bundle bundle) {
// TODO ???
}
#Override
public void onProviderEnabled(final String s) {
// TODO ???
}
#Override
public void onProviderDisabled(final String s) {
// TODO ???
}
};
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, listener);
emitter.setCancellable(new Cancellable() {
#Override
public void cancel() throws Exception {
mLocationManager.removeUpdates(listener);
}
});
emitter.setDisposable(new Disposable() {
private AtomicBoolean mDisposed;
#Override
public void dispose() {
if(mDisposed.compareAndSet(false, true)) {
mLocationManager.removeUpdates(listener);
}
}
#Override
public boolean isDisposed() {
return mDisposed.get();
}
});
}
});
using Observable.create() is indeed a correct way.
However, with RxJava2 the default way is to extend an Observable, you can see this answer for greater details.
some comments though regarding your implementation:
- there is no point setting both Cancellable and Disposable, as the later one will cancel/dispose the first one, you can see the difference between them here.
- I think it's best practice, to register cancellable/disposable before you start listening to update, in order to prevent weird edge cases races.

Async CSLA Calls

The 'standard' CSLA async server calls have typically been structured per the following:
Base class:
public static void GetMyObject(EventHandler<DataPortalResult<MyObject>> callback) {
var dp = new DataPortal<MyObject>();
dp.FetchCompleted += callback;
dp.BeginFetch();
}
ViewModel:
protected override void OnInitialize(object parameter) {
base.OnInitialize(parameter);
base.IsBusy = true;
MyObject.GetMyObject((o, e) => {
if (HasNoException(e)) {
Model = e.Object;
}
base.IsBusy = false;
});
}
With the new async/await features, the format would be something like this:
public async static Task<MyObject> GetMyObject() {
return await DataPortal.FetchAsync<MyObject>();
}
and
protected async override void OnInitialize(object parameter) {
base.OnInitialize(parameter);
base.IsBusy = true;
Model = await MyObject.GetMyObjectAsync();
base.IsBusy = false;
}
Should the callback pattern be considered deprecated at this point, or is it still useful for certain UI technologies? When doing a new project, I'd rather not have those methods in there if I can help it.
Personally, I prefer TAP methods over callbacks in all my code.
With Microsoft.Bcl.Async, most platforms support async. However, there are a few situations where neither TAP nor Task is available, e.g., Windows Phone 7.0, .NET CF, SL 3. I would only use callbacks if I had to support one of those platforms.