CompletableFuture exception behavior with join() then get() - java

My intuition is that the following code is wrong. I believe because join() is being used, any exceptions throw while completing the futures will be unchecked. Then when get() is called, there will be no checked exceptions, no logging of any errors, and difficulty diagnosing errors during failure.
List<CompletableFuture> list = ImmutableList.of(future1, future2);
CompletableFuture.allOf(list.toArray(new CompletableFuture[list.size()])).join();
try {
result1 = future1.get();
result2 = future2.get();
} catch (InterruptedException | ExecutionException e) {
// will this ever run if join() is already called?
}
I have looked through the documentation for CompletableFuture but haven't found the exact answer to my question. I am asking here and will then go read through the source code.
The only why I can see that the catch block code would run is if somehow checked exceptions can be saved in some execution context and not thrown in join() (or thrown wrapped by an unchecked exception), and then throw again in some form after get(). This seems unlikely to me.
So my ultimate question is, will the catch block code ever run?

Both the join and the get method are blocking method that relies on completion signals and returns the result T. Processing the piece of code as in question :-
On one hand, InterruptedException could be thrown while the thread is interrupted in the process of waiting as we do a get, the wait here is already completed by the join method.
Also, as stated in the join method documentation
/**
* ... if a
* computation involved in the completion of this
* CompletableFuture threw an exception, this method throws an
* (unchecked) {#link CompletionException} with the underlying
* exception as its cause.
*/
So, on the other hand, the ExecutionException for futureN.get() in your case could only be thrown when and if the future completed exceptionally. Since the future if executed exceptionally would end up in throwing a CompletionException for the join call, it wouldn't reach the catch block ever or for that sake try block either.

Yes, the code would never be reached, but that doesn't make the "code wrong".
First, let's just try it out...
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
throw new IllegalArgumentException();
});
try
{
CompletableFuture.allOf(future1).join();
}
catch (Exception e1)
{
System.out.println("I'd exit here."); // *1
}
try
{
future1.get();
}
catch (InterruptedException | ExecutionException e)
{
System.out.println("Entered!");
}
Since you didn't do the try/catch "*1", the Exception would cause the method to exit and the get() would never be reached; so the second catch clause would never be executed.
However, the catch is still necessary because it's for the compiler, which has no way of knowing the previous call sequence.
The more straightforward way of doing this would be like this anyway:
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
throw new IllegalArgumentException();
});
try
{
CompletableFuture.allOf(future1).join();
future1.get();
}
catch (CompletionException e1) // this is unchecked, of course
{
System.out.println("Exception when joining");
}
catch (InterruptedException | ExecutionException e)
{
System.out.println("Exception when getting");
}

Related

Execute parallel method calls in java without aborting entire processing for any exception in a one or multiple method calls

I've a method
private void disableXYZ(Long rId, List<Long> disableIds, String requestedBy) {
for (Long disableId : disableIds) {
try {
disablePackXYZ(UnSubscribeRequest.unsubscriptionRequest()
.requestedBy(requestedBy)
.cancellationReason("system")
.id(disableId)
.build());
} catch (Exception e) {
log.error("Failed to disable pack. id: {}, rId: {}. Error: {}", disableId, rId, e.getMessage());
}
}
}
I want to make parallel method calls to disablePackXYZ with ids in disableIds list instead of an iterative for loop. But doing so I don't want to abort all the parallel calls if exception is thrown by any one or more disablePackXYZ calls. I can catch or suppress the exception but it should not abort processing of all the other threads or of the same thread for further tasks. Please suggest the approach for the same.
I went through java streams approach over the web -
final CompletableFuture<ParseException> thrownException = new CompletableFuture<>();
Stream.of(columns).parallel().forEach(column -> {
try {
result[column.index] = parseColumn(valueCache[column.index], column.type);
} catch (ParseException e) {
thrownException.complete(e);
}});
For above approach, I found over web that if there is at least one exception thrown in a thread, the forEach invocation will propagate it (or one of them) to the caller. Hence, the current implementation doesn’t wait for the completion of all threads when it encounters an exception.
You've got a result[] array for storing results, just create an error[] array for storing exceptions. In your catch statement, store the exception into the error[] array and don't call thrownException.complete(e).

Is it right for a thread to throw an InterruptedException for itself?

