Why finally block exists? - try-catch-finally

In most programming languages, there is a finally block that can be placed after try or catch block like this :
try {
sensitiveFunction();
} catch (Exception e) {
executedWhenFailed();
} finally {
alwaysExecuted();
}
But we can execute the same code without finally block like that :
try {
sensitiveFunction();
} catch (Exception e) {
executedWhenFailed();
}
alwaysExecuted();
So, why does finally block exist? Anyone have an example that finally block is required ?
Thanks

Even these examples aren't equivalent: if sensitiveFunction() throws something which doesn't extend Exception but Error instead, alwaysExecuted won't be executed without finally (please don't try to "fix" this by catching Throwable).
Or say executedWhenFailed() itself throws an exception: it's quite common to rethrow an exception from a catch block after adding some information. Again, alwaysExecuted() won't be executed in the second snippet.
Or suppose you have return sensitiveFunction(); instead of just a call. Etc. etc.

finally exists so that code can always be run, without regard to if you caught the exception or not.
Sometimes you want to just use try and finally together:
allocate()
try:
do_something_with_allocated()
finally:
deallocate()
In the above example, it lets you 100% confidently clean up a resource that was opened above without regard for any exceptions that may be propagating up.

If you throw a new exception in your catch block, you will eventually (after that exception has been handled) end up in your finally block. But not in the line after your catch.
Just throw an exception in executedWhenFailed, in your first example alwaysExecuted will be executed, in the second it wil not.

The finally block is executed even if there is a return statement in the catch() block.
(Example in JavaScript)
function foo() {
try {
throw "first"
} catch(err){
console.log(err)
return "third"
} finally {
console.log("second") // Called before return in catch block
}
return "Never reached"
}
console.log(foo())

Related

Break a for loop AND also throw an exception when a specific condition is happening

So I'm looping over a list of accounts and I wanna break the whole "for loop" for all the accounts in the list, and also at the same time to throw an exception as a certain condition is happening:
accounts.forEach(account -> {
try {
if (isSomethingHappens()) {
String errorMsg = "bla bla, you can't do that cuz condition is happening";
printError(errorMsg);
throw new Exception(errorMsg); // AND I also, in addition to the exception, I wanna break the whole loop here
}
doA();
doB();
} catch (Exception e) {
printError(e);
}
}
Does somebody have any elegant way to do that?
Maybe wrapping it with an exception of my own and on this certain case to catch only it?
Is there a good and known practice for my demand?
I appreciate any help, and tnx a lot!
First thing is - in forEach you don't have break functionality like traditional for loop. so if you need to break for loop use traditional for loop
In Java lambda expression can only throw run-time exception
so one thing you can do this is create CustomeRuntimeException and wrap forEach loop in try catch block
try {
accounts.forEach(account -> {
if (isSomethingHappens()) {
throw new CustomeRuntimeException("bla bla, you can't do that cuz condition is happening");
}
}
} catch (CustomeRuntimeException e) {
printError(e);
}
doA();
doB();
}
by dooing this if isSomethingHappens return ture than CustomeRuntimeException will throw and it will catched by catch block and doA() & doB() method will execute after catch
One good way to do this is to re-raise the error in your inner catch block. This will hand control to the next-outer try/catch. So, put another try/catch block outside of your foreach construct.
The exception occurs and is caught by the innermost try.
The printError() stuff is done.
The exception is re-raised, which kills the forEach.
The try that surrounds the forEach catches the re-raised exception.

ParallelFlux doOnNext how to handle Exception

In my project I have this:
ParallelFlux<Device> flux = Flux.fromIterable(children)
.delayElements(Duration.ofMillis(10))
.parallel(18)
.runOn(Schedulers.elastic(), 10)
.doOnNext(c -> recursiveValidationThroughoutChildren(c, tracker)
});
Where recursiveValidationThroughoutChildren is a method with this declaration:
boolean recursiveValidationThroughoutChildren(Device d, NodeChangesTracker tracker) throws Exception;
What I don't understand is how to handle the exception thrown by this last method. I would like the exception to be propagated outside the ParallelFlux.
Is it possible? What is the correct way to handle it?
I followed the link #Rozart suggested, but I could not apply the solution as it is explained. I had to change it a bit:
ParallelFlux<Device> flux = Flux.fromIterable(children)
.delayElements(Duration.ofMillis(10))
.parallel(18)
.runOn(Schedulers.elastic(), 10)
.doOnNext(child -> {
try {
recursiveValidationThroughoutChildren(child, tracker);
} catch (Exception ex) {
Flux.error(ex);
}
});
The change is needed because the ParallelFlux does not support the "handle" method, so I had to add a try catch and relaunch the exception with a Flux.error.
I don't know if it is good practice, but it is the only way I got it work.

