RxJava propogate error from onError to parent from callback - java

I am trying to propagate error from onError to parent caller from Observable.
I am always getting UndeliverableException and control is not getting back to my parent. What can be done to get control over to parent?
public class TestClass {
public void process() {
try {
test();
} catch (Exception ex) {
// Want control here if something goes wrong
}
}
private void test() {
// observable is defined before below call
observable.subscribeWith(new DisposableObserver<Demo>() {
#Override
public void onNext(Demo t) {
// Exception occured here
throw new CustomRunTimeException("Some Exception");
}
#Override
public void onError(Throwable e) {
// I receive CustomRunTimeException here
// how to propagate to caller?
}
#Override
public void onComplete() {
}
});
}
}

As suggested by #akarnokd, I have used blocking subscribe while defining observable. Now, I am able to receive the control back after callback.
observable.blockingSubscribe();

Related

Return value of interface method (no params) is acquired asynchronously. Can it be implemented?

I've been given an interface which is like this:
MyInterface {
List<FirebaseVisionFace> getFaceList();
}
I have to implement it in a class (let's call it MyFirebaseFaceClass) in such a way that we can then do
List<FirebaseVisionFace> faceList = myFirebaseFaceClass.getFaceList()
The problem is that to get this list of faces, the following is required:
Task<List<FirebaseVisionFace>> result =
detector.detectInImage(image)
.addOnSuccessListener(
new OnSuccessListener<List<FirebaseVisionFace>>() {
#Override
public void onSuccess(List<FirebaseVisionFace> faces) {
// Task completed successfully
// ...
}
})
.addOnFailureListener(
new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
// Task failed with an exception
// ...
}
});
Is it possible to implement this getFaceList() method without passing in a callback as a parameter and using the callback to get the list?
You might try using a CompletableFuture. In an implementation of your interface:
class MyImplementation implements MyInterface {
#Override
List<FirebaseVisionFace> getFaceList() {
final CompletableFuture<List<FirebaseVisionFace>> future = new CompletableFuture<>();
final DetectorOfSomeKindYouDidNotSpecifyAbove detector = // ... get detector
detector.detectInImage(image)
.addOnSuccessListener(
new OnSuccessListener<List<FirebaseVisionFace>>() {
#Override
public void onSuccess(List<FirebaseVisionFace> faces) {
// Task completed successfully
future.complete(faces);
}
})
.addOnFailureListener(
new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
// Task failed with an exception
future.completeExceptionally(e);
}
});
try {
return future.get(); // blocks until completion by one of the listeners above
} catch (final RuntimeException throwMe) {
throw throwMe;
} catch (final InterruptedException interruptedException) {
Thread.currentThread().interrupt();
throw new IllegalStateException(interruptedException.getMessage(), interruptedException);
} catch (final Exception everythingElse) {
throw new IllegalStateException(everythingElse.getMessage(), everythingElse);
}
}
}
My error handling code above is stupid for brevity. All code above is untested and written off the cuff. I am assuming that the listeners are called when all discovery is done, and are called once. I'm also assuming that only one of the listeners is called, not both of them. I'm also assuming that they're called by another thread.
Lastly, do note that (as you seem to be aware) an interface like the kind you're trying to implement will inherently remove all benefits of the asynchronicity taking place in its underlying implementation.
Hopefully this will at least point you in the right direction!
If you work with asynchronous tasks in Java, you can't avoid callbacks. You use Task class that uses callbacks a lot. If you don't like this syntax, you can use lambdas:
Task<List<FirebaseVisionFace>> result =
detector.detectInImage(image)
.addOnSuccessListener((List<FirebaseVisionFace> faces) -> {
// Task completed successfully
})
.addOnFailureListener((#NotNull Exception e) -> {
// Task failed with an exception
})
You cannot avoid callbacks, but you can use method references as callbacks, so the whole code looks cleaner:
class MyFirebaseFaceClass implements MyInterface {
List<FirebaseVisionFace> faces;
Exception exception;
boolean done = false;
// Task completed successfully
private synchronized void onSuccess(List<FirebaseVisionFace> faces) {
this.faces = faces;
done = true;
notifyAll();
}
// Task failed with an exception
private synchronized void onError(Exception exception) {
this.exception = exception;
done = true;
notifyAll();
}
List<FirebaseVisionFace> getFaceList() {
detector.detectInImage(image)
.addOnSuccessListener(this::onSuccess)
.addOnFailureListener(this::onError);
synchronized (this) {
while (!done) {
wait();
}
if (exception == null) {
return faces;
} else {
throw new ExcecutionException(exception);
}
}
}
}

