Use Lambda to wrap methods with same exception handling - java

I have dozens of methods that I want to wrap with the same try/catch handling. I think lambdas can help me out here, but I'm having difficulty figuring out the syntax.
Here's the context of what I'm trying to achieve.
method1(..., result -> method2(result, ...));
method2 is a handler for the results of method1. I would like to wrap method2 with a common try/catch statement that's common to a large number of handlers, without having to copy/paste the statement to all handlers.
Note: These are unchecked exceptions.
*edit - Concrete example of what I'm trying to do.
I'm using Vert.x, and they use a common design pattern of Handlers. Here's an example of their SQL interface
query(String sql, Handler<AsyncResult<ResultSet>> resultHandler)
Handler is a simple 1 function interface:
void handle(E event)
So basically, the query defined in "sql" is executed, and the results are sent to the resultHandler. Here would be an example of this in use:
connection.query("SELECT * from table1", asyncResult -> {
// do something with results
}
The above uses their documentation's standard coding style. I personally prefer to handle the results in named functions various reasons, so it changes to:
connection.query("SELECT * from table1", asyncResult -> method1(asyncResult));
void method1(AsyncResult<ResultSet> asyncResult) {
// do something with results
}
I do not have control over the query() interface, so I'm stuck with this pattern. I'm not sure if Tagir's solution will work in this context, but I'll play around with it in the morning.
*edit2 - I should note that I'm trying to wrap method1 in the above example in the exception wrapper, so ideally, I'd add the wrapper call inside the query() call. So what I'm looking for is something like:
connection.query("SELECT * from table1", wrap(asyncResult -> method1(asyncResult)));
Obviously, I can't use it that way, because it'll evaluate the original lambda as a parameter, but conceptually, that's where I want the wrapping to be added.

You may use Runnable functional interface to implement the method which handles exceptions:
public static void handleExceptions(Runnable r) {
try {
r.run();
}
catch(RuntimeException ex) {
ex.printStackTrace();
}
}
And call it like this:
handleExceptions(() -> method2(foo, bar));
If your method2 produces a result, you should determine what will be the default result in case if exception occurred (and you don't rethrow it in the handler). You may use the Supplier functional interface for such case:
public static <T> T handleExceptions(Supplier<T> r, T defaultValue) {
try {
return r.get();
}
catch(RuntimeException ex) {
ex.printStackTrace();
return defaultValue;
}
}
And call like this:
// set result to null if exception occurred
result = handleExceptions(() -> method2(foo, bar), null);
Or
// do not modify the result if exception occurred
result = handleExceptions(() -> method2(foo, bar), result);

Related

Java does not catch exception

I am trying to implement lambda expression for constructor. My constructor can throw an IllegalArgumentException. I tried different ways. First way is just calling lambda expression:
catchThrowable(() -> new SomeClass(testVar1, null, testVar2));
It works perfectly fine, I can catch Exception and then parse it. The problem occurs when I try to use my own interface:
interface SomeClassFactory{
SomeClass create (String testVar1, String persId, String testVar2) throws IllegalArgumentException;
}
SomeClassFactory factory = SomeClass::new;
and then I use it as:
catchThrowable((ThrowableAssert.ThrowingCallable) factory.create(testVar1, null, testVar3));
But the last line of code does not catch any exceptions, my code gives runtime exception and stops. Can you please explain why it happens and, if possible, how to fix it?
What happens is that factory.create(...) is executed and the result is passed to catchThrowable, so the exception is actually thrown before the catchThrowable execution.
To fix it, you can either use a lambda:
catchThrowable( () -> factory.create(testVar1, null, testVar3));
or you can define your own interface extending ThrowableAssert.ThrowingCallable:
interface SomeClassFactory extends ThrowableAssert.ThrowingCallable {
#Override
SomeClass call() throws IllegalArgumentException;
}
which would allow you to call:
catchThrowable(factory);
Note that the custom interface does not allow parameters on the overridden method.

Throwing Exception in a nested Flowable's onNext is causing an UndeliverableException

I've code like this in a repository:
return Completable.fromAction {
// Some code
loginService.login(id)
.subscribe(
{ response ->
if(response.isNotSuccessful()) {
throw Exception()
}
// Some code
},
{ e ->
throw e
}
)
}
I've code like this in a ViewModel:
fun onLoginAction(id) {
repository.login(id)
.subscribe(
{
showSuccess()
},
{
showFailure()
}
)
}
Basically, the ViewModel calls the login method in the repository which returns the Completable.
This results in an UndeliverableException when the response is not successful. I want the Completable's subscriber's onError() method to be called. How do I do this?
I don't have enough knowledge to actually say this with certainty, but I still think this has some value to you and it's too big for a comment.
Here's what I think it's happening. When onError fails rx won't run this through the same observable stream. Instead, it will propagate this to the RxPlugins error handler and eventually to the default exception handler in your system. You can find this here.
This is to say that when loginService.login(id) throws the exception in the onError, the Completable stream won't have a chance to catch it and forward it to the onError of the outer subscribe. In other words, the completable stream is independent of the login service one.
Usually, you'd want to create one single stream and let the view model subscribe to it. If you have more than one stream, rx has loads of operators to help you chain these. Try and make the repository return one stream from the service. Something like this:
fun login(id) = loginService.login(id)
And now on the view model, you can check if the call was or not successful using the same method - response.isNotSuccessful()

Any design patterns for handling the following case in Java?

I'm new to Java & its design patterns, I have a scenario like this:
Method 1 calls Method 2.
Method 2 looks like the following:
public String createUser(String username, String password) {
someApi.do(config -> {
//code here with respect to someApi.
});
}
now the trick is I need to return the value to caller which is method 1. If there are no exceptions then that is fine. However the code block inside do can throw exception, which will be handled in a separate listener class like this:
public class TestListener implements SomeApiListener {
#Override
public void exception(Throwable cause) {
}
}
Now how should I send back the exception to method 1 from this listener? I'm really confused.
it's not clear what that API do, where the listener is assigned, and what other methods it has, like if there is also onSuccess() ?
what i got from this, is that, you are dealing with async call, which usually do not return a value directly, it deals with a CallBack which in your case is SomeApiListener
So, ... I would make createUser() receives extra arg, SomeApiListener, pass the listener as anonymous inner class (with implementation) when calling the method (from caller).
ex,
public String createUser(String username, String password, SomeApiListener listener) {
someApi.do(config -> {
//code here with respect to someApi.
//somewhere here you are creating a TestListener ?,
//well... don't, and use the one passed from caller (listener)
});
}
Caller part will look like this:
public void method1(){
//..some code ...
createUser(username, password, new SomeApiListener(){
#Override
public void exception(Throwable cause) {
//handle exception...
}
#Override
public void success(Response response) {
//handle response ...
}
});
}
Note: you can still pass TetstListern, if you want, in that case you will have to have a physical class (local class) defined and instantiated, the anonymous-inner-class is somehow a shortcut for that, you don't create a local class, just pass it as an arg.
You can't, at least not in any simple way. I'd expect the documentation for your someApi to demonstrate some common use cases, with exception handling included. If you're combining different ways of programming ("normal" java & functional programming), you can get into tricky situations.
Based on the information you've given, a clumsy solution could look something like this (code obviously not fit for compilation):
public class MyClass implements SomeApiListener {
private Throwable e;
public void exception(Throwable cause) {
e = cause;
}
public void method1() {
createUser("foo", "bar");
if(e != null) {
// Exception was thrown, do something with it
}
}
}
However this is in no way a recommendation. It's clumsy, hacky and bad in every way. A better solution would involve not trying to send the exception back to method1, but instead to modify your code to work in the way that someApi expects.
It depends on your design on how to handle exceptions. Normally, if the method 2 is an utility method then throw the exception back to method 1 and let it handle the exception. Else, if method 2 understands the use case for which it is called then handle the exception there. There are no hard and fast rules, but keep the utility classes clean and send the exception back to the caller so that caller can handle it.

How to use Observable.fromCallable() with a checked Exception?

Observable.fromCallable() is great for converting a single function into an Observable. But how do you handle checked exceptions that might be thrown by the function?
Most of the examples I've seen use lambdas and "just work". But how would you do this without lambdas? For example, see the quote below from this great article:
Observable.fromCallable(() -> downloadFileFromNetwork());
It's a one-liner now! It deals with checked exceptions, no more weird Observable.just() and Observable.error() for such easy thing as deferring code execution!
When I attempt to implement the above Observable without a lambda expression, based on other examples I've seen, and how Android Studio auto-completes, I get the following:
Observable.fromCallable(new Func0<File>() {
#Override
public File call() {
return downloadFileFromNetwork();
}
}
But if downloadFileFromNetwork() throws a checked exception, I have to try-catch it and wrap it in a RuntimeException. There's got to be a better way! How does the above lambda support this?!?!
Rather than using a Func0 with Observable.fromCallable(), use Callable. For example:
Observable.fromCallable(new Callable<File>() {
#Override
public File call() throws Exception {
return downloadFileFromNetwork();
}
}
Since Callable's method call() throws Exception, you don't have to wrap your function in a try-catch! This must be what the lambda is using under the hood.
You could also do this to return checked exceptions:
return Observable.fromCallable(() -> {
sharedPreferences.edit()
.putString(DB_COMPANY, LoganSquare.serialize(
CompanyDBTransformation.get(user.getCompany())
))
.apply();
return user;
}).onErrorResumeNext(
throwable -> Observable.error(new CompanySerializationException(throwable))
);
So here I'm serializing taking the IOException risk, and I'm giving back a more descriptive description.

Handling an exception as a method argument

I am looking for a design pattern to handle Exception instances received as method arguments.
To put some context into the question, I am using GWT and have various asynchronous handlers that usually come in a form similar to:
public interface AsyncCallback<T> {
void onFailure(Throwable caught);
void onSuccess(T result);
}
So, the onFailure method receives a Throwable instance that I need to handle.
Now, I have a number of exceptions I can receive in this method, for example
ConstraintViolationException
TimeoutException
NoSuchElementException
In my handling code I could of course write the following:
void handleException(final Exception e) {
if(e instanceof TimeoutException) {
handleTimeout();
} else if (e instanceof NoSuchElementException) {
handleInvalidElement();
} else {
stopAndCatchFire();
}
}
But to my eye, that looks very ugly. The large if..else if chain combined with heavy usage of instanceof seems like something that should be avoided.
I thought that maybe I could use the try...catch construct to handle the Exception using something like the following:
void handleException(final Exception e) {
try {
throw e;
} catch (TimeoutException te) {
handleTimeout();
} catch (NoSuchElementException nsee) {
handleInvalidElement();
} catch (Exception ex) {
stopAndCatchFire();
}
}
But this seems like an abuse somehow. Do you see any downsides to the second approach or another approach I could go with to avoid the first case?
Could you not have a dictionary of exceptionHandlers keyed by the type of exception they handle, then when you get a exception you look in the dictionary for the handler for the exception type. If there is one, then pass the exception to the handler, if there isn't then use the default handler.
So your handler becomes something like this:
void handleException(final Exception e) {
if (handlers.containsKey(e.getType())
{
handlers[e.getType()].handle(e);
}
else
{
defaultHandler.handle(e);
}
}
My Java is a bit rusty, so the example is c-sharpy but should be simple enough to translate (though I remembered not to capitalise the first letter of everything :))
This approach should have the advantage that you can add new handlers simply.
It will however suffer if you have the same handler for sub types, as you will have to register each subtype explicitly.
To get around this issue simply make each handler responsible for making the decision about whether it can handle an exception:
public interface ExceptionHandler
{
bool canHandle(Exception e);
void handle(Exception e)
}
then just put the handlers in a list an iterate asking each one if it can handle the current exception and when you find one that can, get it to handle it.
But to my eye, that looks very ugly. The large if..else if chain combined with heavy usage of instanceof seems like something that should be avoided.
I don't agree. I think this snippet of code is using both language constructs exactly how they were intended. If the code becomes unmanageable (too many clauses) then you should question the approach to error handling generally, rather than the specifics of this method. At that stage you might want to consider AOP.
The second approach on the other hand is horrible ;)
You can make it more elegant just by handling the if statements inside the exceptions inside the function.
void handleException(Exception e){
handleOne(e)
handleTwo(e)
...
}
It looks prettier. Of course, every function is always called, but its first line is just an if statement. There are variations - e.g. make your handle functions guava function objects, put them in a list, and iterate through them until you get the first one that returns "true". Something like:
public class handlerOne implements Function<Exception, Boolean> {
Boolean apply(Exception input) {
return handlerOne();
}
}
Then your handle function can be something like:
void handleException(Exception e){
list<Function<Exception, Boolean> list = Object.getHandlers(); //store your handlers somewhere
for(Function<Exception, Boolean> f : list){
if(f.apply(e)){
break
}
}
}
That way you insure only one handler which works is called, and you can control the order by changing the order of the list, since the list iterator will return them in order.
Control flow on exceptions should be avoided, and should certainly not be in the onFailure. the onFailure method should be as simple as possible.
Modify whatever code is run asynchronously to handle the exception cases there. The ElementNotFound-exception could be handled by just checking if an element exists prior to doing anything. Timeout-exception could be handled by surrounding the code that can timeout (calling a webservice or something)?) by a try .. catch block.
Then extend the result-type T to contain extra information that a timeout occurred or an element is not found - if needed.

Categories