This is what I'm doing:
Stopwatch stopWatchToCheckTimeout;
void checkShutDown() throws InterruptedException {
if (stopWatchToCheckTimeout.elapsed() >= MAX_GRACEFUL_TIMEOUT_DURATION) {
throw new InterruptedException("Time to shut down now!");
}
}
public Void mainFancyMethod() {
try {
while(true) {
checkShutDown();
// do fancy work
}
} catch (InterruptedException ex) {
log.debug("Shutting down gracefully");
}
return null;
}
From the java/lang/InterruptedException documentation its not clear to me if by standards it should be another thread that should interrupt or if its okay for a thread to throw this exception for itself?
Whats the best exception to throw for this use-case?
It seems like you are using exceptions in place of control flow. Is there any reason you couldn't just have checkShutDown return a boolean?
boolean timedOut() {
return (stopWatchToCheckTimeout.elapsed() >= MAX_GRACEFUL_TIMEOUT_DURATION)
}
It is correct for a thread to throw an interrupted exception, and in fact threads are usually the sources of InterruptedException.
In your case, I don't think it's appropriate because it has nothing to do with interruption, which is an established thread state. You just want to exit the execution, which could be done in more graceful and performant ways.
TimeLimitExceededException: https://docs.oracle.com/javase/7/docs/api/javax/naming/TimeLimitExceededException.html
From the Docs: "This exception is thrown when a method does not terminate within the specified time limit. This can happen, for example, if the user specifies that the method should take no longer than 10 seconds, and the method fails to complete with 10 seconds. "
This sounds like just what you are after, or?
In the example you posted, you should not throw an InterruptedException.
The Javadoc for InterruptedException states: Thrown when a thread is waiting, sleeping, or otherwise occupied, and the thread is interrupted, either before or during the activity. Being interrupted is a result of Thread.interrupt() being called on your running thread, which is not what's happening in the code you posted.
If you do still want to use an exception to break out of your loop, you should use some other exception type. However, an alternative would be to make your check method return true/false, and use that for the condition of your while loop. So instead of this:
try {
while(true) {
checkShutDown();
// do fancy work
}
} catch (InterruptedException ex) {
log.debug("Shutting down gracefully");
}
do something like this:
while (checkIfSafeToContinue()) {
// do fancy work
}

Exception hierarchy/try-multi-catch