Execute same piece of code in catch clause for all methods in a class

I have a class that has many methods. All the methods throw one exception when data is not ready. In that case, I want to retry the method after a certain interval. So in catch, I need to add retry logic. The same logic i need to add for all methods.
Is there some way/pattern to execute same logic for all catch clause without copy paste
One way I could think of is to write my own Exception class and Throw that exception. And do this retry logic from My Exception class.
Is there any other better way to this?
class MyClass {
public void method1() {
try {
//do some logic
} catch (Exception e) {
//retry logic
//existing exception handling logic
}
}
public void method2() {
try {
//do some logic
} catch (Exception e) {
//retry logic
//existing exception handling logic
}
}
public void method3() {
try {
//do some logic
} catch (Exception e) {
//retry logic
//existing exception handling logic
}
}
}
EDIT:
class MyClass {
public void method1(int a, int b) {
try {
//do some logic
} catch (Exception e) {
Object args[] = {a,b};
executeLater("method1",args);
//retry logic
//existing exception handling logic
}
}
public void method2() {
try {
//do some logic
} catch (Exception e) {
Object args[] = null;
executeLater("method1",args);
//retry logic
//existing exception handling logic
}
}
public void method3(String abcd, int a) {
try {
//do some logic
} catch (Exception e) {
Object args[] = {abcd,a};
executeLater("method1",args);
//retry logic
//existing exception handling logic
}
}
public boolean executeLater(String methodName, Object args[]){
//Execute given method with the supplied args
return true;
}
}
Added code that shows what i would be doing in each catch clause
boolean processCompleted=false;
while(!processCompleted){
try{
doProcess();
processCompleted=true;
}catch(Exception e){
Thread.sleep(10000);
}
}
This might give you an idea. It keeps try to call doProcess until it doesn't throw exception. If any exception occurs, waits 10 seconds.
Well, you could extract the whole catch block content to a method and call that one, but this only works if your retry logic is not dependent on the specific method. And it also requires a try-catch in every method.
Instead, use functional programming to shorten it:
public class Playground
{
public static void main(String[] args)
{
new Playground().method2(1, 2);
new Playground().method1();
}
public void method1()
{
tryAndTryAgain(() -> {
// logic 1
System.out.println("no params");
throw new RuntimeException();
});
}
public void method2(int a, int b)
{
tryAndTryAgain(() -> {
// logic 2
System.out.println(a + " " + b);
throw new RuntimeException();
});
}
public static void tryAndTryAgain(Runnable tryThis)
{
try
{
tryThis.run();
}
catch (Exception e)
{
new Timer().schedule(new TimerTask()
{
#Override
public void run()
{
tryAndTryAgain(tryThis);
}
}, 1000);
// existing exception handling logic
}
}
}
The exact structure depends on your specfic implementation, but it should give you an idea how to structure it. The benefit is that all those methods can concentrate on the business logic, and the retry logic and exception handling are done in a util method. And that util method doesn't even need to know anything about parameters, methods, or anything, because all the business logic is contained in the Runnable.

RxJava: Conditionally catch error and stop propagation

