Hot(ish) Observable - java

I need to have something in between hot and cold Observable. It should emit items when client subscribes and stops emission when client unsubscribes. But when client subscribes to the same Observable the remained items should be delivered. And the last thing is time in between items.
Observable<String> hotishObservable = createHotishObservable("a", "b", "c");
Disposable sub = hotishObservable.subscribe();
// emit "a"
// 1 second passed
// emit "b"
sub.dispose()
Disposable sub = hotishObservable.subscribe();
// emit "c"
The obvious solution is to extend ObservableOnSubscribe and handle ObservableEmitter:
class HotishSub implements ObservableOnSubscribe<String> {
public HotishSub(String... items) {
this.items = items;
}
#Override
public void subscribe(ObservableEmitter<String> emitter) {
if(isNotEmpty())
emitter.onNext(nextItem);
executor.schedule(this::handleNext, 1000, TimeUnit.MILLISECONDS);
else
emitter.onComplete();
}
private void handleNext(){
//if emitter is not disposed and there're still items then emit it
}
}
Observable<String> createHotishObservable(String... items){
return Observable.create(new HotishSub(items));
}
Is there any better option?
It's needed for stream of messages from simplified chat bot. UI client code uses the same Observable to get stream of messages from bots and real users.

I use Flowable.generate to do it.
public static <T> Flowable<T> create(T... ts) {
List<T> list = new ArrayList<>(Arrays.asList(ts));
return Flowable.generate(() -> list, (l, e) -> {
if (l.isEmpty()) {
e.onComplete();
} else {
e.onNext(l.remove(0));
if (!l.isEmpty()) {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
// you can use other way to delay it
}
}
}
});
}
Then test it
public static void main(String[] args) throws Exception {
Flowable<String> ob = create("a", "b", "c", "d", "e");
Disposable d = ob.subscribeOn(Schedulers.computation())
.subscribe(i -> System.out.println(System.currentTimeMillis() + "\t" + i));
Thread.sleep(2500);
d.dispose();
ob.subscribeOn(Schedulers.computation())
.blockingSubscribe(i -> System.err.println(System.currentTimeMillis() + "\t" + i));
}
And output:
1520304164412 a // sys.out
1520304165413 b // sys.out
1520304166413 c // sys.out
1520304166928 d // sys.err
1520304167927 e // sys.err

Related

Single.zip - How to catch failed call and continue the rest of network calls?