try {
throw new FileNotFoundException();
} catch (IOException e) {
e.printStackTrace();
}
catch (Exception e) {
e.printStackTrace();
}
Can someone tell me why the second catch block is not considered as unreachable code by the compiler? But in the following case:
try {
throw new FileNotFoundException();
} catch (Exception e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
The second catch block is considered unreachable?
After all, FileNotFoundException comes under IOException, just as it comes under Exception.
Edit Please clarify:
The compiler will know an exception is thrown by a method based on the method's throws clause. But it may not necessarily know the specific type of exception (under that class of exception). So if a method throws exception 'A', compiler won't know if the actual exception is 'A' or a subtype of 'A' because this is only determined at runtime. The compiler however will know that an exception of type 'X' is never thrown, so giving a catch block for X is erroneous. Is this right?
The compiler cannot assume that the only possible exception thrown from your try block will be a FileNotFoundException. That's why it doesn't consider the 2nd catch block to be unreachable in your first code sample.
What if, for some unknown reason, a RuntimeException gets thrown while creating the FileNotFoundException instance (entirely possible)? What then?
In your first code sample, that unexpected runtime exception would get caught by the 2nd catch block, while the 1st block would take care of the FileNotFoundException if it gets thrown.
However, in your 2nd code sample, any and all exceptions would get caught by the 1st catch block, making the 2nd block unreachable.
EDIT:
To better understand why the catch(Exception e) block in your first code is not considered unreachable by the compiler, try the following code, and notice how the the 2nd catch is definitely reachable:
public class CustomIOException extends IOException {
public CustomIOException(boolean fail) {
if (fail) {
throw new RuntimeException("the compiler will never know about me");
}
}
}
public static void main(String[] args) {
try {
throw new CustomIOException(true);
} catch(IOException e) {
System.out.println("Caught some IO exception: " + e.getMessage());
} catch(Exception e) {
System.out.println("Caught other exception: " + e.getMessage());
}
}
Output:
Caught other exception: the compiler will never know about me
TL;DR
The compiler considers that FileNotFoundException() may not be the only Exception thrown.
Explaination
JLS§11.2.3 Exception Checking
A Java compiler is encouraged to issue a warning if a catch clause can
catch (§11.2) checked exception class E1 and the try block
corresponding to the catch clause can throw checked exception class
E2, a subclass of E1, and a preceding catch clause of the immediately
enclosing try statement can catch checked exception class E3 where E2
<: E3 <: E1.
That means that if the compiler considers that the only exception possibly thrown by your catch block is a FileNotFoundException(), it will warn you about your second catch block. Which is not the case here.
However, the following code
try{
throw new FileNotFoundException();
} catch (FileNotFoundException e){
e.printStackTrace();
} catch (IOException e){ // The compiler warns that all the Exceptions possibly
// catched by IOException are already catched even though
// an IOException is not necessarily a FNFException
e.printStackTrace();
} catch (Exception e){
e.printStackTrace();
}
This happens because the compiler evaluates the try block to determine which exceptions has the possibility to be thrown.
As the compiler does not warn us on Èxception e, it considers that other exceptions may be thrown (e.g RunTimeException). Since it is not the compiler's work to handle those RunTimeExceptions, it lets it slip.
Rest of the answer is intersting to read to understand the mechanism behind exception-catching.
Schema
As you may see, Exception is high in the hierarchy so it has to be declared last after IOException that is lower in the hierarchy.
Example
Imagine having an IOException thrown. As it is inherited from Exception, we can say IOException IS-A Exception and so, it will always be catched within the Exception block and the IOException block will be unreachable.
Real Life Example
Let's say, you're at a store and have to choose pants. The seller tells you that you have to try the pants from the largest ones to the smallest ones and if you find one that you can wear (even if it is not your size) you must take it.
You'll find yourself buying pants too large for your size and you'll not have the chance to find the pants that fits you.
You go to another store : there, you have the exact opposite happening. You can choose your pants from smallest to largest and if you find one you can wear, you must take it.
You'll find yourself buying pants at your exact size.
That's a little analogy, a bit odd but it speaks for itself.
Since Java 7 : multi-catch
Since Java 7, you have the option to include all the types of Exceptions possibly thrown by your try block inside one and only catch block.
WARNING : You also have to respect the hierarchy, but this time, from left to right.
In your case, it would be
try{
//doStuff
}catch(IOException | Exception e){
e.printStackTrace();
}
The following example, which is valid in Java SE 7 and later,
eliminates the duplicated code:
catch (IOException|SQLException ex) {
logger.log(ex);
throw ex;
}
The catch clause specifies the types of exceptions that the block can
handle, and each exception type is separated with a vertical bar (|).
First case:
catch (IOException e) { // A specific Exception
e.printStackTrace();
}
catch (Exception e) { // If there's any other exception, move here
e.printStackTrace();
}
As you can see, first IOException is catched. This means we are aiming at just one specific exception. Then in second catch, we aim for any other Exceptions other than IOException. Hence its logical.
In second:
catch (Exception e) { // Move here no matter whatever exception
e.printStackTrace();
}
catch (IOException e) { // The block above already handles *Every exception, hence this won't be reached.
e.printStackTrace();
}
We catched any exception (whether its IOException or some other Exception), right in the first block. Hence second block will not be reached because everything is already included in first block.
In other words, in first case, we aim at some specific exception, than at any other exceptions. While in second case, we first aim at all/any Exception, than at a specific exception. And since we already dealt will all exceptions, having a specific exception later won't make any logical sense.

Unhandled Java exception execute remainder of method?

I was responding to a slough of basic Java practice test questions and the correct answer to the following question slipped past me while taking the test.
Question: "If an exception is not caught, the finally block will run and the rest of the method is skipped - TRUE or FALSE?"
I am attempting to prove out the answer with the ThrowTest class (pasted at bottom) but I find Java exception handling to be somewhat unfamiliar. I compile the class as is with the ArrayIndexOutOfBoundsException portion of the catch block commented out. I then execute the class without passing an input parm thus creating an exception (the ArrayIndexOutOfBoundsException exception) . I would expect the final System.out.println would not execute and indeed it does not.
I find if I un-comment the ArrayIndexOutOfBoundsException catch block and recompile, the class then catches that specific error at run time and executes the "Rest of method" println at bottom. So, does my code prove the rest of "the rest of the method is skipped" or do I have to test it from a method other than the main method? Maybe there is a more straightforward method of testing it.
public class ThrowTest
{
public static void main(String[] args)
{
try
{
String anyString = args[0];
System.out.println("Try code executes");
}
catch(SecurityException e) //any old exception
{
System.err.println ("Error: SecurityException. ");
e.printStackTrace();
}
/* begin comment
catch(ArrayIndexOutOfBoundsException e)
{
System.err.println("Error: Caught ArrayIndexOutOfBoundsException. ");
e.printStackTrace();
}
end comment */
finally
{
System.out.println("finally block executes!");
}
System.out.println("Rest of method executes!");
}
}
Regardless of what exception is thrown a finally block will always execute (barring any strange situations like out of memory), so given the following
try {
// do some code
}
catch (SomeException e) {
// exception handling
}
finally {
doFinallyStuff();
}
doOtherStuff();
doFinallyStuff will always execute here. But doOtherStuff will only execute under the following conditions:
No exceptions are thrown
SomeException is thrown and the catch block does not rethrow the exception up the chain
If another exception is thrown in the try block that is not handled by the catch block, doFinallyStuff will still execute, but doOtherStuff will not
Your code is indeed proving that everything works as you described. When you catch an exception, then the rest of the method thereafter executes. If you let the method throw the exception, its execution halts immediately. Either way, the finally block will always execute.

why is it not possible to insert code between try and catch block?

i was asked a question in interview what happens if we put finally block between try and catch block i answered in that case compiler will think that there is no catch block and it will directly execute finally block.
Then he asked why is it not possible to put code between try and catch block?
Can you please help me...
Okay, first thing first - the compiler doesn't execute the code, it just compiles it, allowing it to be run by the JVM.
Empirically speaking, that wouldn't make too much sense, since if you have some code that you would want to put outside the try block but before the catch block, the code could just as well be placed in the try block. The thing is, it would just behave as it were in the try block anyway if you think about it.
Let's assume this is valid Java (this doesn't compile):
try {
throw new Exception();
}
System.out.println("Sup!");
catch(Exception e) { }
When the exception gets thrown, that line that prints out Sup! will still get skipped as the JVM is searching to jump to the appropriate exception handler to treat Exception. So, in a way, the code behaves just as it would if it were in the try {} block itself, which is why it wouldn't really matter where it is, and the Java specifies that this (now proven useless) construct is illegal.
Now what if that code after the try were to throw another exception itself? If it were valid code, it would behave just like a nested try...catch block in the original try block. Of course that once things start getting complicated, the approach where there is no clear connection between a try and a catch block could get fuzzy, and the JVM would end up not knowing which catch/finally belongs to which try block (especially since the handler doesn't have to be in the same function, or even in the same package!).
Well, the flippant answer is that the language spec forbids it.
But let's step back a bit and think about it a different way - what if you could do this?
try {
foo();
}
bar();
catch (Exception e) {
baz();
}
What could the semantics of this be? If we catch an exception in foo(), is baz() called? What about bar()? If bar() throws, do we catch the exception in that case?
If exceptions in bar() are not caught, and exception in foo() prevent bar() from running, then the construct is equivalent to:
try {
foo();
} catch (Exception e) {
baz();
}
bar();
If exceptions in bar() are caught, and exception in foo() prevent bar() from running, then the construct is equivalent to:
try {
foo();
bar();
} catch (Exception e) {
baz();
}
If exceptions in bar() are not caught, and exception in foo() do not prevent bar() from running (bar() is always executed), then the construct is equivalent to:
try {
foo();
} catch (Exception e) {
baz();
} finally {
bar();
}
As you can see, any reasonable semantics for this between-try-catch construct are already expressible without the need for a new - and rather confusing - construct. It's hard to devise a meaning for this construct that is not already redundant.
As an aside, one potential reason we can't do:
try {
foo();
} finally {
bar();
} catch (Exception e) {
baz();
}
could be that it does not reflect actual execution order - catch blocks run before the finally block. This allows catch blocks to make use of resources that the finally block might release later (for example, to request additional diagnostic information from a RPC object or something). Could be made to work the other way as well? Sure. Is it worth it? Probably not.
Well it would mean something like this :
try
{
somCode();
}
someMoreCode();
catch
{
}
What should this mean ?
This is not possible because it has no semantic, and therefore it has been decided to be syntaxically incorrect by language designers!
If you have a try you must have either catch or finally, as defined in the java language specification, 14.20 "The try Statement`
try and catch like .. if and else ..
so there is no need to add code between try and catch block

Categories