I use Retrofit with RxJava Observables and lambda expressions. I'm new to RxJava and cannot find out how to do the following:
Observable<ResponseBody> res = api.getXyz();
res.subscribe(response -> {
// I don't need the response here
}, error -> {
// I might be able to handle an error here. If so, it shall not go to the second error handler.
});
res.subscribe(response -> {
// This is where I want to process the response
}, error -> {
// This error handler shall only be invoked if the first error handler was not able to handle the error.
});
I looked at the error handling operators, but I don't understand how they can help me with my usecase.
Method 1: Keep the two Subscribers but cache the Observable.
Just keep everything as it is now, but change the first line to:
Observable<ResponseBody> res = api.getXyz().cache();
The cache will make sure that the request is only sent once but that sill both Subscribers get all the same events.
This way whether and how you handle the error in the first Subscriber does not affect what the second Subscriber sees.
Method 2: Catch some errors with onErrorResumeNext but forward all others.
Add onErrorResumeNext to your Observable to produce something like this (in the "inner" object):
Observable observable = Observable.error(new IllegalStateException())
.onErrorResumeNext(new Func1<Throwable, Observable<?>>() {
#Override
public Observable<?> call(Throwable throwable) {
if (throwable instanceof NumberFormatException) {
System.out.println("NFE - handled");
return Observable.empty();
} else {
System.out.println("Some other exception - panic!");
return Observable.error(throwable);
}
}
});
And only subscribe once (in the "outer" object):
observable.subscribe(new Subscriber() {
#Override
public void onCompleted() {
System.out.println("onCompleted");
}
#Override
public void onError(Throwable e) {
System.out.println("onError");
e.printStackTrace();
}
#Override
public void onNext(Object o) {
System.out.println(String.format("onNext: %s", String.valueOf(o)));
}
});
This way, the error is only forwarded if it cannot be handled in the onErrorResumeNext - if it can, the Subscriber will only get a call to onCompleted and nothing else.
Having side effects in onErrorResumeNext makes me a bit uncomfortable, though. :-)
EDIT: Oh, and if you want to be extra strict, you could use Method 3: Wrap every case in a new object.
public abstract class ResultOrError<T> {
}
public final class Result<T> extends ResultOrError<T> {
public final T result;
public Result(T result) {
this.result = result;
}
}
public final class HandledError<T> extends ResultOrError<T> {
public final Throwable throwable;
public Result(Throwable throwable) {
this.throwable = throwable;
}
}
public final class UnhandledError<T> extends ResultOrError<T> {
public final Throwable throwable;
public Result(Throwable throwable) {
this.throwable = throwable;
}
}
And then:
Wrap proper results in Result (using map)
Wrap handle-able errors in HandledError and
un-handle-able errors in UnhandledError (using onErrorResumeNext with an if clause)
handle the HandledErrors (using doOnError)
have a Subscriber<ResultOrError<ResponseBody>> - it will get notifications (onNext) for all three types but will just ignore the HandledErrors and handle the other two types.

Java Programming Help- Throwing and Catching an Exception

I have a Java assignment and I need help at this point. Below is the requirement:
Create a WindowMalfunction and PowerOut Events to simulate problems that may occur in a GreenhouseControls. The event should set the following boolean variables as appropriate in GreenhouseControls:
windowok = false;
poweron = false;
After setting the variables, WindowMalfunction or PowerOut should throw an exception specifying the faulty condition. Create a ControllerException class that extends Exception for this purpose.
If an exception is thrown from WindowMalfunction or PowerOut, the Controller catches the exception, then initiates an emergency shutdown with an appropriate message. Add a method to Controller called shutdown, and override this method in GreenhouseControls to accomplish the shutdown.
I have created the ControllerException class:
public class ControllerException extends Exception{
public ControllerException(String except){
super(except);
}
public String getMessage(){
return super.getMessage();
}
public void shutdown(){
}
}
Now I have to implement it in the GreenHouseControls class. This is what I have done:
public class WindowMalfunction extends Event{
ControllerException newExcep= new ControllerException("Error:");
public WindowMalfunction(long delayTime) {
super(delayTime);
}
public void action() throws ControllerException {
}
}
Now, in the action() method of the WindowMalfunction I need to actually throw the ControllerException that I have created. Then, I will need to catch the exception in the Controller.run method.
public void run() throws ControllerException {
while(eventList.size() > 0)
// Make a copy so you're not modifying the list
// while you're selecting the elements in it:
for(Event e : new ArrayList<Event>(eventList)) {
if(e.ready()) {
System.out.println(e);
e.action();
eventList.remove(e);
}
}
}
How do I go about doing so?
Thanks.
In the action() method you can do something like this to throw the exception you just created
throw new ControllerException();
And in run() method put the call to action() method in try-catch block something like
try{
action()
}
catch(ControllerException ex){
System.out.println("Woho caught the exception");
}

How to differentiate between server errors and integrity constraint exceptions when using RPC?

I have this method on the server side talking communicating with the client side code through RPC.
#Override
public void registerStudent(param1, param2...) throws IllegalArgumentException {
//some code here
try {
//some code here
} catch (ConstraintErrorViolationException e) {
throw new RegisterFailedException();
}
}
I have this chunk of code handling failures.
#Override
public void onFailure(Throwable caught) {
displayErrorBox("Could not register user", caught.getMessage());
}
Currently, the onFailure() function does not differentiate between random exceptions and the specific exception I am looking to deal with and handle, which is RegisterFailedException.
How can I successfully handle the two different sort of errors properly?
So your exception
public class RegisterFailedException extends RuntimeException {
public RegisterFailedException () {
super();
}
}
and your method throws the exception like
throws new RegisterFailedException();
Then in onFailure() check
if (caught instanceof RegisterFailedException){
}
If RegisterFailedException is part of the client packages, you can simply use instanceof:
if(caught instanceof RegisterFailedException) {
// handle RegisterFailedException
}
else {
// handle other exceptions
}

Categories