Handling Service call errors with ErraiCallback - java

What is the requirement in a Service implementation so that the ErrorCallback will be able to print the error message on the UI like.
I tried injecting a ErrorCallback in the Service call code, and when I print the Message object its null.
What should be the Service implementation look like, should I put throws SomeException on the implementation method? Or?
myService.call(new RemoteCallback<String>() {
#Override
public void callback(String response) {
Multimap<String, String> state = ArrayListMultimap.create();
state.put("hash", response);
submit.go(state);
}
}, new ErrorCallback() {
#Override
public boolean error(Message message, Throwable throwable) {
throwable.printStackTrace();
Window.alert("Error: " + message);
return false;
}
}).createmy(my);

Your code should work as stated in the question. The exception thrown by the remote service should be delivered to you in the throwable parameter to your ErrorCallback.error() method.
You only need to put a throws clause on the remote interface if you want to throw a checked exception. Unchecked exceptions should work as you've done it. In fact, there is a disadvantage to declaring checked exceptions on remote interfaces: you will have to surround your RPC calls with a useless try/catch block, like this:
#Remote public interface MyService {
Result dangerousOperation() throws MyCheckedException;
}
and the calling code:
try {
myService.call(new RemoteCallback<Result>() {
#Override
public void callback(final Result result) {
Window.alert("Yay, got a result: " + result);
}
},
new BusErrorCallback() {
#Override
public boolean error(Message message, Throwable throwable) {
Window.alert("Got an exception from the remote service: " + throwable);
return false;
}
}).dangerousOperation();
}
catch (MyCheckedException e) {
throw new AssertionError(); // can't happen: caller stub won't throw this
}
So you're probably better off with the unchecked exception.

Related

RxJava - Using Single.Error / Observable.error vs throwing exception

I have recently started using RxJava2 in one of my projects and currently I am working on implementing error handling in it.
I have written a mock class below in which I was initially throwing the error after wrapping it in a custom exception. However some of the examples I came across on error handling on stackoverflow and other sites used Single.error instead.
I used both approaches and they resulted in my subscribers onError method being invoked with the / by zero exception. I didn't notice any difference between the two.
There is comprehensive documentation on Error Handling and Error Handling Operators along with a lot of other articles on how to handle the exception after it is thrown. But the information in the javadoc for Single.error and Observable.error is quite minimal.
Is there an advantage of using Single.error or Observable.error over just throwing the exception? When do we choose one approach over the other?
public class Test {
public static void main(String[] args){
Single.just(1)
.flatMap(x -> externalMethod(x))
.subscribe(
s -> System.out.println("Success : " + s),
e -> System.out.println("Error : "+e)
);
}
public static Single<Integer> externalMethod(int x){
int result = 0;
try{
/* Some database / time consuming logic */
result = x % 0;
}
catch (Exception e){
throw new CustomException(e.getMessage()); // --> APPROACH 1
OR
return Single.error(new CustomException(e.getMessage())); // --> APPROACH 2
}
return Single.just(result);
}
}
Actually it does not matter, becaues RxJava tries to catch and relay all Throwables
APPROACH 1 -- throw new CustomException();
(io.reactivex.internal.operators.single.SingleFlatMap)
#Override
public void onSuccess(T value) {
SingleSource<? extends R> o;
try {
o = ObjectHelper.requireNonNull(mapper.apply(value), "The single returned by the mapper is null");
} catch (Throwable e) {
Exceptions.throwIfFatal(e);
downstream.onError(e);
return;
}
if (!isDisposed()) {
o.subscribe(new FlatMapSingleObserver<R>(this, downstream));
}
}
You see here, that given mapper from flatMap is invoked with an try-catch. If the mapper throws a Throwable, the Throwable will be forwarded via onError to downstream subscriber.
APPROACH 2 -- return Single.error(...)
(io.reactivex.internal.operators.single.SingleError)
Single#error
#Override
protected void subscribeActual(SingleObserver<? super T> observer) {
Throwable error;
try {
error = ObjectHelper.requireNonNull(errorSupplier.call(), "Callable returned null throwable. Null values are generally not allowed in 2.x operators and sources.");
} catch (Throwable e) {
Exceptions.throwIfFatal(e);
error = e;
}
EmptyDisposable.error(error, observer);
}
public static void error(Throwable e, SingleObserver<?> observer) {
observer.onSubscribe(INSTANCE);
observer.onError(e);
}
Single#error emits given Throwable on subscription via #onError
When a value is emitted to Single#flatMap the mapper is applied and a subscription is opened returned value from the mapper.
(io.reactivex.internal.operators.single.SingleFlatMap.SingleFlatMapCallback.FlatMapSingleObserver)
#Override
public void onSubscribe(final Disposable d) {
DisposableHelper.replace(parent, d);
}
#Override
public void onError(final Throwable e) {
downstream.onError(e);
}
The returned Single returns a Single#error, which emits a Throwable via #onError. Given #onError will be delegated to the downstream subscriber via onError.
Performance wise one could be faster than the other, but this must be measured to have an exact image. Returning Single#error does more allocations and has more methods on the Stack (subscribeActual). On the other side, when throwing a Throwable it must be caught and handeled.
Therefore in my opinion it acutally does not matter, whether you use the one or the other.

