Exception handling with Consumer functions in Java 8 - java

This code gives me a compile error on the line processBatch(batch, this::backupMetacard); The process batch method wraps the consumer in a try/catch block, but Java will not compile the call.
private synchronized void drain() {
for (List<Metacard> batch : Lists.partition(metacards, BATCH_SIZE)) {
getExecutor().submit(() -> {
processBatch(batch, this::backupMetacard);
});
}
metacards.clear();
}
void processBatch(List<Metacard> metacards, Consumer<Metacard> operation) {
List<String> errors = new ArrayList<>();
for (Metacard metacard : metacards) {
try {
operation.accept(metacard);
} catch (IOException e) {
errors.add(metacard.getId());
}
}
if (!errors.isEmpty()) {
LOGGER.info("Plugin processing failed. This is allowable. Skipping to next plugin.",
pluginExceptionWith(errors));
}
}
private void backupMetacard(Metacard metacard) throws IOException {...}

The problem is that in the following snippet, the method backupMetacard declares to throw the checked IOException.
getExecutor().submit(() -> {
processBatch(batch, this::backupMetacard);
^^^^^^^^^^^^^^^^^^^^ // <-- this throws a checked exception
});
As such, it does not comply anymore with the contract of the functional method of Consumer, which is apply and doesn't declare to throw checked exceptions.
Wrap this into a try-catch, where you can throw an unchecked exception instead UncheckedIOException:
getExecutor().submit(() -> {
processBatch(batch, metacard -> {
try {
backupMetacard(metacard);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
});
});

Consumer.accept() does not declare an exception whereas your backupMetacard method does, so you can't pass this::backupMetacard as Consumer parameter.

You can have an adapter functional interface
interface ConsumerX<T>
{
void consumeX(T) throws Exception;
void default consume(T t)
{
try{ consumeX(t); }
catch.... // handle exception
}
}
And use it like
processBatch( batch, (ConsumerX<Metacard>)this::backupMetacard )
The type argument <Metacard> seems redundant, unfortunately it's needed in current Java. We could however have a helper method instead
static <T> ConsumerX<T> of(ConsumerX<T> c){ return c; }
processBatch( batch, ConsumerX.of(this::backupMetacard) )
There are more things to consider. Currently, ConsumerX throws a fixed, overreaching Exception. We would rather have it throw the same exception that the lambda body throws, i.e. exception transparency. This could be done by consumeX() throws a type variable.
Another thing is to provide custom exception handling, e.g.
ConsumerX.of( lambda, ex->{ ... } )
or my preferred syntax --
ConsumerX.of(...).catch_(FooException.class, fe->{ ... });

Below are snippet codes that is basically wrapped try-catch block and being consumed Exception object.
public static <T> T unchecked(final ExceptionBearingAction<T> template, Consumer<Exception> exceptionConsumer) {
T results = null;
try {
results = template.doAction();
} catch (Exception ex) {
exceptionConsumer.accept(ex);
}
return results;
}
ExceptionBearingAction.Java - It's a Functional Interface that perform and Exception bearing action.
#FunctionalInterface
public interface ExceptionBearingAction<T> {
T doAction() throws Exception;
}
How to used it
unchecked(() -> Files.copy(srcPath, Paths.get(distFileUrl), StandardCopyOption.REPLACE_EXISTING), (ex) -> LOGGER.warn("Oops!! copy failed due to {}", ex));

You can do it with apache commons-lang3 library.
https://commons.apache.org/proper/commons-lang/javadocs/api-release/org/apache/commons/lang3/function/Failable.html
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
Change method: processBatch
void processBatch(List<Metacard> metacards, FailableConsumer<Metacard, IOException> operation) {
List<String> errors = new ArrayList<>();
for (Metacard metacard : metacards) {
try {
operation.accept(metacard);
} catch (IOException e) {
errors.add(metacard.getId());
}
}
if (!errors.isEmpty()) {
LOGGER.info("Plugin processing failed. This is allowable. Skipping to next plugin.",
pluginExceptionWith(errors));
}
}

Related

Handling Multiple Generic Exceptions

I am running a multithreaded testing program and would like to add some extra details to exceptions throw for it to be clear which thread is the one that threw the exception. In order to do this I created the following generic function to take any Callable function as a parameter and return it's value; however, in the case it throws an exception, it is caught and extra details are added to the Exception message and then thrown again for the calling function to catch.
public <U> U enhanceThrownException(#NonNull Callable<U> callable) throws Exception {
try {
return callable.call();
} catch (Exception e) {
throw new Exception(controller.getFullScenarioMessage(e.getLocalizedMessage()), e);
}
}
Now this works great for what I needed it for, however, I do not want calling functions to need to catch a generic Exception. I wanted to clearly specify exceptions that I know the function will throw, so I added to the code and have this:
public <U, V extends Exception> U enhanceThrownException(#NonNull Callable<U> callable,
Class<V> exceptionType) throws V {
try {
return callable.call();
} catch (Exception e) {
try {
throw (V) e.getClass().getDeclaredConstructor(String.class, Throwable.class)
.newInstance(controller.getFullScenarioMessage(e.getLocalizedMessage()), e);
} catch (ReflectiveOperationException rException) {
e.printStackTrace();
throw new RuntimeException(controller.getFullScenarioMessage(rException.getLocalizedMessage()), rException);
}
}
}
This works perfectly for a function that has only one throwable exception, but if I want to handle multiple thrown exceptions, how would I go about doing so? Is it necessary to do this, or would using the generic Exception case be enough? Also, if I can specify, is it possible to get the possible thrown exceptions form the function itself without the user needing to input them as parameters? The following does not work because all entered Exceptions would have to be of the same type, which is kind of useless since different Exception derivatives are of different types.
public <U, V extends Exception> U enhanceThrownException(#NonNull Callable<U> callable,
Class<V> exceptionType,
Class<V>... exceptionTypes) throws V {
try {
return callable.call();
} catch (Exception e) {
try {
throw (V) e.getClass().getDeclaredConstructor(String.class, Throwable.class)
.newInstance(controller.getFullScenarioMessage(e.getLocalizedMessage()), e);
} catch (ReflectiveOperationException rException) {
e.printStackTrace();
throw new RuntimeException(controller.getFullScenarioMessage(rException.getLocalizedMessage()), rException);
}
}
}
(Update)
After looking further into this, I realized I may have been overthinking it all. I simply created an custom Exception class:
public class EnhancedException extends Exception {
public EnhancedException(String message, Throwable cause) {
super(message, cause);
}
}
And then I edited the previous code to:
public <U> U enhanceThrownException(#NonNull Callable<U> callable) throws EnhancedException {
try {
return callable.call();
} catch (Exception e) {
throw new EnhancedException(controller.getFullScenarioMessage(e.getLocalizedMessage()), e);
}
}
If needed, the calling functions can check for this custom Exception and then further check if the cause is an Exception it is specifically looking for. This would actually just work with a generic Exception, but maybe there are some uses for having a custom Exception class.
I might have solved my own issue, but if anyone believes there is a better approach or just has some good programming practice advice, I'm all ears.

How to handle Exception in Java 8 Stream?

I have a method where I am traversing through a List and creating List. While doing so, I am calling a method(createResult) to will give a Result also throws CustomException which I am wrapping as ResultClassException. But I keep getting an error saying Unhandled Exception.
My Code :
private List<Result> getResultList(List<String> results) throws ResultClassException {
List<Result> resultList = new ArrayList<>();
results.forEach(
(resultName) -> {
if (!resultRepository.contains(resultName)) {
try {
final Result result = createResult(resultName);
resultList.add(result);
} catch (CustomException e) {
throw new ResultClassException("Error",e);
}
} else {
resultList.add(resultRepository.get(resultName));
log.info("Result {} already exists.", resultName);
}
}
);
return Collections.unmodifiableList(resultList);
}
Can Someone tell what I am doing wrong?
You probably have too many responsibilities in your method. You should think about splitting it into a method that only maps and another one that gathers them.
private List<Result> getResultList(List<String> names) throws ResultClassException {
try {
return names.stream()
.map(this::getOrCreateResult)
.collect(collectingAndThen(toList(), Collections::unmodifiableList));
} catch (RuntimeException e) {
if (e.getCause() instanceof CustomException) {
throw new ResultClassException("Error", e.getCause());
}
throw e;
// Or use Guava's propagate
}
}
private Result getOrCreateResult(String name) {
if (!resultRepository.contains(name)) {
try {
return createResult(name);
} catch (CustomException e) {
throw new RuntimeException(e);
}
} else {
log.info("Result {} already exists.", name);
return resultRepository.get(name);
}
}
I wouldn't suggest using RuntimeException as that would drive you into poor coding practice. Try to handle ResultClassException in the calling method of getResultList(...).
You can't handle a checked exception from inside of Streams
One workaround can be to throw a RuntimeException from createResult or write a method to wrap createResult which will catch and handle the checked exception.
With the lambda expressions in Java 8 you are representing inner classes. So the exception will be thrown inside your anonymous inner class.
try to add that where you are adding your the throw new ResultClassException("Error",e)
Thread.getAllStackTraces()
.keySet()
.stream()
.map(Thread::getStackTrace)
.map(Arrays::asList)
.forEach(list -> System.out.println(list.stream()
.map(i -> i.toString())
.collect(Collectors.joining("\n\t"))));
and see the thread that is calling it. You will see that your exception is out of the scope you expected with the lambdas. You will see that the stream is creating many threads and your exception is not part of the thread you want.
You can wrap your method like that:
Java 8: How do I work with exception throwing methods in streams?
A good way to process gracefully if partially processed stream is acceptable(not wrong):
List.of(1,2,3)
.stream().map( entry-> {
try {
return Optional.of(new Object());
} catch (Exception e) {
log.error("error [{}] while transforming entry [{}]", e.getMessage(), entry, e);
return Optional.empty();
}
}).filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toList());