How can i catch Container exceptions?

I want to be able to catch container binding exceptions but it doesn't seem to work.
If i have this code:
try {
$instance = app()->make('SomeNonExistingBinding');
} catch (Exception $e) {
// handle failure
}
But somehow the thrown Exception is being caught in the Illuminate\Routing\Pipeline::prepareDestination() method that AFAIK converts the exceptions in HTTP responses, instead of my try-catch block.
Can someone help me on this, please?
Thanks in advance.

Inside a try block should only be the instructions that could throw the exception or can put some code not relevant for the exception?

If i know that only one function (take in the example) will throw the exception, what could be the correct way, of the following options?
All in the try block:
try
{
while (someCondition)
{
take();
anotherFunction();
}
}
catch(Exceotion e)
{
//some instructions
}
Inside the block only the function that throw the exception:
while (someCondition)
{
try
{
take();
}
catch....
{
//some instructions
}
anotherFunction();
}
I would use the first way because it's clearer, but there is an explicit rule about this?
Thanks!
The two ways do very different things and depending on what you need the code to do, either can be correct.
In the first example, anotherFunction is not called if there was an exception.
In the second example, the exception is being dealt with in the catch block, and anotherFunction will be executed afterwards.
Along the same lines, in the first example, an exception aborts the whole while loop, whereas in the second example it aborts only a single iteration and continues the loop with the next iteration.

About Spring Transaction Manager

Currently i am using spring declarative transaction manager in my application. During DB operations if any constraint violated i want to check the error code against the database. i mean i want to run one select query after the exception happened. So i am catching the DataIntegrityViolationException inside my Catch block and then i am trying to execute one more error code query. But that query is not get executed . I am assuming since i am using the transaction manager if any exception happened the next query is not getting executed. Is that right?. i want to execute that error code query before i am returning the results to the client. Any way to do this?
#Override
#Transactional
public LineOfBusinessResponse create(
CreateLineOfBusiness createLineOfBusiness)
throws GenericUpcException {
logger.info("Start of createLineOfBusinessEntity()");
LineOfBusinessEntity lineOfBusinessEntity =
setLineOfBusinessEntityProperties(createLineOfBusiness);
try {
lineOfBusinessDao.create(lineOfBusinessEntity);
return setUpcLineOfBusinessResponseProperties(lineOfBusinessEntity);
}
// Some db constraints is failed
catch (DataIntegrityViolationException dav) {
String errorMessage =
errorCodesBd.findErrorCodeByErrorMessage(dav.getMessage());
throw new GenericUpcException(errorMessage);
}
// General Exceptions handling
catch (Exception exc) {
logger.debug("<<<<Coming inside General >>>>");
System.out.print("<<<<Coming inside General >>>>");
throw new GenericUpcException(exc.getMessage());
}
}
public String findErrorCodeByErrorMessage(String errorMessage)throws GenericUpcException {
try{
int first=errorMessage.indexOf("[",errorMessage.indexOf("constraint"));
int last=errorMessage.indexOf("]",first);
String errorCode=errorMessage.substring(first+1, last);
//return errorCodesDao.find(errorCode);
return errorCode;
}
catch(Exception e)
{
throw new GenericUpcException(e.getMessage());
}
}
Please help me.
I don't think problem you're describing has anything to do with Transaction management. If DataIntegrityViolationException happens within your try() block you code within catch() should execute. Perhaps exception different from DataIntegrityViolationException happens or your findErrorCodeByErrorMessage() throwing another exception. In general, Transaction logic would be applied only once you return from your method call, until then you could do whatever you like using normal Java language constructs. I suggest you put breakpoint in your error error handler or some debug statements to see what's actually happening.

Resources