How to handle Exception in Java 8 Stream? - java

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());

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.

Common catch block for two methods with return type?

I have two methods as :
ApiResponse methodA(){
try{
.....
.....
}
catch(Exception e){
handleException(e) // getting error here as return is missing
}
}
There is methodB which does different work but same catch block as above.
private void handleException(Exception e){
if (ex instanceof Exception_A) {
throw new Service_Exception_A();
}
else if (ex instanceof Exception_B) {
throw new Service_Exception_B();
}
else if (ex instanceof Exception_C) {
throw new Service_Exception_C();
}
.......
......
else{
throw ex;
}
Now I am getting the error where handleException() method is called in MethodA and Method B saying that "return statement is missing"
If i copy paste the catch block in each of method, then it works fine,but isnt java intelligent enough to see that the handleException will always throw exception, so no need of return statement in catch block of method A and method B.What am I missing here and how can I get this work?
You should change handleException to be something like:
private <T> T handleException(Exception e){
// ...
}
this way the compiler will check that you only throw exceptions and do not return any values in the body of handleException method, because there is no way to construct a new instance of abstract type T (you can return null, but null is always an explicit escape hatch in Java).
In your methodA and methodB you should return in the catch-block:
ApiResponse methodA(){
try {
...
} catch(Exception e) {
return handleException(e);
}
}

Is it necessary to use throw keyword with Throwables.propagate(e)?

In this code, do I need the throw keyword in order to propagate the exception?
try {
//try something
} catch (Exception e) {
throw Throwables.propagate(e);
}
The Throwables documentation says that this method always throws an exception - is adding the throw superfluous? Could I have written the following instead?
try {
//try something
} catch (Exception e) {
Throwables.propagate(e);
}
The javadoc also states
The RuntimeException return type is only for client code to make Java
type system happy in case a return value is required by the enclosing
method.
and then provides this example
T doSomething() {
try {
return someMethodThatCouldThrowAnything();
} catch (IKnowWhatToDoWithThisException e) {
return handle(e);
} catch (Throwable t) {
throw Throwables.propagate(t);
}
}
In other words, the return type (RuntimeException) is necessary so you can use the method in return or throws statements.
In the above example, if you omitted the throw in the last catch block, then the Java compiler would report an error because it cannot guarantee that a value will be returned from that catch block. A return or throws instead indicate that the method completes at that point, abruptly.

Exception handling with Consumer functions in Java 8

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));
}
}

Factory pattern to create Exceptions dynamically