Junit assert something after awaiting and handling an exception

method which throws at first and second call:
public void foo() throws Exception
test:
#test
public void testFooThrowsAtFirstAndSecondTime(){
boolean thrown;
try {
foo();
} catch (Exception e) {
thrown = true;
}
assertTrue(thrown);
thrown = false;
try {
foo();
} catch (Exception e) {
thrown = true;
}
assertTrue(thrown);
foo();
}
Could you help me find a better solution for this?
Use of Mockito for a better solution would be also acceptable.
With better i mean, if i could avoid try/catch or even multiple try/catch in my test. In other languages or in jAssert i think even in spring there are statements like:
assertThrows(method(..)) //PseudoCode
I thought with Mockito or JUnit 4.x there is a similar thing.
I know about
#Test(expected=Exception)
But this would only be acceptable if i expect one throw and the test ends after that.
I don't think a one-liner per method invocation is possible.
I would write the test like this:
#Test
public void testFooThrowsAtFirstAndSecondTime() throws Exception {
try {
foo();
fail("foo did not throw an exception");
} catch (Exception ex) { }
try{
foo();
fail("foo did not throw an exception");
} catch (Exception ex) { }
foo();
}
The key here is that the try block is crucial if you want to resume execution after an exception. You can factor it out into a method or library, but it has to be called within your test method.
Things that work:
The tried-and-true fail() idiom that you and nrainier cite, which I prefer:
try {
foo();
fail("foo did not throw an exception");
} catch (Exception ex) { }
catch-exception is a library that, like Mockito, wraps the passed object and puts a try block around each method. Mockito's caveats about final methods and classes apply here too, so this won't always work.
List myList = new ArrayList();
catchException(myList).get(1); // myList is wrapped here
assert caughtException() instanceof IndexOutOfBoundsException;
Note that catch-exception is in "maintenance mode" because the Java 8 solution (below) is much more solid.
Any solution like assertThrows(() -> methodThatThrows()) (Java 8) or:
assertThrows(new Runnable() {
#Override public void run() { methodThatThrows(); }
});
...in Java 6/7. Importantly, assertThrows is called before methodThatThrows, so it can invoke methodThatThrows. Thanks Stefan for pointing out Fishbowl, but you could easily write an equivalent yourself:
public void assertThrows(Runnable block) {
try {
block.run();
fail("Block didn't throw.");
} catch (Exception ex) { }
}
Things that don't work:
#Test(expected=YourException.class) will go up the stack to the try block that JUnit wraps your test method in. Control never returns to the test method after that.
JUnit4's ExpectedException #Rule looks tempting, but because it wraps the entire test method, you have to set expectations before calling the method that throws the exception.
Anything that looks like assertThrows(methodCallThatThrows()). Java will try to get the return value out of methodCallThatThrows before assertThrows is ever invoked, so any try block there can't help.
With Java 8 you can use the Fishbowl library.
#Test
public void testFooThrowsAtFirstAndSecondTime(){
Throwable firstException = exceptionThrownBy(() -> foo());
assertEquals(Exception.class, firstException.getClass());
Throwable secondException = exceptionThrownBy(() -> foo());
assertEquals(Exception.class, secondException.getClass());
foo()
}
It is possible to use this library with Java 6 and 7, too. But then you have to use anonymous classes.
#Test
public void testFooThrowsAtFirstAndSecondTime(){
Throwable firstException = exceptionThrownBy(new Statement() {
public void evaluate() throws Throwable {
foo();
}
});
assertEquals(Exception.class, firstException.getClass());
Throwable secondException = exceptionThrownBy(new Statement() {
public void evaluate() throws Throwable {
foo();
}
});
assertEquals(Exception.class, secondException.getClass());
foo()
}
If you are unlucky enough to have to code for some version of java prior to 8, then you cannot do it with one line per exception.
But if you are using java 8, then you can do it as Stefan Birkner suggested.
Now, if you are unwilling to include an entire library for just one method, then here is a method that will work for you, copied from my blog
public final <T extends Throwable> T expectException( Class<T> exceptionClass, Runnable runnable )
{
try
{
runnable.run();
}
catch( Throwable throwable )
{
if( throwable instanceof AssertionError && throwable.getCause() != null )
throwable = throwable.getCause();
assert exceptionClass.isInstance( throwable ) : throwable; //exception of the wrong kind was thrown.
assert throwable.getClass() == exceptionClass : throwable; //exception thrown was a subclass, but not the exact class, expected.
#SuppressWarnings( "unchecked" )
T result = (T)throwable;
return result;
}
assert false; //expected exception was not thrown.
return null; //to keep the compiler happy.
}
So, your test code becomes something like this:
#Test
public void testFooThrowsAtFirstAndSecondTime()
{
expectException( Exception.class, this::foo );
expectException( Exception.class, this::foo );
foo();
}
#Test(expected=Exception.class)

