why maybe.toSingle() throw error no such element? I tried to handle doOnError but doesn't work!!
Single<Integer> singleOdd = Single.just(1);
Single<Integer> singleEven = Single.just(2);
Single.concat(singleOdd.filter(integer -> integer%2 ==0).toSingle(),singleEven).doOnError(throwable -> throwable.printStackTrace()).subscribe();
why maybe.toSingle() throw error no such element?
filter() on a Single has two outcomes, either it passes and you have one item, or it doesn't pass and you have an empty Maybe. Converting back to Single mandates that you have exactly one item or an error.
I tried to handle doOnError but doesn't work!!
doOnError is not error handling from the stream's perspective but a peek into the error channel. You have to use onErrorResumeNext or retry to react to an error case.
Related
Our project use a external library. It has a method return FluxMap (since FluxMap is not completely public so just call it Flux):
Flux<MappedType> aFluxMap = Library.createMappingToMappedType();
I have to emit some objects to aFluxMap to get them converted to MappedType (it has private constructor, few setter), then I can:
aFluxMap.doOnNext(converted -> doJob(converted))
I expect that there is a method on Flux/Mono like:
aFluxMap.emit(myObj);
But I could not find any method like that.
I have searched "how to emit to flux dynamically", then there is a solution:
FluxProcessor p = UnicastProcessor.create().serialize();
FluxSink sink = p.sink();
sink.next(mess);
But seem that it emit to newly created flux (p), not my aFluxMap. So I want to ask is there any way to emit message to a existed Flux (or how to connect a FluxSink to a existed Flux, so that whenever FluxSink .next(mess), then the existed Flux get the message). Thank you
Note: please don't pay much attention to the stupidity of the library. We must use it
==========================================
UPDATE:
As #lkatiforis suggestion:
FluxProcessor p = //see above
Flux<MappedType> aFluxMap = Library.createMappingToMappedType();
p.flatMap(raw -> aFluxMap).subscribe();
I got another issue. Library.createMappingToMappedType() return a subscribed Flux with its source is UnicastProcessor (also subscribed).
When I call p.flatMap(raw -> aFluxMap), then internally aFluxMap get subscribed again cause its source also get subscribed again, so that I got an exception telling that "UnicastProcessor can be subscribe once". Any suggestion?
You can create a new stream and then merge the two streams into one by using one of these methods: merge, concat, zip, and their variants.
Here is an example:
Flux<MappedType> yourFlux = //...
Flux<MappedType> aFluxMap = Library.createMappingToMappedType();
Flux.merge(aFluxMap, yourFlux);
The merge operator executes a merging of the MappedType objects from the two provided publisher sequences.
I am currently creating a retry mechanism for performing requests using the failsafe-lib.
The issue: the RetryPolicy that I defined includes several timeout-related exceptions, but when I use the failsafe-lib (Failsafe.with(someFallback, somePolicy).get(() -> performRequest), exceptions that I did not specify (DataBufferLimitException) to be handled are negated instead of being thrown.
Now I understand that the FailsafeExecutor(...).get() method takes a CheckedSupplier, and this (possibly) might cause in negation of unchecked exceptions (please correct me if I'm wrong, this is just an assumption). However, I am still curious if I have done something wrong and if there is something that I can do to resolve this issue.
Below I have a simplified version of my code:
public Response performRequest() {
RetryPolicy<Object> retryPolicy = RetryPolicy.builder()
.withDelay(Duration.ofMillis(60_000L))
.handle(exceptionA, exceptionB, ...)
.withMaxRetries(3)
.onSuccess(o -> log.info("someRandomMessage"))
.onFailure(o -> log.warn("someRandomWarnMessage"))
.onRetriesExceeded(o -> log.error("someRandomErrorMessage"))
.build();
Fallback<Object> fallback = Fallback.of(event -> {
Throwable rootException = ExceptionUtils.getRootCause(event.getLastException());
if (rootException instanceof TimeoutException || rootException instanceof ConnectException) {
throw new someRandomException(rootException.getMessage());
}
}
);
Response response Failsafe.with(fallback, retryPolicy).get(() -> someRequest);
return response;
The scenario that is performed with this code:
We perform a request and (during testing) we expect to see an unchecked exception. However, this exception is 'swallowed' by functionality of the failsafe-lib, while I in fact want to see back this exception. I know this is more on my end, but I'm not sure how to fix this issue. Any tips, alternatives or corrections are much appreciated.
Found my own mistake: if the if-statement was not triggered, no exception would be thrown and null would be returned. This resulted in an empty response, etc.
Consider this example:
I have a file downloading in sequence. If one download fails, it should move to next.
Psudo code:
Observable.from(urls)
.concatMap(url -> downloadObservable(url))
There is no option for moving to next url if the download fails.
There is no way to skip with onErrorResumeNext() as I just want to move to next url. Can anyone help?
There is an operator for this: concatMapDelayError since 1.3. In general, if there is a reason errors could be delayed until all sources have been consumed fully, there is likely a opNameDelayError operator for it.
Observable.from(urls)
.concatMapDelayError(url -> downloadObservable(url))
.doOnError(error -> {
if (error instanceof CompositeException) {
System.out.println(((CompositeException)error).getExceptions().size());
} else {
System.out.println(1);
}
});
(The doOnError addendum comes from the updated OP's cross post on the RxJava issue list.)
If you are using RxJava 1, a quick and dirty solution is to return null when the download fails and then filter them out:
Observable
.from(urls)
.concatMap(url -> downloadObservable(url).onErrorReturn(null))
.filter(result -> result != null)
A nicer solution would be to create a wrapper for the result having a method like wasSuccessful() for checking in the filter and a method like getResult() for extracting the result from the wrapper. This way you don't have to handle nulls.
According to: https://github.com/ReactiveX/RxJava/issues/3870 there is no way to do this. Of course you can introduce some other error handling, i.e. handle error inside downloadObservable then filter null answers.
You have to think that is a pipeline so, in case you don't want to stop the emission of the pipeline, you have to control the error and return something in order to continue with the next emission.
The only way to use onErrorResumeNext and not stop the emission after that, is if it´s executed in a flatMap
Observable.from(urls)
.flatMap(url -> downloadObservable(url)
.onErrorResumeNext(t -> Observable.just("Something went wrong"))))
You can see an example here https://github.com/politrons/reactive/blob/master/src/test/java/rx/observables/errors/ObservableExceptions.java
I'm trying to filter a list which might or might not be empty (or the item is not in the list). inboxData is filled by another observable:
private BehaviorSubject<InboxResponse> inboxData = BehaviorSubject.create();
public Observable<Item> getInboxItem(String id) {
return inboxData
.flatMap(response -> Observable.from(response.getData()))
.filter(item -> item.getId().equals(id))
.firstOrDefault(null);
}
In this case if response.getData() is empty firstOrDefault never runs. But why? It clearly says that it gives you back the default value if the preceeding observable emits nothing.
firstOrDefault emits the default if the stream completes without any items being passed through the observable. For your stream to complete the BehaviorSubject would need to signal completion. Since there is no indication that happens it would never realize it needs to send the default.
The solution is to move the filter and firstOrDefault to the inside of the flatMap so the end of the list provided by getData ends up completing the inner stream.
Note that if you're using RxJava2 as your tags suggest, null can never be an item in the stream, so passing it as default would cause an exception.
public Observable<Item> getInboxItem(String id) {
return inboxData
.flatMap(response -> Observable.from(response.getData()))
At this point, response.getData() returns null, right?
.filter(item -> item.getId().equals(id))
That means that item here is null. So item.getId() throws a NullPointerException. An error like that is immediately passed to the subscriber's onError handler. The firstOrDefault method will not even be called anymore, because the stream is immediately terminated.
.firstOrDefault(null);
}
I have a List<Observable<?>> and I want to get the first item emitted by any of these (running sequentially) or return error from last observable if all returned error or custom error if all were empty (which I can do with .switchIfEmpty(Observable.error(RuntimeException()))).
Currently, I have something like this:
Observable.fromIterable(listOfObservables)
.take(1)
.switchIfEmpty(Observable.error(RuntimeException()))
This code handles getting only first emitted value and returning an error if all observables were empty but don't handle error case. Any ideas how I can solve that part?
This code should do what you want
Observable
.fromIterable(listOfObservables)
.concatMapDelayError(i -> i)
.take(1)
.switchIfEmpty(Observable.error(new RuntimeException()))
concatMapDelayError will process observables sequentially as requested and delay errors till the end, so if every observable is an error you will get CompositeException with all exceptions aggregated.