How to handle exceptions when subscribing with Actions in RXJava

Here is a simple example:
Completable c = Completable.create(new CompletableOnSubscribe() {
#Override
public void subscribe(#NonNull CompletableEmitter e) throws Exception {
throw new Exception("Oh No!");
}
});
try {
c.subscribe(new Action() {
#Override
public void run() throws Exception {
Timber.v("It's ok");
}
});
}
catch (Exception e) {
e.printStackTrace();
Timber.v("Error");
}
In this case, I would have expected the exception to be caught however it causes the app to crash. So how are we supposed to handle the exception thrown by the inner class method?
I know that we could handle this differently by subscribing with a CompletableObserver but that adds extra verbosity that I'd like to avoid and I feel that there must be a way to handle this kind of Exception other the Action consumer wouldn't be very useful.
First of all RxJava already has a mechanism to catch Exceptions, But you need to implement onError Action.
have a look at following code:
Completable c = Completable.create(new CompletableOnSubscribe() {
#Override
public void subscribe(#NonNull CompletableEmitter e) throws Exception {
throw new Exception("Oh No!");
}
})
c.subscribe(new Action() {
#Override
public void run() throws Exception {
Timber.v("It's ok");
}
}, new Consumer<Throwable>() { // Second argument is onError Action
#Override
public void accept(Throwable e) {
// Handle you exception here.
Timber.v("Error");
}
});
Let's come to why your code is unable to catch exception even when you have put everything in try-catch, because exception being thrown is instance of RuntimeException class and your are catching instance of Exception class.
Try using RuntimeException, thrown exception should be caught then.
But it is not ideal way to catch exception instead use onError action described in above code snippet. And if your code is throwing Runtime exception then convert it into Exception using try-catch inside Observables.
Hope it helps.
There is an overload for handling errors:
c.subscribe(new Action() {
#Override
public void run() throws Exception {
Timber.v("It's ok");
}
}, new Consumer<Throwable>() {
#Override
public void accept(Throwable e) {
e.printStackTrace();
Timber.v("Error");
}
});

Hystrix circuit breaker with business exceptions

