-
-
Notifications
You must be signed in to change notification settings - Fork 48
Exceptions
Exceptions can be a nasty part of programming but could also be rather handy. Lamp allows you to protect yourself against the bad ones while also leveraging the benefits of good ones, while maintaining upmost flexibility, All done through the following classes:
- CommandExceptionHandler: A bare-boned interface for handling any sort of exceptions thrown during command invocation. This includes built-in ones, ones returned from resolvers, conditions, validators, etc., as well as command errors/exceptions from the command logic itself
- CommandExceptionAdapter: A rich implementation of CommandExceptionHandler that provides direct, overridable methods for each individual exception, with default (and overridable) messages implemented for each one.
- Platform-specific subclasses of
CommandExceptionAdapter
: - SelfHandledException for exceptions that wish to handle themselves
-
CommandExceptionHandlers must be registered with
CommandHandler#setExceptionHandler(CommandExceptionHandler)
.
In most cases, you may not need more than extending your platform-specific exception adapter and overriding methods with more dynamic messages, however you also have the ability to control the full command handling process by implementing the bare-boned CommandExceptionHandler.
One of Java's powerful features is tracking the invocation order of the exception from the direct location and going until native methods. However many times we only need the actual, useful couple of lines of the error and not the whole bunch of trace that comes along with it.
This usually becomes a problem with reflectively calling methods, overloading, and delegating, as this is where the trace begins to get relatively long with little value.
To solve this problem, Lamp includes a default stack trace sanitizer that strips down the usually irrelevant paths of classes and only includes the actual, useful error trace.
We can assess the difference between sanitized trace and un-sanitized ones.
@Command("error")
public void alwaysError() {
System.out.println(1 / 0);
}
Before:
An error occurred while executing the command.
java.lang.ArithmeticException: / by zero
at our.commands.Test.alwaysError(TestCLI.java:21)
at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:627)
at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:649)
at revxrsal.commands.core.reflect.MethodHandlesCallerFactory$1.call(MethodHandlesCallerFactory.java:35)
at revxrsal.commands.core.reflect.MethodCaller.lambda$bindTo$0(MethodCaller.java:29)
at revxrsal.commands.core.BaseCommandDispatcher.execute(BaseCommandDispatcher.java:80)
at revxrsal.commands.core.BaseCommandDispatcher.eval(BaseCommandDispatcher.java:32)
at revxrsal.commands.core.BaseCommandHandler.dispatch(BaseCommandHandler.java:302)
at revxrsal.commands.core.BaseCommandHandler.dispatch(BaseCommandHandler.java:306)
at revxrsal.commands.cli.core.CLIHandler.pollInput(CLIHandler.java:42)
at our.commands.TestCLI.main(TestCLI.java:16)
After:
java.lang.ArithmeticException: / by zero
at our.commands.TestCLI.alwaysError(TestCLI.java:20)
The error is relatively clean and straightforward, and at the same time, does not contain long but unhelpful error paths. However, it could inadvertently strip otherwise important traces if you tend to use MethodHandles in your own command logic or such, and in that case it is possible to disable this feature by using CommandHandler#disableStackTraceSanitizing()
.
👋 If you're having trouble, need support, or just feel like chatting, feel free to hop by our Discord server!