I'm wondering what the cleanest way is to go through a collection in RxJava syntax and raise an error if any item(s) do not exist. A hybrid example is shown below, but ideally I'd like all the logic in RxJava syntax.:
public Single<List<Bar>> doSomething(Collection<String> ids) {
Single<List<Bar>> bars = getAllBars();
List<Bar> results = bars
.flattenAsObservable(z-> z)
.filter(bar -> ids.contains(bar.getId())
.toList()
.blockingGet();// Blocking since I don't know the RxJava syntax for below
if (results.isEmpty()) {
throw SomeError();
}
if (results.size() != ids.size()) {
// Ideally know which bar(s) are not in the ids list
throw someError();
}
return Single.just(results);
}
Actually, this can be achieved quite simply if you propagate an error downstream if an id is not found and subscribe where ever you want to act on that error. It's also quite easy to include info about the missing bar(s) like so:
public Single<List<Bar>> doSomething(Collection<String> ids) {
return getAllBars()
.map(bars -> {
List<Bar> unknownBars = new ArrayList<>();
for(Bar bar : bars) {
if(!ids.contains(bar.getId()) {
unknownBars.add(bar);
}
}
if (unknownBars.isEmpty()) {
return bars;
} else {
throw new BarsNotFoundException(unknownBars);
}
});
}
//elsewhere
doSomething(ids)
.subscribe(bars -> { /* do something */ }, throwable -> { /* handle error */ });
If the throw statement gets reached in your map, the second lambda of your subscribe method will be executed with the error you've thrown.
What I've learned from using rx myself: When you're starting to get more comfortable with it, it starts to feel like a fancy new hammer and suddenly everything looks like a nail. Remember to only use it when it makes your life easier, not harder.