I have observed that Hystrix treats all exceptions coming out of commands as failures for circuit breaking purposes. It includes exceptions which are thrown from command run () method and created by Hystrix itself, e.g. HystrixTimeoutException.
But I have business exceptions to be thrown from run() method that signify that service responded with valid error which has to be processed further.
One example of such exception is WebServiceFaultException while using WebServiceTemplate from SpringWS.
So I do not need those specific exceptions to trip the circuit.
How this behavior can be achieved?
There is an obvious way of wrapping business exceptions into a holder object, returning it from run() method, then unwrapping it back to the Exception and rethrow. But it was wondering if there is a cleaner way.
There are following solutions available.
Return exception instead of throwing
Most straightforward and dirty approach. This looks a little funky, because you have to erase the command to Object and there is a lot of type casting.
Observable<BusinessResponse> observable = new HystrixCommand<Object>() {
#Override
protected Object run() throws Exception {
try {
return doStuff(...);
} catch (BusinessException e) {
return e; // so Hystrix won't treat it as a failure
}
}
})
.observe()
.flatMap(new Func1<Object, Observable<BusinessResponse>>() {
#Override
public Observable<BusinessResponse> call(Object o) {
if (o instanceof BusinessException) {
return Observable.error((BusinessException)o);
} else {
return Observable.just((BusinessResponse)o);
}
}
});
Use holder object to hold both result and exception
This apporach requires introduction of additional holder class (which can also be used on it's own for other purposes).
class ResultHolder<T, E extends Exception> {
private T result;
private E exception;
public ResultHolder(T result) {
this.result = result;
}
public ResultHolder(E exception) {
if (exception == null) {
throw new IllegalArgumentException("exception can not be null");
}
this.exception = exception;
}
public T get() throws E {
if (exception != null) {
throw exception;
} else {
return result;
}
}
public Observable<T> observe() {
if (exception != null) {
return Observable.error(exception);
} else {
return Observable.just(result);
}
}
#SuppressWarnings("unchecked")
public static <T, E extends Exception> ResultHolder<T, E> wrap(BusinessMethod<T, E> method) {
try {
return new ResultHolder<>(method.call());
} catch (Exception e) {
return new ResultHolder<>((E)e);
}
}
public static <T, E extends Exception> Observable<T> unwrap(ResultHolder<T, E> holder) {
return holder.observe();
}
interface BusinessMethod<T, E extends Exception> {
T call() throws E;
}
}
Now code that uses it looks much cleaner, the only downside might be a fair amount of generics. Also this approach is at it's best in Java 8 where lambdas and method references are available, otherwise it will look clunky.
new HystrixCommand<ResultHolder<BusinessResponse, BusinessException>>() {
#Override
protected ResultHolder<BusinessResponse, BusinessException> run() throws Exception {
return ResultHolder.wrap(() -> doStuff(...));
}
}
.observe()
.flatMap(ResultHolder::unwrap);
Use HystrixBadRequestException
HystrixBadRequestException is a special kind of exception which will not count as a failure in terms of circuit breaker and metrics. As seen in documentation:
Unlike all other exceptions thrown by a HystrixCommand this will not
trigger fallback, not count against failure metrics and thus not
trigger the circuit breaker.
Instances of HystrixBadRequestException are not created by Hystrix itself, so it is safe to use it as a wrapper for business exceptions. However, original business exception still requires to be unwrapped.
new HystrixCommand<BusinessResponse>() {
#Override
protected BusinessResponse run() throws Exception {
try {
return doStuff(...);
} catch (BusinessException e) {
throw new HystrixBadRequestException("Business exception occurred", e);
}
}
}
.observe()
.onErrorResumeNext(e -> {
if (e instanceof HystrixBadRequestException) {
e = e.getCause(); // Unwrap original BusinessException
}
return Observable.error(e);
})

Throw Exception in onFailure of LoopJ AndroidAsyncHttp

Edited
I have a custom Exception class MyException
public class MyException extends RunTimeException{
public MyException()
{
super();
}
public MyException(String message)
{
super(message);
}
public MyException(Exception e)
{
super(e);
}
}
now whenever an exception is raised I catch it in MyException and throw it back to the parent function. I am facing an issue as I am using AsyncHttpClient and it raises an exception in onFailure as it is raised by the server.
This is how I am making HTTP Request and trying to handle Exception.
AsyncHttpClient client = new AsyncHttpClient();
client.setTimeout(TIMEOUT);
try {
client.post(mainActivity,
PATH, new StringEntity(requiredDataForRequest),
"application/json", new AsyncHttpResponseHandler() {
#Override
public void onSuccess(String response) {
}
#Override
public void onFailure(int arg0, Header[] arg1,
byte[] arg2, Throwable e) throws MyException {
throw new MyException("Error Description Here!");
}
});
} catch (MyException e) {
log.debug("Exception: " + e.getMessage());
}
Now it is Crashing my app on throw new MyException and not catching it in catch block. Any idea or help would be appreciated.
Because the definition of onFailure does not specify that it throws anything means that none of its implementations can throw a checked exception. You can change your MyException by making it extend RuntimeException, but because it is a runtime exception any callers of onFailure are not required to catch the exception. If you are the only user of this class, that is fine as long as you remember to catch the exception yourself.
You are missing the basic java concept here, you added a throw clause to your onFailure(), but the original method definition does not know what to do if something is thrown!
Basically when you use the throw keyword and throw an exception, then this exception has to be caught at the place where method is called.
Now, since you are overriding onFailure() and the AsyncHttpClient has no catch() for your MyException class, so its simply not getting catched!
If you want to get it catched, write the throw inside a try catch block in your onFailure()
try {
throw MyException();
} catch(MyException e){
// Exception caught
}
this will work as you have a catch for your thrown exception.
Next,In your case you call
try {
client.post(///);
} catch (MyException e) {
// exception caught
}
Now for the exception to be caught it has to be thrown by the client.post method call!
If you look at the post method
public RequestHandle post(android.content.Context context,
java.lang.String url,
org.apache.http.HttpEntity entity,
java.lang.String contentType,
ResponseHandlerInterface responseHandler)
It doesn't throws anything! so your exception will never be called!
And in case you want to catch something, you will either have to modify the library!

GWT. Throw exception inside onFailure()

It is possible to throw exception inside onFailure() method of GWT's RPC call? Because this method will be called later, after server response, I apologize that here may happen something bad..
For example:
public void method() {
try {
rpc.invoke(new AsyncCallback<Void>() {
#Override
public void onSuccess(Void arg0) {}
#Override
public void onFailure(Throwable arg0) {
throw new RuntimeException("Error message"); //HERE
}
});
}
catch (Exception e) {
Window.alert(e.getMessage()); // AND CATCH ABOVE EXCEPTION HERE
}
}
I usually use the following approach on my GWT projects:
1) Create an MyExceptionsHandler:
#Singleton
public class MyExceptionsHandler implements
GWT.UncaughtExceptionHandler,
RpcFailureEvent.Handler, // create corresponding GwtEvent-s
AnyOtherErrorEvent.Handler {
public MyExceptionsHandler(EventBus evenBus) {
eventBus.addHandler(RpcFailureEvent.TYPE, this);
eventBus.addHandler(AnyOtherErrorEvent.TYPE, this);
}
// implement corresponding methods for interfaces
}
2) On entry point:
GWT.setUnchaughtExceptionHandler(myExceptionHandler);
3) In any other place you have an error, which you don't know how to handle:
rpc.invoke(new AsyncCallback<Void>() {
#Override
public void onSuccess(Void arg0) {}
#Override
public void onFailure(Throwable arg0) {
eventBus.fireEvent(new RpcFailureEvent(<any context info you think helpful>));
}
});
Yes, it's possible.
#Override
public void onFailure(Throwable arg0) {
throw new RuntimeException(arg0);
}
This code is absolutely valid. But to what purpose are you creating and throwing a new instance of RuntimeException?
At that if you write
new RuntimeException("Error message")
you lose all information about occurred exception.
And don't forget that in GWT all calls from client to a remote service are handled asynchronously. And the onFailure() callback method are called immediatly when an asynchronous call fails to complete normally.
No, you can't. Well, you can throw the exception, but it won't be handled by the catch block you defined, since the AsyncCallback is an anonymous class that does not run in the same scope and is not called at the same time as your catch block.
You can however try to use GWT.setUncaughtExceptionHandler(), see the details at http://google-web-toolkit.googlecode.com/svn/javadoc/latest/com/google/gwt/core/client/GWT.html.

Categories

Resources