I need to handle a try catch block in a mvel compiled expression called from Java, something like this
try {
func1()
} catch (Exception e) {
...do something
}
func2()
From my understandings of http://mvel.documentnode.com/ it's not possible. Am I correct?
Any idea to achieve this inside the expression? Sadly I can't split the expression to handle the exception in Java or modify functions.
Thanks
Related
I want to run cleanup code after a certain block of code completes, regardless of exceptions. This is not a closeable resource and I cannot use try-with-resources (or Kotlin's use).
In Java, I could do the following:
try {
// ... Run some code
} catch(Exception ex) {
// ... Handle exception
} finally {
// ... Cleanup code
}
Is the following Kotlin code equivalent?
runCatching {
// ... Run some code
}.also {
// ... Cleanup code
}.onFailure {
// ... Handle exception
}
Edit: added boilerplate exception handling - my concern is with ensuring the cleanup code runs, and maintainability.
There is one important difference, where the code inside runCatching contains an early return. A finally block will be executed even after a return, whereas also has no such magic.
This code, when run, will print nothing:
fun test1()
runCatching {
return
}.also {
println("test1")
}
}
This code, when run, will print "test2":
fun test2() {
try {
return
} finally {
println("test2")
}
}
There is one big difference between both code samples. try...finally propagates exceptions while runCatching().also() catches/consumes them. To make it similar you would have to throw the result at the end:
runCatching {
// ... Run some code
}.also {
// ... Cleanup code
}.getOrThrow()
But still, it is not really 1:1 equivalent. It catches all exceptions just to rethrow them. For this reason, it is probably less performant than simple try...finally.
Also, I think this is less clear for the reader. try...finally is a standard way of dealing with exceptions. By using runCatching() just to immediately rethrow, you actually confuse people reading this code later.
Your question sounded a little like you believed Kotlin does not have try...finally and you need to search for alternatives. If this is the case, then of course Kotlin has try...finally and I think you should use it instead of runCatching().
As per Kotlin's doc for runCatching:
Calls the specified function block and returns its encapsulated result if invocation was successful, catching any Throwable exception that was thrown from the block function execution and encapsulating it as a failure.
Even if finally always runs after a try block and also always runs after a runCatching, they do not serve the same purpose.
finally doesn't receive any argument and cannot operate on the values of the try block, while also receives the Result of the runCatching block.
TLDR; .runCatching{}.also{} is a more advanced try{}finally{}
There is also a difference in what is the result of evaluating the expression.
Consider the following code:
fun main() {
val foo = try {
throw Exception("try")
} catch(e: Exception) {
"catch"
} finally {
"finally"
}
val bar = runCatching{
throw Exception("runCatching")
}.also{
"also"
}.onFailure {
"onFailure"
}
println(foo)
println(bar)
}
The output will be:
catch
Failure(java.lang.Exception: runCatching)
https://pl.kotl.in/a0aByS5l1
EDIT:
An interesting article that points out some differences as well:
https://medium.com/#mattia23r/a-take-on-functional-error-handling-in-kotlin-515b67b4212b
Now let’s give a second look at the implementation of runCatching in the gist above. What does it do? It catches everything.
In this case, it goes even further: it catches all Throwables. For those not knowing, Throwable is everything that can go after a throw keyword; it has two descendants: Exceptions and Errors. We haven’t mentioned Errors so far; Errors usually represent something wrong that happened at a lower level than your business logic, something that can’t usually be recovered with a simple catch.
I'm working on a kotlin web backend and have something like this:
try {
val uuid = UUID.fromString(someString)
} catch (e: IllegalArgumentException) {
throw BadRequestException("invalid UUID")
}
doSomething(uuid)
The code above doesn't compile since uuid is unresolved outside the try block.
Alternatives I can imagine are:
move doSomething(uuid) inside the try block, but I'd rather avoid that so I don't accidentally catch some other potential IllegalArgumentException thrown by doSomething (if that happens for whatever reason I want things to fail and get a 500 in my logs so I can investigate)
use a nullable var instead and initialize it to null but that seems a bit ugly?
This throw BadRequestException pattern is working well otherwise so I don't want to change the return type of the method or something like that in order to avoid throwing.
Is there a better / more elegant / recommended pattern for this in Kotlin?
In Kotlin, try/catch can be used as an expression. Branches that throw don't affect the resolved type. So you can write:
val uuid = try {
UUID.fromString(someString)
} catch (e: IllegalArgumentException) {
throw BadRequestException("invalid UUID")
}
I'm trying to use the inline function use with a FileInputStream instead of the classic try/catch IOException so that
try {
val is = FileInputStream(file)
// file handling...
}
catch (e: IOException) {
e.printStackTrace()
}
becomes
FileInputStream(file).use { fis ->
// do stuff with file
}
My question is, why use the function use if it stills throws exception? Do I have to wrap use in a try/catch? This seems ridiculous.
From Kotlin documentation:
Executes the given block function on this resource and then closes it
down correctly whether an exception is thrown or not.
When you use an object that implements the Closeable interface, you need to call the close() method when you are done with it, so it releases any system resources associated with the object.
You need to be careful and close it even when an exception is thrown. In this kind of situation that is error prone, cause you might not know or forget to handle it properly, it is better to automate this pattern. That's exactly what the use function does.
Your try-catch does not close the resource so you are comparing apples to oranges. If you close the resource in finally block:
val is = FileInputStream(file)
try {
...
}
catch (e: IOException) {
...
}
finally {
is.close()
}
is definitely more verbose than use which handles closing the resource.
I'm using ANTLR3 with the C runtime.
I'd like to do some custom error handling. What I'm really after is that if there is an antlr matching exception of any kind in a sub rule I'd like to tell ANTLR to skip trying to handle it and let it percolate up to a more global rule.
At that rule I'll log it and then try to resume.
I've set the rule catch method like so, so that all rules won't try to recover.
#rulecatch
{
if (HASEXCEPTION())
{
PREPORTERROR();
}
}
This allows me to insert catch handlers on the rules that i want.
At my rule of interest i can then use the catch syntax like so:
catch [ANTLR3_RECOGNITION_EXCEPTION]
{
PREPORTERROR();
RECOGNIZER->consumeUntil(RECOGNIZER,RCURLY);
CONSUME();
PSRSTATE->error = ANTLR3_FALSE;
PSRSTATE->failed = ANTLR3_FALSE;
}
The problem is that this syntax seems to only allow me to catch one type of exception. I'd like to be able to catch all exception types.
Is there a way to do this?
I thought I could overload all the recovery functions but then some code generates exceptions like so:
CONSTRUCTEX();
EXCEPTION->type = ANTLR3_NO_VIABLE_ALT_EXCEPTION;
EXCEPTION->message = (void *)"";
EXCEPTION->decisionNum = 23;
EXCEPTION->state = 0;
goto rulewhenEx;
which means I'll need to catch all possible exceptions.
Any thoughts??
I've ended up trying two solutions for this.
Approach 1)
Overloading the rulecatch setting to set the exception type to one specific type
#rulecatch
{
if (HASEXCEPTION())
{
// This is ugly. We set the exception type to ANTLR3_RECOGNITION_EXCEPTION so we can always
// catch them.
PREPORTERROR();
EXCEPTION->type = ANTLR3_RECOGNITION_EXCEPTION;
}
}
This allows me to use one catch block as all exceptions will be of that type.
Approach 2)
I just use multiple catch blocks and they all dispatch to a common function to handle the error
catch [ANTLR3_RECOGNITION_EXCEPTION]
{
handleException();
}
catch [ANTLR3_MISMATCHED_TOKEN_EXCEPTION]
{
handleException();
}
....
I have the following code
Try
'Some code that causes exception
Catch ex as ExceptionType1
'Handle Section - 1
Catch ex as ExceptionType2
'Handle section - 2
Catch ex as ExceptionType3
'Handle section - 3
Finally
' Clean up
End Try
Suppose ExceptionType1 is thrown by the code which is handled by section - 1. After handling that in section-1, can I have control passed to section-2/section-3? Is that possible?
Change the code to catch all the exceptions in one block and determine the type and execution path from there.
You could call functions in the exception handlers.
Try
'Some code that causes exception'
Catch ex as ExceptionType1
handler_1()
handler_2()
handler_3()
Catch ex as ExceptionType2
handler_2()
handler_3()
Catch ex as ExceptionType3
handler_3()
Finally
handler_4()
End Try
You haven't specified a language, and i don't know the language, so i answer generally.
You can't do that. If you want to have common code, put that either into finally, or if it only needs to be executed for some catching cases, you can copy that code into the respective cases. If the code is bigger and you want to avoid redundancy, you can put it into a function of its own. If that would reduce the readability of your code, you can nest your try/catch blocks (at least in Java and C++. I don't know about your language). Here is an example in Java:
class ThrowingException {
public static void main(String... args) {
try {
try {
throw new RuntimeException();
} catch(RuntimeException e) {
System.out.println("Hi 1, handling RuntimeException..");
throw e;
} finally {
System.out.println("finally 1");
}
} catch(Exception e) {
System.out.println("Hi 2, handling Exception..");
} finally {
System.out.println("finally 2");
}
}
}
This will print out:
Hi 1, handling RuntimeException..
finally 1
Hi 2, handling Exception..
finally 2
put your common code into the outer catch block. Doing it using the nested version also handles cases where an exception occurs without you explicitly re-throwing the old in a catch block. It may fit to what you want even better, but it may also not.
I think you could get the behavior you want if you do nested try blocks. Once an exception is thrown, execution goes to the catch block. If nothing is rethrown, it moves on to finally.