Declarative error handling. Define expected behaviour of API and don't worry about actual implementation. It uses your annotations to generate code that will make sure your interface methods get called when specific error code is returned from API.
Specify interface with methods that you want called for different API error codes.
@AutoHandler // let compiler know it should analyse your class
public interface SimplerErrorListener { // your code has to implement this interface
@ErrorCode("422")
void userError();
@ErrorCode(codes = {"500", "501", "503"}) // expected error codes
void multiple();
}
This will generate implementation calling matching methods when specified error codes are encountered:
@Generated("com.azimolabs.errorhandler")
public class SimplerErrorListenerHandler implements ErrorHandler {
private final ErrorLogger errorLogger;
private final SimplerErrorListener listener;
@Inject
public SimplerErrorListenerHandler(SimplerErrorListener listener, ErrorLogger errorLogger) {
this.listener = listener;
this.errorLogger = errorLogger;
}
public boolean handle(ErrorPayload error) {
Map<String, Object> errors = error.errors();
boolean handled = false;
switch(error.code()) {
case "422": {
listener.userError();
return true;
}
case "500": {
listener.multiple();
return true;
}
case "501": {
listener.multiple();
return true;
}
case "503": {
listener.multiple();
return true;
}
default: {
return false;
}
}
}
}
- payload fields to give meaningful error messages to the user,
{
"error": "422",
"errors": {
"user": "Email already taken"
}
}
- nested fields:
{
"error": "422",
"errors": {
"user": {
"phoneNumber": "Invalid phone number"
}
}
}
- report error to your bug tracking backend with one annotation,
- collapse field messages and pass to UI when form config is dynamic,
- delegated error handler when logic is too complex or awkward to use regular way,
- @AutoHandler - class level annotation to let javac annotation processor know that it should analyse contents of your class.
- @ErrorCode - response field code returned by your backend. Optionally allows you to specify whether error is not expected and should be reported to your crash service.
- @ErrorField - response field name returned by your backend. Supports nesting and reporting to crash services.
- @ErrorLogger - if you want to report errors, you need to provide implementation of this interface.
- @ErrorPayload - as error responses vary, this is the minimal model you need to provide. Your error response should expose
String code()
(used by@ErrorCode
to match errors to methods),String requestId()
(required for crash tracking),String message()
(developer friendly message) andMap<String, Object> errors
that are going to be analysed for error messages for the user.
repositories {
maven { url 'https://dl.bintray.com/azimolabs/maven' }
}
dependencies {
implementation 'com.azimolabs.errorhandler:api:1.4.19'
annotationProcessor 'com.azimolabs.errorhandler:generator:1.4.19'
}
- SimplerErrorListener - basic example, error codes without messages
- FieldsErrorListener - basic example, error codes without messages
- ErrorEnabledView - you can use generic interface, additional, non-annotated methods are also available
- DynamicErrorListener - collapse error messages and pass it to dynamic form, with unspecified number of fields
- DelegatingErrorListener - specify which case requires custom logic
- DelegatedErrorListener - custom handling, write logic for exceptional flow only
We’re working throughout the company to create faster, cheaper, and more available financial services all over the world, and here are some of the techniques that we’re utilizing. There’s still a long way ahead of us, and if you’d like to be part of that journey, check out our careers page.