I have created Exception xml and dynamically create and throw exception.
<exception-mappings>
<exception-mapping key="exceptionkey1">
<class-name>com.package.CheckedException</class-name>
<message>Checked Exception Message</message>
</exception-mapping>
<exception-mapping key="exceptionkey2">
<class-name>com.package.UnCheckedException</class-name>
<message>UnChecked Exception Message</message>
</exception-mapping>
I create object of exception dynamically using reflection depending on the exception key.
public static void throwException(final String key) throws CheckedException, UncheckedException {
ExceptionMapping exceptionMapping = exceptionMappings.getExceptionMappings().get(key);
if (exceptionMapping != null) {
try {
Class exceptionClass = Class.forName(exceptionMapping.getClassName());
try {
throw ()exceptionClass.newInstance(); // line X
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
I want to know which class to typecast at line X so that I do not need to use If/else. Reason behind I do not want to use if else is, it may be possible that in future, there may be new classes added and I do not want to change this code every time new exception is added.
My base logic is my service layer will throw either CheckedException or UncheckedException. If CheckedException is thrown, it will be handled by my web layer. Also I can not throw Super parent class Exception or Throwable as my web layer only catch CheckedException. If UncheckedException is thrown, it will display exception page.
Please help me as I am not able to proceed further.
EDIT: Any other solution is also accepted.
Well, in the name of science, here's how you can do it. Would I recommend doing this? By no means. Would I ever do anything remotely like this myself? Probably not.
public class ExceptionFactory {
public static void throwException(String className)
throws CheckedException, UncheckedException {
Class<?> exceptionClass;
try {
exceptionClass = Class.forName(className);
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException(e);
}
try {
if (CheckedException.class.isAssignableFrom(exceptionClass)) {
throw exceptionClass.asSubclass(CheckedException.class)
.newInstance();
} else if (UncheckedException.class
.isAssignableFrom(exceptionClass)) {
throw exceptionClass.asSubclass(UncheckedException.class)
.newInstance();
} else {
throw new IllegalArgumentException(
"Not a valid exception type: "
+ exceptionClass.getName());
}
} catch (InstantiationException | IllegalAccessException e) {
throw new IllegalStateException(e);
}
}
public static void main(String... args) {
try {
throwException("CheckedException");
} catch (CheckedException e) {
System.out.println(e);
} catch (UncheckedException e) {
System.out.println(e);
}
}
}
class CheckedException extends Exception {
}
class UncheckedException extends Exception {
}
I don't see the point of this factory. Even if you get it to work (which you can by having all the exceptions thrown by it being sub-classes of a single ancestor class), its usage would be something like this :
....
if (somethingInWrong) {
ExceptionFactory.throwException("SomeKey");
}
....
For each key you'd still have to create an exception class to be mapped to it. Lets say SomeKeyException is the exception mapped to "SomeKey".
In that case, it's much more type safe to simply write :
....
if (somethingInWrong) {
throw new SomeKeyException();
}
....
This way the compiler checks that you are creating an exception class that it actually knows. If you use your Factory, you might use some String that is not a valid key, and the compiler won't be able to do anything about it. Only in runtime your Factory will fail to find an exception mapped to the invalid key.
There's no need to use reflection (as I commented above you shouldn't use reflection unless you really have to...).
You can implement the exceptions class to be something like this:
class MyExceptions {
static void myExceptionsThrower(String key) throws Exception {
if("illegalstate".equals(key)) {
throw new IllegalStateException("that's my IllegalStateException bro!");
}
else if("illegalaccess".equals(key)) {
throw new IllegalAccessException("that's my IllegalAccessException bro!");
}
// etc...
}
}
and use it with:
MyExceptions.myExceptionsThrower(key);
A few tweaks:
public static void throwException(final String key) throws Throwable {
ExceptionMapping exceptionMapping =
exceptionMappings.getExceptionMappings().get(key);
if (exceptionMapping != null) {
try {
Class<Throwable> exceptionClass =
(Class<Throwable>)Class.forName(exceptionMapping.getClassName());
try {
throw exceptionClass.cast( exceptionClass.newInstance() ); // line X
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
Here's my entry into this derby. :-)
The other answers have commented on whether this is a reasonable design. I'll set these issues aside for the purpose of this answer.
A couple of my pet peeves are unnecessary warnings (even if suppressed), and exceptions that don't report what actually went wrong. In particular merely printing out a stack trace is usually insufficient. Yes, this is just test code, but when dealing with code like this -- even code that's designed to throw an exception -- one really ought to think about how to deal with errors. In this case I've chosen to represent these kinds of errors as instances of InternalError since the configuration or whatever can be wrong in a variety of ways. Specifically: if the class can't be found, if it is found but isn't a subtype of CheckedException or UncheckedException (or even an ordinary class), or if doesn't have a no-arg constructor or if it's inaccessible.
Another issue with some of the proposed solutions is that if the exception class name is "java.lang.InstantiationException" (or one of the other internally-caught exceptions) an instance of this exception type might be constructed, thrown, and then caught internally, resulting in a stack trace but not actually throwing the requested exception. I've avoided that by linearizing the logic instead of nesting try-catch blocks.
Finally, I extracted the exception-creating code into a separate method so that it can be used for both the checked and unchecked cases. This can be simplified considerably if you rearrange the exception hierarchy to allow only a single root exception (I recommend unchecked) and have exception subtypes that are handled at the web layer or are thrown out to the caller.
static void throwException(final String exClassName) throws CheckedException, UncheckedException {
Class<?> clazz;
try {
clazz = Class.forName(exClassName);
} catch (ClassNotFoundException cnfe) {
throw new InternalError(exClassName, cnfe);
}
if (CheckedException.class.isAssignableFrom(clazz)) {
throw newException(clazz.asSubclass(CheckedException.class));
} else if (UncheckedException.class.isAssignableFrom(clazz)) {
throw newException(clazz.asSubclass(UncheckedException.class));
} else {
throw new InternalError(exClassName + " is not a valid exception");
}
}
static <X extends Throwable> X newException(Class<X> clazz) {
X x;
try {
x = clazz.newInstance();
} catch (InstantiationException|IllegalAccessException e) {
throw new InternalError("creating instance of " + clazz, e);
}
return x;
}
This could be helpful to create a custom precondition exception to avoid multiple if conditions.
Creates a precondition exception while checking for null pointer.
class Preconditions {
/**
* <p>
* Checks the value to be null and if null throws a new Exception with the message given.
* Used to reduce checking if conditions for complexity.
* </p>
* #param val - val to check null
* #param exceptionClass - exception class to be thrown
* #param args - message to be called for throwing exception
* #throws Throwable - Common Throwable Exception.
*/
public static void checkNotNull(final Object val, final Class<?> exceptionClass, final Object ...args) throws Throwable {
Class<?>[] argTypes = new Class<?>[args.length];
Arrays.stream(args).map(WithIndex.indexed()).forEach(arg ->argTypes[arg.index()] = arg.value().getClass());
if (null == val) throw (Throwable) exceptionClass.getConstructor(argTypes).newInstance(args);
}
}
Then you can use it in code with:
PreConditionUtil.checkNotNull(objectToCheck, CustomException.class, ErrorCode, "your error message", ...);

Categories