I'm in the process of updating from picocli 3.9.6 to 4.2.0, and I'm running into an issue when replacing old deprecated calls with the new versions.
In my original version, I had a code block like this:
try {
return commandLine.parseWithHandlers(
new RunLast().useOut(ps),
new ExceptionHandler(),
args);
}
catch(Exception e) {
// handle exceptions
}
The ExceptionHandler handles both parameter and execution exceptions -- both are rethrown, but parameter exceptions get the help text added to the exception text. The catch would get hit in cases where, e.g., a command was given bad args. The catch would ensure the error was printed in the UI.
I attempted to update it like this:
try {
commandLine.setOut(pw);
ExceptionHandler handler = new ExceptionHandler();
commandLine.setExecutionExceptionHandler(handler);
commandLine.setParameterExceptionHandler(handler);
commandLine.execute(args);
return commandLine.getExecutionResult();
}
catch(Exception e) {
// handle exceptions
}
With this new version, exceptions are thrown as before, but they are no longer caught by the catch block after being rethrown by the ExceptionHandler. How can I catch these exceptions?
One of the changes in picocli 4.x is the new execution framework. The user manual has a section on migration that may be useful.
By design, the CommandLine::execute method never throws an exception. So there is no need to surround the call to CommandLine::execute with a try/catch block (unless you need to catch an Error or Throwable).
Instead, you can optionally specify custom exception handlers, like you already do in your example. These exception handlers is where you can show an error message to the users. (Perhaps a combination of what was in the previous ExceptionHandler and the logic that previously was in the catch block.)
The ParameterExceptionHandler is invoked when the user provided invalid input. The default handler shows an error message, may suggest alternative spellings for options or subcommands that look like a typo, and finally displays the usage help message. The Handling Errors section of the user manual has an example ShortErrorMessageHandler that may be useful when the usage help message is so long that it obscures the error message.
The ExecutionExceptionHandler is invoked when the business logic throws an exception. The default handler just rethrows the exception, which results in a stack trace being printed. The Business Logic Exceptions section of the user manual shows an alternative.
It sounds like you need a custom ExecutionExceptionHandler that prints a stack trace followed by the usage help message.
Related
There is a static exception path on class Spark, but it only takes something that extends from Exception. If an error occurs that is a Throwable, but does not extend Exception, there appears to be no way to catch it in the Spark API to log or handle it before a 500 is returned to client.
Example of a common type of Throwable that can't be mapped to Spark.exception: java.lang.ExceptionInInitializerError
Any way to get hold of these in Spark before they disappear out to client, without wrapping the functions of every route in a try/catch(Throwable)?
You can't catch Throwable errors in Spark.
The thing is that Throwable includes Error
Error is programmatically unrecoverable and therefore is usually not to be caught.
On the other hand Exception is programmatically recoverable, and therefore something that you may want to catch.
I recommend you reading
Difference between using Throwable and Exception in a try catch
Why catch Exceptions in Java, when you can catch Throwables?
You should ask yourself why are you trying to catch Throwable's and maybe modify that part (if that code of yours).
I am trying to catch exceptions which will occur during run time in spring hibernate below is hibernate code which inserts data into sql table but i want to catch certain exceptions but i am getting below
error:
Unreachable catch block for JDBCConnectionException.
This exception is never thrown from the try statement body
try
{
TokenBo tokenBo = (TokenBo)appContext.getBean("TokenBo");
Token token = new Token();
token.setFirstName(FirstName);
tokenBo.save(token);
}
catch(JDBCConnectionException e1) {}
Runtime Exception & Error are supposed to happen at run time (reporting that something went wrong when the program ran) and ConstraintViolationException is a runtime exception
The error you are getting is because ConstraintViolationException is never thrown from your code.
Why would you even want to catch ConstraintViolationException? This exception states that you failed to fulfill one of the DB constraints, which means you didn't have proper data check in place
To avoid "chat" mode in commens:
The error message is pretty self-explanatory:
This exception is never thrown from the try statement body
Remove the catch block for the ConstraintViolationException. Don't try to handle Exceptions that can not be thrown by your code.
If you remove this, and running your code causes a JDBCConnectionException, you'll need to tackle this problem, not creating another one to hide it.
If you need help to fix that issue, you'll have to provide more code/configuration/stacktrace/...
Let me first provide some background information. If you don't care you can skip to the next paragraph. I wanted to use the DrEdit sample Java application which is integrated with Google Drive as the basis of my application. I need to refactor the code, though, because the original scenario assumed that the user would only access the application through the Drive and never directly. Currently when the latter happens, a RuntimeException is thrown which should not be the case in a normal flow.
Thanks to that issue I stumbled upon a difference between my local environment and the GAE which is manifested when the following code is run:
} catch (CredentialMediator.NoRefreshTokenException e) {
try {
resp.sendRedirect(e.getAuthorizationUrl());
} catch (IOException ioe) {
throw new RuntimeException("Failed to redirect user for authorization");
}
throw new RuntimeException("No refresh token found. Re-authorizing.");
}
When I run this application on GAE, the RuntimeException is thrown (I can see it in the logs) and the sendRedirect is also executed so I get to see the page that should be displayed.
However when I run the same application locally, I get the HTTP 500 error and the RuntimeException is displayed but the sendRedirect is ignored.
So far I haven't been successful in finding an explanation for this behaviour. I would like to know why this is the case and if there are settings that I can change in order to fully replicate the GAE environment locally.
This is how standard defines the sendRedirect(). It actually commits the response so after calling this method you should not be able to change or add to the response. However it does not define what happens if you trigger an exception after redirect.
Anyway, your code is ambiguous on purpose - you should not continue processing the request and throw exceptions after sending redirect. If you have any processing to do, then do it before redirect.
OTOH you should not rely on generic exception handling. Instead install a servlet filter that catches exceptions and return a proper user-readable or device-readable response.
I have an application that runs headless and needs to be able to notify administrators of problems. I built an email notification framework for it to use, and basically if an exception is thrown and caught, depending on the area in code and the criticality of the exception, it may be passed into the alert notification framework which triggers an email to go out to the listed admins with the stack trace and other debug info.
This works, pretty well.
Before deploying, I was putting it through it's paces. One of my tests is to throw an unhandled exception from a random spot in code - simulating a potentially serious runtime problem where exceptions are being thrown that we did not expect.
For example, here is a method I inserted the test unhandled exception:
/**
* Closes connection.
*/
public void closeConnection() {
if (true)
throw new NullPointerException("Test unexpected exception NPE");
LOG.info("Closing SFTP connection");
getSftpChannel().exit();
getSession().disconnect();
LOG.debug("SFTP Connection closed");
}
The code runs, and when it gets to this unhandled exception, the program hardlocks (because exception is thrown and the sftp connection thread is never closed, so it holds the jvm open until the connection timeout).
I had thought it would crash the JVM, or pass it up to it's caller which eventually would bubble up to the alert system.
In this scenario, I had assumed this NPE would throw out of this exception, isn't handled by it's caller or the caller's caller, etc, so it should bubble to the main() and then crash the JVM since even main does not catch Exception or NPE's.
Question: What is going on here and how can I ensure a scenario like this won't hang in production? Do I just had a huge catch-all catch clause to my main() and have it catch all Exception so that every exception gets handled?
EDIT FOR CLARITY: The question is more-or-less -- Why does an unhandled exception that is not explicitly thrown in a method's signature, nor handled by a caller, not crash the JVM?
To answer your question: Why does an unhandled exception that is not explicitly thrown in a method's signature, nor handled by a caller, not crash the JVM?
Assuming this code is running in a Thread, the reason is, that unless you've set an UnhandledExceptionHandler on either the Thread class or the Thread instance, then the 'main' thread group is the default UnhandledExceptionHandler. By default, the thread group handles unhandled exceptions by logging the stack trace to system.out, the thread 'dies' and the JVM does not crash.
You may want to consider implementing an UnhandledExceptionHandler that uses your email framework to notify you of these failures.
As other posters have suggested, the code should clean up resources like Channels and Session in a finally block.
use a finally block to ensure the connection is closed.
public void closeConnection() {
try {
if (true)
throw new NullPointerException("Test unexpected exception NPE");
} finally {
LOG.info("Closing SFTP connection");
getSftpChannel().exit();
getSession().disconnect();
LOG.debug("SFTP Connection closed");
}
}
Sometimes, you just have to catch Throwable, e.g. when writing a dispatcher queue that dispatches generic items and needs to recover from any errors (said dispatcher logs all caught exceptions, but silently, and then execution is continued on other items).
One best practice I can think of is to always rethrow the exception if it's InterruptedException, because this means someone interrupted my thread and wants to kill it.
Another suggestion (that came from a comment, not an answer) is to always rethrow ThreadDeath
Any other best practices?
Probably the most important one is, never swallow a checked exception. By this I mean don't do this:
try {
...
} catch (IOException e) {
}
unless that's what you intend. Sometimes people swallow checked exceptions because they don't know what to do with them or don't want to (or can't) pollute their interface with "throws Exception" clauses.
If you don't know what to do with it, do this:
try {
...
} catch (IOException e) {
throw new RuntimeException(e);
}
The other one that springs to mind is to make sure you deal with exceptions. Reading a file should look something like this:
FileInputStream in = null;
try {
in = new FileInputStream(new File("..."));;
// do stuff
} catch (IOException e) {
// deal with it appropriately
} finally {
if (in != null) try { in.close(); } catch (IOException e) { /* swallow this one */ }
}
Depends on what you are working on.
if you are developing an API to be used by some one else, its better to re-throw the Exception or wrap it into a custom exception of yours and throw.
Whereas if you are developing an enduser application you need to handle this exception and do the needful.
What about OutOfMemoryError (or perhaps its super class VirtualMachineError)? I can't imagine there is much you can do after something that serious.
If you're writing a dispatcher queue, then by the time the exception comes back to you there's no point in doing anything with it other than logging it. The Swing event queue has basically that type of behavior.
Alternatively, you could provide a hook for an "uncaught exception handler," similar to ThreadGroup. Be aware that the handler could take a long time, and end up delaying your dispatcher.
As far as InterruptedException goes: the only thing that cares about that is your dispatch loop, which should be checking some external state to see if it should stop processing.