Exception handling using Lambda in Java 8

I'm doing some tests using lambda expressions but my code does not compile. My lambda implementation is wrong or the exception handling? What would be the correct implementation of the following code?
class MyObject { }
interface Creatable<T> {
T create() throws IOException;
}
/* Using the code: */
Creatable<MyObject> creator = () -> {
try {
return new MyObject();
} catch (IOException e) {
e.printStackTrace();
}
};
MyObject obj1 = creator.create();
If i remove the try catch block and declare the exception to throw in the method, the code compiles and runs normally.
Creatable<MyObject> creator = () -> new MyObject();
The compilation error is:
incompatible types: bad return type in lambda expression
Your lambda needs to return a MyObject. If the try block completes successfully that is the case, but if it doesn't the catch block is executed which does not return anything. So you could write:
Creatable<MyObject> creator = () -> {
try {
return new MyObject();
} catch (IOException e) {
e.printStackTrace();
return null;
}
};
But then you will get another compile error: "IOException is never thrown in try block". So you would also need to have a constructor in MyObject that throws an IOException:
class MyObject { MyObject() throws IOException {} }
In the end, unless MyObject actually throws an exception, you can simply use:
Creatable<MyObject> creator = () -> new MyObject();
which you can also write:
Creatable<MyObject> creator = MyObject::new;
Lambda needs all paths to return the value as mentioned in the previous answer the easy solution is to return at the end of the catch block
However there is a more elegant way to handle exception when using lambda
you can wrap a lambda with another
Example
wrap(((x,y)->x/y))
Biconsumer<Integer,Integer> consumer wrap(Biconsumer<Integer,Integer> consumer)
{
return (v,k)->{try
{consumer.apply()}
catch(){};
}
https://www.youtube.com/watch?v=YLKMCPMLv60&list=PLqq-6Pq4lTTa9YGfyhyW2CqdtW9RtY-I3&index=18
#FunctionalInterface
public interface CreateThrowable<T, R, E extends Throwable> {
R create(T t) throws E;
static <T, R, E extends Throwable> Function<T, R> uncheckedException(ThrowingFunction<T, R, E> f) {
return t -> {
try {
return f.create(t);
} catch (Throwable e) {
throw new RuntimeException(e);
}
};
}
}

In Java how can I validate a thrown exception with JUnit?

When writing unit tests for a Java API there may be circumstances where you want to perform more detailed validation of an exception. I.e. more than is offered by the #test annotation offered by JUnit.
For example, consider an class that should catch an exception from some other Interface, wrap that exception and throw the wrapped exception. You may want to verify:
The exact method call that throws the wrapped exception.
That the wrapper exception has the original exception as its cause.
The message of the wrapper exception.
The main point here is that you want to be perf additional validation of an exception in a unit test (not a debate about whether you should verify things like the exception message).
What's a good approach for this?
In JUnit 4 it can be easily done using ExpectedException rule.
Here is example from javadocs:
// These tests all pass.
public static class HasExpectedException {
#Rule
public ExpectedException thrown = ExpectedException.none();
#Test
public void throwsNothing() {
// no exception expected, none thrown: passes.
}
#Test
public void throwsNullPointerException() {
thrown.expect(NullPointerException.class);
throw new NullPointerException();
}
#Test
public void throwsNullPointerExceptionWithMessage() {
thrown.expect(NullPointerException.class);
thrown.expectMessage("happened?");
thrown.expectMessage(startsWith("What"));
throw new NullPointerException("What happened?");
}
}
As provided in your answer, it's a good approach. In addition to this:
You could wrap the function expectException into a new Annotation, called ExpectedException.
An annotated method would look like this:
#Test
#ExpectedException(class=WrapperException.class, message="Exception Message", causeException)
public void testAnExceptionWrappingFunction() {
//whatever you test
}
This way would be more readable, but it's exactly the same approach.
Another reason is: I like Annotations :)
Looking at the proposed answers, you can really feel the pain of not having closures in Java. IMHO, the most readable solution is ye good old try catch.
#Test
public void test() {
...
...
try {
...
fail("No exception caught :(");
}
catch (RuntimeException ex) {
assertEquals(Whatever.class, ex.getCause().getClass());
assertEquals("Message", ex.getMessage());
}
}
For JUNIT 3.x
public void test(){
boolean thrown = false;
try{
mightThrowEx();
} catch ( Surprise expected ){
thrown = true;
assertEquals( "message", expected.getMessage());
}
assertTrue(thrown );
}
Until this post I've done my exception validation by doing this:
try {
myObject.doThings();
fail("Should've thrown SomeException!");
} catch (SomeException e) {
assertEquals("something", e.getSomething());
}
I spent a few moments thinking about the issue though and came up with the following (Java5, JUnit 3.x):
// Functor interface for exception assertion.
public interface AssertionContainer<T extends Throwable> {
void invoke() throws T;
void validate(T throwable);
Class<T> getType();
}
// Actual assertion method.
public <T extends Throwable> void assertThrowsException(AssertionContainer<T> functor) {
try {
functor.invoke();
fail("Should've thrown "+functor.getType()+"!");
} catch (Throwable exc) {
assertSame("Thrown exception was of the wrong type! Expected "+functor.getClass()+", actual "+exc.getType(),
exc.getClass(), functor.getType());
functor.validate((T) exc);
}
}
// Example implementation for servlet I used to actually test this. It was an inner class, actually.
AssertionContainer<ServletException> functor = new AssertionContainer<ServletException>() {
public void invoke() throws ServletException {
servlet.getRequiredParameter(request, "some_param");
}
public void validate(ServletException e) {
assertEquals("Parameter \"some_param\" wasn't found!", e.getMessage());
}
public Class<ServletException> getType() {
return ServletException.class;
}
}
// And this is how it's used.
assertThrowsException(functor);
Looking at these two I can't decide which one I like more. I guess this is one of those issues where achieving a goal (in my case, the assertion method with functor parameter) isn't worth it in the long run since it's just a lot easier to do those 6+ of code to assert the try..catch block.
Then again, maybe my 10 minute result of problem solving at friday evening just isn't the most intelligent way to do this.
#akuhn:
Even without closures we can get a more readable solution (using catch-exception):
import static com.googlecode.catchexception.CatchException.*;
public void test() {
...
...
catchException(nastyBoy).doNastyStuff();
assertTrue(caughtException() instanceof WhateverException);
assertEquals("Message", caughtException().getMessage());
}
The following helper method (adapted from this blog post) does the trick:
/**
* Run a test body expecting an exception of the
* given class and with the given message.
*
* #param test To be executed and is expected to throw the exception.
* #param expectedException The type of the expected exception.
* #param expectedMessage If not null, should be the message of the expected exception.
* #param expectedCause If not null, should be the same as the cause of the received exception.
*/
public static void expectException(
Runnable test,
Class<? extends Throwable> expectedException,
String expectedMessage,
Throwable expectedCause) {
try {
test.run();
}
catch (Exception ex) {
assertSame(expectedException, ex.getClass());
if (expectedMessage != null) {
assertEquals(expectedMessage, ex.getMessage());
}
if (expectedCause != null) {
assertSame(expectedCause, ex.getCause());
}
return;
}
fail("Didn't find expected exception of type " + expectedException.getName());
}
The test code can then invoke this as follows:
TestHelper.expectException(
new Runnable() {
public void run() {
classInstanceBeingTested.methodThatThrows();
}
},
WrapperException.class,
"Exception Message",
causeException
);
i did something very simple
testBla(){
try {
someFailingMethod()
fail(); //method provided by junit
} catch(Exception e) {
//do nothing
}
}
For JUnit 5 it is much easier:
#Test
void testAppleIsSweetAndRed() throws Exception {
IllegalArgumentException ex = assertThrows(
IllegalArgumentException.class,
() -> testClass.appleIsSweetAndRed("orange", "red", "sweet"));
assertEquals("this is the exception message", ex.getMessage());
assertEquals(NullPointerException.class, ex.getCause().getClass());
}
By returning the exception object itself, assertThrows() allows you to test every aspect regarding your thrown exceptions.
I made a helper similar to the other posted ones:
public class ExpectExceptionsExecutor {
private ExpectExceptionsExecutor() {
}
public static void execute(ExpectExceptionsTemplate e) {
Class<? extends Throwable> aClass = e.getExpectedException();
try {
Method method = ExpectExceptionsTemplate.class.getMethod("doInttemplate");
method.invoke(e);
} catch (NoSuchMethodException e1) {
throw new RuntimeException();
} catch (InvocationTargetException e1) {
Throwable throwable = e1.getTargetException();
if (!aClass.isAssignableFrom(throwable.getClass())) {
// assert false
fail("Exception isn't the one expected");
} else {
assertTrue("Exception captured ", true);
return;
}
;
} catch (IllegalAccessException e1) {
throw new RuntimeException();
}
fail("No exception has been thrown");
}
}
And the template the client should implement
public interface ExpectExceptionsTemplate<T extends Throwable> {
/**
* Specify the type of exception that doInttemplate is expected to throw
* #return
*/
Class<T> getExpectedException();
/**
* Execute risky code inside this method
* TODO specify expected exception using an annotation
*/
public void doInttemplate();
}
And the client code would be something like this:
#Test
public void myTest() throws Exception {
ExpectExceptionsExecutor.execute(new ExpectExceptionsTemplate() {
#Override
public Class getExpectedException() {
return IllegalArgumentException.class;
}
#Override
public void doInttemplate() {
riskyMethod.doSomething(null);
}
});
}
It looks really verbose but if you use an IDE with good autocompletion you will only need to write the type of exception and the actual code under test. (the rest will be done by the IDE :D)

Categories