The inqwise-errors library provides structured error handling for complex applications. It introduces a set of classes to define error tickets, track error events, manage exceptions, and focus on stack traces in a consistent and maintainable manner. This library is particularly suited for building applications that require detailed error reporting, such as RESTful APIs, microservices, or enterprise software.
- Error Ticket Creation: Use the 
ErrorTicketclass to capture error events, including details such as error codes, status codes, and optional exceptions. - Helper Functions for Error Checks: The 
ErrorTicketshelper class provides static methods for common error handling patterns, such as checking null references or validating conditions. - Exception Normalization: Use 
ExceptionNormalizerto convert exceptions into a standard format for consistent handling. - Bug Tracking: Use the 
Bugclass for representing unexpected issues that should never occur in a stable system. - Stack Trace Focusing: Use 
StackTraceFocuserto filter stack trace elements and highlight the most relevant parts, making debugging easier. 
To use the library, include the following Maven dependency in your pom.xml:
<dependency>
    <groupId>com.inqwise</groupId>
    <artifactId>inqwise-errors</artifactId>
    <version>${latest.version}</version>
</dependency>This section explains the steps to create custom error codes, define a provider for them, and correctly configure the library using SPI (Service Provider Interface). This is useful when you have a module with multiple custom error codes and want to ensure they are grouped and managed correctly.
Define your custom error codes using the ErrorCode interface and group them into a new enum class. For example, in a "Users" module:
package com.example.errors;
import com.inqwise.errors.ErrorCode;
public enum UserErrors implements ErrorCode {
    UserNotExist,           // User does not exist in the system
    FirstNameIsMandatory,   // First name is a required field
    EmailInvalid;           // Email format is incorrect
    public static final String GROUP = "users";  // Define a group identifier
    @Override
    public String group() {
        return GROUP;
    }
}Create a class that implements the ErrorCodeProvider interface, using the valueOf method to retrieve the error code. This example follows the ErrorCodesProvider pattern by using Enums.getIfPresent:
package com.example.errors;
import com.google.common.base.Enums;
import com.inqwise.errors.ErrorCode;
import com.inqwise.errors.spi.ErrorCodeProvider;
public class UserErrorCodeProvider implements ErrorCodeProvider {
    @Override
    public String group() {
        return UserErrors.GROUP;  // Return the group identifier for your custom error codes
    }
    @Override
    public ErrorCode valueOf(String errorCodeName) {
        // Use Enums.getIfPresent to safely retrieve the error code from the enum
        return Enums.getIfPresent(UserErrors.class, errorCodeName).orNull();
    }
}Create a file named com.inqwise.errors.spi.ErrorCodeProvider inside the src/main/resources/META-INF/services/ directory. This file should contain the fully qualified class name of your custom provider:
com.example.errors.UserErrorCodeProvider
Directory Structure Example:
src/
 └── main/
     └── resources/
         └── META-INF/
             └── services/
                 └── com.inqwise.errors.spi.ErrorCodeProvider
Once your custom error codes and provider are defined, you can use them to create error tickets in your application:
import com.inqwise.errors.ErrorTicket;
import com.example.errors.UserErrors;
public class UserService {
    public void checkUserExists(String userId) {
        if (userId == null || userId.isEmpty()) {
            // Create an error ticket for the custom UserNotExist error
            ErrorTicket ticket = ErrorTicket.builder()
                                            .withError(UserErrors.UserNotExist)
                                            .withErrorDetails("User ID cannot be null or empty.")
                                            .build();
            System.err.println("Error: " + ticket.toString());
        }
    }
}To ensure that your custom errors are registered correctly, you can query the ErrorCodeProviders utility and retrieve a specific error code using its string representation:
import com.inqwise.errors.ErrorCodeProviders;
import com.example.errors.UserErrors;
public class Test {
    public static void main(String[] args) {
        var provider = ErrorCodeProviders.get(UserErrors.GROUP);
        System.out.println("Error Code Class: " + provider.valueOf(UserErrors.UserNotExist.toString()).getClass());
    }
}The following sections describe the main classes and functionalities for error handling and management in this library.
The ErrorTicket class is a core component of the library used to encapsulate an error event and is modeled for use with Vert.x. It provides a standardized way to structure error data, making it easier to integrate with Vert.x's JSON and error-handling mechanisms.
Example: Creating an Error Ticket
import com.inqwise.errors.ErrorTicket;
import com.example.errors.UserErrors;
public class ErrorHandlingExample {
    public static void main(String[] args) {
        ErrorTicket ticket = ErrorTicket.builder()
                                        .withError(UserErrors.FirstNameIsMandatory)
                                        .withErrorDetails("First name must be provided during registration.")
                                        .withStatusCode(400)
                                        .build();
        System.out.println("Error Ticket: " + ticket.toString());
    }
}The ErrorTickets class is a utility helper that provides static methods for common error handling scenarios. It includes predefined error tickets for common cases like notFound or general, and validation methods such as checkNotNull and checkArgument.
Example: Using ErrorTickets Helper Methods
import com.inqwise.errors.ErrorTickets;
public class Validator {
    public void validateInput(String input) {
        // Show how to use ErrorTickets validation methods
        ErrorTickets.checkNotNull(input, "Input cannot be null.");
        ErrorTickets.checkArgument(input.length() > 3, "Input length must be greater than 3.");
    }
    public void handleNotFoundScenario() {
        // Example of using predefined error tickets
        throw ErrorTickets.notFound("Requested resource not found.");
    }
}The Bug class is used to represent unexpected conditions that should never happen in a properly functioning application.
Example: Using the Bug Class
import com.inqwise.errors.Bug;
public class SystemValidator {
    public void validateSystemState() {
        boolean unexpectedCondition = true;
        if (unexpectedCondition) {
            throw new Bug("An unexpected condition occurred: {}", "Invalid system state");
        }
    }
}The StackTraceFocuser class provides a way to filter and highlight relevant stack trace elements from exceptions. This is particularly useful when debugging complex issues, as it helps pinpoint the most important parts of a stack trace.
Example: Custom Stack Trace Filtering
import com.inqwise.errors.StackTraceFocuser;
import java.util.regex.Pattern;
import java.util.List;
public class CustomStackTraceFocusing {
    public static void main(String[] args) {
        try {
            throw new RuntimeException("Simulated custom exception");
        } catch (Exception e) {
            // Create a custom StackTraceFocuser to ignore specific package patterns
            List<Pattern> ignorePatterns = List.of(
                Pattern.compile("^java\\."),           // Ignore standard Java classes
                Pattern.compile("^javax\\."),          // Ignore Javax classes
                Pattern.compile("^sun\\."),           // Ignore Sun implementation classes
                Pattern.compile("^com\\.thirdparty\\."), // Ignore third-party library classes
                Pattern.compile("^jdk\\."),           // Ignore JDK internal classes
                Pattern.compile("^org\\.junit\\.")     // Ignore test framework classes
            );
            
            StackTraceFocuser<Throwable> focuser = StackTraceFocuser.ignoreClassNames(ignorePatterns);
            Throwable focusedException = focuser.apply(e);
            focusedException.printStackTrace();
        }
    }
}This library is licensed under the MIT License. See the LICENSE file for more details.