I'm making 5 parallel network calls, mocking 4 of them to succeed and one of them to fail.
The failed call makes the entire Single.zip() fail and I can't get the results of the 4 other network calls even though they have succeeded.
How can I handle the error for the single failed network call in the Single.zip() and get the results of the ones that have succeeded?
private Single<BigInteger> createNetworkCall(){
return Single.fromCallable(() -> {
return service.getBalance("validaddress").execute();
}).subscribeOn(Schedulers.io());
}
private Single<BigInteger> createFailedNetworkCall(){
return Single.fromCallable(() -> {
return service.getBalance("invalidaddress").execute();
}).subscribeOn(Schedulers.io());
}
private void makeParallelCalls(){
List<Single<BigInteger>> iterable = new ArrayList<>();
iterable.add(createNetworkCall());
iterable.add(createNetworkCall());
iterable.add(createNetworkCall());
iterable.add(createNetworkCall());
iterable.add(createFailedNetworkCall());
Single.zip(iterable, (results) -> {
Log.d(TAG, "makeParallelCalls: " + Arrays.toString(results));
return results;
}).observeOn(AndroidSchedulers.mainThread())
.subscribe(results-> {
Log.d(TAG, "onSuccess: makeParallelCalls: " + results);
}, (exception) -> {
Log.e(TAG, "onError: makeParallelCalls", exception);
});
}
Catch the exception and don't allow the error to interrupt the Single.zip.
For example inside your request factory, return an Optional instead of the response.
private Single<Optional<Long>> performNetworkCall(int n){
return Single.fromCallable(() -> {
if (n % 2 == 0) {
throw new Exception("failed call");
}
return 0L;
}).subscribeOn(Schedulers.io())
.map(Optional::of)
.onErrorReturnItem(Optional.empty());
// or .onErrorReturn(exception -> Optional.empty());
}
private void makeParallelCalls(){
List<Single<BigInteger>> iterable = new ArrayList<>();
iterable.add(performNetworkCall(1));
iterable.add(performNetworkCall(2));
iterable.add(performNetworkCall(3));
iterable.add(performNetworkCall(4));
iterable.add(performNetworkCall(5));
Single.zip(iterable, (results) -> {
for (Object result : results) {
var optional = (Optional<Integer>)result;
if (optional.isEmpty()) {
// this one failed, no data
} else {
var response = optional.get();
}
}
return results;
});
}
You could replace the Optional with a custom class that holds additional information, such as the exception or error information that caused the failure.
If you have recovery options, you could use .onErrorResumeNextinstead.
I'm quite new to RxJava so I don't know if there is a more better solution or if this is a really bad practice, but I used the onErrorReturn callback on the Single.
If someone has a better solution, please share so I can mark yours correct!
public static final int INVALID_USER_ADDRESS = -101;
private Single<BigInteger> createNetworkCall(){
return Single.fromCallable(() -> {
return service.getBalance("validaddress").execute();
}).subscribeOn(Schedulers.io());
}
private Single<BigInteger> createFailedNetworkCall(){
return Single.fromCallable(() -> {
return service.getBalance("invalidaddress").execute();
}).subscribeOn(Schedulers.io()).subscribeOn(Schedulers.io()).onErrorReturn(throwable -> {
if(throwable instanceof IllegalArgumentException){
return BigInteger.valueOf(INVALID_USER_ADDRESS);
}else{
return BigInteger.valueOf(-100);
}
});;
}
private void makeParallelCalls(){
List<Single<BigInteger>> iterable = new ArrayList<>();
iterable.add(createNetworkCall());
iterable.add(createNetworkCall());
iterable.add(createNetworkCall());
iterable.add(createNetworkCall());
iterable.add(createFailedNetworkCall());
Single.zip(iterable, (results) -> {
Log.d(TAG, "makeParallelCalls: " + Arrays.toString(results));
return results;
}).observeOn(AndroidSchedulers.mainThread())
.subscribe(results-> {
for(int i = 0; i < results.length; i++){
if(results[i].equals(INVALID_USER_ADDRESS)){
//Handle error here
}else{
//Handle success value here
}
}
}, (exception) -> {
Log.e(TAG, "onError: makeParallelCalls", exception);
});
}
.subscribe(results-> {
returns:
[2583397195825000000000, 2583397195825000000000, 2583397195825000000000, 2583397195825000000000, -101]

How can I return my database values ​through Vertx?

Good afternoon, I'm trying to get the values from my database and add them to a list and I always get null. What is the cause and how could it save those values? When it comes to printing by console I have no problem. Best regards.
public List<JsonObject> getAll() {
List<JsonObject> listObject = new ArrayList<JsonObject>();
try {
this.connect();
this.client.query("SELECT * FROM user")
.execute().onSuccess(ar -> {
for (Row row : ar) {
listObject.add(row.toJson());
System.out.println("---- OK " + listObject.stream().collect(Collectors.toList()));
}
}
);
} catch (Exception e) {
System.out.println(e.getLocalizedMessage());
}
System.out.println("--- Null: " + listObject.stream().collect(Collectors.toList()));
return listObject;
}
You wouldn't use return since this is an asynchronous call.
Instead, pass a Consumer
public void getAll(Consumer<ArrayList<JsonObject>> callback) {
try {
this.connect();
this.client.query("SELECT * FROM user").execute().onSuccess(ar -> {
List<JsonObject> listObject = new ArrayList<>();
for (Row row : ar) {
listObject.add(row.toJson());
}
System.out.printf("Fetched %d objects%n", listObject.size());
callback.accept(listObject); // this replaces your return statement
});
} catch (Exception e) {
System.out.println(e.getLocalizedMessage()); // TODO: replace with a proper logger
}
}
Elsewhere, pass in an instance of a consumer
databaseClient.getAll(list -> {
// TODO: use the list to perform some action
})
Otherwise, you might want to look at R2DBC and how it can be used to wire subscribers to the result-set.

Java: How can I queue up asynchronous calls to be executed when a certain condition is met?

TL;DR: I want to perform an asynchronous Call to a REST-API. The standard call would give me a CompleteableFuture<Response>, however because the API has a limit on how many calls it allows in a certain amount of time I want to be able to queue up calls to 1. execute them in order and 2. execute them only when I am not exceeding the APIs limits at that current moment, otherwise wait.
Long verson:
I am using Retrofit to perform Rest calls to an API and Retrofit returns a CompleteableFuture<WhateverResponseClassIDeclare> when I call it. However due to limitations of the API I am calling I want to have tight control over when and in what order my calls go out to it. In detail, too many calls in a certain timeframe would cause me to get IP banned. Similarly I want to maintain the order of my calls, even if they won't get executed immediately. The goal is to call a Wrapper of the API that returns a CompleteableFuture just like the original API but performs those in-between steps asynchronously.
I was playing around with BlockingQueues, Functions, Callables, Suppliers and everything inbetween, but I couldn't get it to work yet.
Following there is my currently NON FUNCTIONAL code I created as a Mockup to test the concept.
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.function.Function;
public class Sandbox2 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
MockApi mockApi = new MockApi();
CompletableFuture<Integer> result1 = mockApi.requestAThing("Req1");
CompletableFuture<Integer> result2 = mockApi.requestAThing("Req2");
CompletableFuture<Integer> result3 = mockApi.requestAThing("Req3");
System.out.println("Result1: " + result1.get());
System.out.println("Result2: " + result2.get());
System.out.println("Result3: " + result3.get());
}
public static class MockApi {
ActualApi actualApi = new ActualApi();
BlockingDeque<Function<String, CompletableFuture<Integer>>> queueBlockingDeque = new LinkedBlockingDeque();
public CompletableFuture<Integer> requestAThing(String req1) {
Function<String, CompletableFuture<Integer>> function = new Function<String, CompletableFuture<Integer>>() {
#Override
public CompletableFuture<Integer> apply(String s) {
return actualApi.requestHandler(s);
}
};
return CompletableFuture
.runAsync(() -> queueBlockingDeque.addLast(function))
.thenRun(() -> waitForTheRightMoment(1000))
.thenCombine(function)
}
private void waitForTheRightMoment(int time) {
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static class ActualApi {
public CompletableFuture<Integer> requestHandler(String request) {
return CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return Integer.parseInt(request.substring(3));
});
}
}
}
Pre JDK 9 (JDK 1.8)
You can make use of ScheduledExecutor that accepts items to execute asynchronously on a pre-configured thread pool at a pre-fixed rate / delay.
You can obtain such a service as follows:
private final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
Once an instance of ScheduledExecutorService is created, you can start submitting items (requests) to be executed as follows:
executorService.schedule(
() -> actualApi.requestHandler(req),
delay,
unit
);
Meanwhile, using a direct call want lead a CompletableFuture<Integer> but instead would lead a ScheduledFuture<CompletableFuture<Integer>> on which you will have to block to get the wrapped result.
Instead, you would need to block on your final requests results inside the ScheduledExecutorService then wrap your final request result in a completed ComppletableFuture:
public <T> CompletableFuture<T> scheduleCompletableFuture(
final CompletableFuture<T> command,
final long delay,
final TimeUnit unit) {
final CompletableFuture<T> completableFuture = new CompletableFuture<>();
this.executorService.schedule(
(() -> {
try {
return completableFuture.complete(command.get());
} catch (Throwable t) {
return completableFuture.completeExceptionally(t);
}
}),
delay,
unit
);
return completableFuture;
}
Here down a review version of your implementation:
public class Sandbox2 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
MockApi mockApi = new MockApi();
CompletableFuture<Integer> result1 = mockApi.requestAThing("Req1");
CompletableFuture<Integer> result2 = mockApi.requestAThing("Req2");
CompletableFuture<Integer> result3 = mockApi.requestAThing("Req3");
System.out.println("Result1: " + result1.get());
System.out.println("Result2: " + result2.get());
System.out.println("Result3: " + result3.get());
}
public static class MockApi {
private final AtomicLong delay = new AtomicLong(0);
private final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
public CompletableFuture<Integer> requestAThing(String req1) {
return this.scheduleCompletableFuture(new ActualApi().requestHandler(req1), delay.incrementAndGet(), TimeUnit.SECONDS);
}
public <T> CompletableFuture<T> scheduleCompletableFuture(
final CompletableFuture<T> command,
final long delay,
final TimeUnit unit) {
final CompletableFuture<T> completableFuture = new CompletableFuture<>();
this.executorService.schedule(
(() -> {
try {
return completableFuture.complete(command.get());
} catch (Throwable t) {
return completableFuture.completeExceptionally(t);
}
}),
delay,
unit
);
return completableFuture;
}
}
public static class ActualApi {
public CompletableFuture<Integer> requestHandler(String request) {
return CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return Integer.parseInt(request.substring(3));
});
}
}
}
JDK 9 and onward
If you are using a JDK 9 version, you may make use of the supported delayed Executor:
CompletableFuture<String> future = new CompletableFuture<>();
future.completeAsync(() -> {
try {
// do something
} catch(Throwable e) {
// do something on error
}
}, CompletableFuture.delayedExecutor(1, TimeUnit.SECONDS));
Your MockApi#requestAThing would then be cleaner and shorter and you are no more in need of a custom ScheduledExecutor:
public static class MockApi {
private final AtomicLong delay = new AtomicLong(0);
public CompletableFuture<Integer> requestAThing(String req1) {
CompletableFuture<Void> future = new CompletableFuture<>();
return future.completeAsync(() -> null, CompletableFuture.delayedExecutor(delay.incrementAndGet(), TimeUnit.SECONDS))
.thenCombineAsync(new ActualApi().requestHandler(req1), (nil, result) -> result);
}
// ...
}
You might consider using bucket4j
I have found a way to produce my desired behaviour. By limiting my Executor to a single Thread I can queue up calls and they will follow the order I queued them up in.
I will supply the code of my mock classes below for anyone interested:
import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Sandbox2 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
MockApi mockApi = new MockApi();
CompletableFuture<Integer> result1 = mockApi.requestAThing("Req1");
System.out.println("Request1 queued up");
CompletableFuture<Integer> result2 = mockApi.requestAThing("Req2");
System.out.println("Request2 queued up");
CompletableFuture<Integer> result3 = mockApi.requestAThing("Req3");
System.out.println("Request3 queued up");
//Some other logic happens here
Thread.sleep(10000);
System.out.println("Result1: " + result1.get());
System.out.println("Result2: " + result2.get());
System.out.println("Result3: " + result3.get());
System.exit(0);
}
public static class MockApi {
ActualApi actualApi = new ActualApi();
private ExecutorService executorService = Executors.newSingleThreadExecutor();
;
public CompletableFuture<Integer> requestAThing(String req1) {
CompletableFuture<Integer> completableFutureCompletableFuture = CompletableFuture.supplyAsync(() -> {
try {
System.out.println("Waiting with " + req1);
waitForTheRightMoment(new Random().nextInt(1000) + 1000);
System.out.println("Done Waiting with " + req1);
return actualApi.requestHandler(req1).get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
return null;
}, executorService);
return completableFutureCompletableFuture;
}
private void waitForTheRightMoment(int time) {
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static class ActualApi {
public CompletableFuture<Integer> requestHandler(String request) {
return CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(new Random().nextInt(1000) + 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Request Handled " + request);
return Integer.parseInt(request.substring(3));
});
}
}
}

Returning a value from lambda inside a method

I'm completely lost here.
I have a method like this
String foo(String param) {
seechOutput(params, () -> {
// Callback after the task is performed!
// Speech output task.
speechInput(params, (result) -> {
// Some calculations.
// Now return result to the caller function of foo.
});
});
}
I tried while() loop outside of lambda but that didn't worked.
how to return the value?
Is there is any better design approach?
EDIT: Here is the Original Code.
String getNumberFromName(String name) {
AtomicReference<String> finalResult = new AtomicReference<>("");
int i = 1;
StringBuilder toSpeak = new StringBuilder("There are multiple contacts, Which one you wanted to call? ");
for (String s : hs.keySet()) {
toSpeak.append(i).append(". ").append(s).append(", ");
++i;
}
System.out.println(toSpeak);
audioOutput.speak(String.valueOf(toSpeak), TextToSpeech.QUEUE_FLUSH, "multiple1", () -> {
runOnUiThread(() -> {
mSpeechInput.startListening((str) -> {
finalResult.set(str);
});
});
});
return finalResult.get();
}
Try this
String foo(String param) {
String finalResult = "";
seechOutput(params, () -> {
// Callback after the task is performed!
// Speech output task.
speechInput(params, (result) -> {
// Some calculations.
// Now return result to the caller function of foo.
finalResult = result;
});
});
return finalResult;
}
If your function is synchronous then this will work perfectly. If you're doing some asynchronous operations, then the finalResult will be empty.
If it's asynchronous do it like this
interface AsyncCallback {
void catchResult(String result)
}
Edit your method like
foo(String param,AsyncCallback callback) {
// your code here
speechInput(params, (result) -> {
//here use the method
callback.catchResult(result)
});
}
Use it like
foo("params", new AsyncCallback() {
#Override
public void catchResult(String number) {
// result here
}
});
If you use RxJava, you can go with:
Single<String> speechResult(String param) {
return Single.fromEmitter(emitter -> {
speechOutput(params, () -> {
speechInput(params, (result) -> {
emitter.onSuccess(result);
});
});
});
}
With usage:
speechResult("").subscribe(result -> /* Do something with result */);
You could probably do this with a Future as well, although you'd need to block in the method until it returns.
Or, you can define your own callback:
void speechResult(String param, Consumer<String> onComplete) {
speechOutput(params, () -> {
speechInput(params, (result) -> {
onComplete.accept(result);
});
});
}
With usage:
speechResult("", result -> /* Do something with result*/);

How to execute an Array of CompletableFuture and compose their results

I am investigating Java 8 CompletableFutures and read (and seen) that I should employ thenCompose instead of thenApply.
I have converted my code to use thenCompose but I have a feeling in an incorrect manner.
Here is my controlling code...
final CompletableFuture<List<String>> extractor = get(htmlPageSource);
#SuppressWarnings("unchecked")
final CompletableFuture<List<Documentable>>[] completableFutures =
new CompletableFuture[ENDPOINT.EXTRACTABLES.size()];
int index = 0;
for( ENDPOINT endpoint : ENDPOINT.EXTRACTABLES ) {
final CompletableFuture<List<Documentable>> metaData =
extractor.thenComposeAsync(
s -> endpoint.contactEndpoit(s), executorService );
completableFutures[index++] = metaData.exceptionally(x -> failedList(x));
}
CompletableFuture
.allOf( completableFutures )
.thenComposeAsync( dummy -> combineDocuments( completableFutures ))
.thenAccept ( x -> finish( x ))
.exceptionally( x -> failed( x ));
private List<Documentable> failedList(final Throwable x) {
LOGGER.error("failedList", x);
final List<Documentable> metaData = new ArrayList<>();
return metaData;
}
private Void failed(final Throwable x) {
LOGGER.error("failed", x);
return null;
}
Which I believe is acceptable
However the code that makes me uneasy is this:-
WWW_SITE_ONE("https://example.site.one/") {
#Override
public <T extends Documentable> CompletionStage<List<T>> contactEndpoit( final List<String> elements) {
LOGGER.info("WWW_SITE_ONE " + Thread.currentThread().getName());
final List<T> SITE_ONEs = new ArrayList<>();
for (final String element : elements) {
try {
final String json = Jsoup.connect(ENDPOINT.WWW_SITE_ONE.getBaseUrl() + element).ignoreContentType(true).ignoreHttpErrors(true).maxBodySize(0).timeout(60000).execute().body();
if (json.contains("errors")) {
continue;
}
final T SITE_ONE = OBJECT_READER_SITE_ONE.readValue(json);
SITE_ONEs.add(SITE_ONE);
}
catch( final Throwable e ) {
LOGGER.error("WWW_SITE_ONE failed", e);
throw new RuntimeException(e);
}
}
return CompletableFuture.supplyAsync(() -> SITE_ONEs);
}
},
WWW_SITE_TWO("https://example.site.two/") {
#Override
public <T extends Documentable> CompletionStage<List<T>> contactEndpoit(final List<String> elements) {
LOGGER.info("WWW_SITE_TWO " + Thread.currentThread().getName());
final List<T> SITE_TWOs = new ArrayList<>();
for (final String element : elements) {
try {
final String json = Jsoup.connect(ENDPOINT.WWW_SITE_TWO.getBaseUrl() + element).ignoreContentType(true).ignoreHttpErrors(true).maxBodySize(0).timeout(60000).execute().body();
if (json.equals("Resource not found.")) {
continue;
}
final T SITE_TWO = OBJECT_READER_SITE_TWO.readValue(json);
SITE_TWOs.add(SITE_TWO);
}
catch (final Throwable e) {
LOGGER.error("WWW_SITE_TWO failed", e);
throw new RuntimeException(e);
}
}
return CompletableFuture.supplyAsync(() -> SITE_TWOs);
}
},
WWW_SITE_THREE("https://example.site.three/") {
#Override
public <T extends Documentable> CompletionStage<List<T>> contactEndpoit(final List<String> elements) {
LOGGER.info("WWW_SITE_THREE " + Thread.currentThread().getName());
final List<T> SITE_THREEs = new ArrayList<>();
for (final String element : elements) {
try {
final String SITE_THREEJsonString = Jsoup
.connect( ENDPOINT.WWW_SITE_THREE.getBaseUrl() + element)
.ignoreContentType(true)
.ignoreHttpErrors(true)
.maxBodySize(0)
.timeout(60000)
.execute()
.body();
final SITE_THREE SITE_THREE_Json = OBJECT_READER_SITE_THREE.readValue(SITE_THREEJsonString);
final T SITE_THREE = (T) SITE_THREE_Json;
if (SITE_THREE_Json.getHitCount() > 0) {
SITE_THREEs.add(SITE_THREE);
}
}
catch (final Throwable e) {
LOGGER.error("WWW_SITE_THREE failed", e);
throw new RuntimeException(e);
}
}
return CompletableFuture.supplyAsync(() -> SITE_THREEs);
}
};
Its where I am returning CompletableFuture.supplyAsync(() -> SITE_THREEs);
Is this the correct approach?
Or does this start another asynchronous thread to simply return my List<>?
As the name suggests, supplyAsync will perform an asynchronous operation, executing the Supplier’s get() method, hence the body of the lambda expression, in a background thread, regardless of how trivial it is. Since the implementation of supplyAsync has no way to check how trivial the code encapsulated by the Supplier is, it has to work this way.
Instead of CompletableFuture.supplyAsync(() -> SITE_THREEs), you should use CompletableFuture.completedFuture(SITE_THREEs) which returns a future that has already been completed with the result, hence, not requiring additional actions.
If the method only returns completed stages or throws an exception, you may also change it to return the result value instead of a CompletionStage and use thenApply instead of thenCompose, simplifying your code—unless you want to keep the option of introducing asynchronous operations in a future version of that method.

Categories

Resources