Skip to content

About

Lightweight Spring Boot library for standardized RFC 9457 API error responses.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

15 Commits

Folders and files

Repository files navigation

ApiErrorKit

A lightweight Spring Boot library for converting custom exceptions into standardized RFC 9457 API error responses.

Java Spring Boot RFC Tests Maven Central

ApiErrorKit provides a simple and extensible way to transform application exceptions into consistent RFC 9457 ProblemDetail responses.

Instead of creating a separate @ExceptionHandler for every custom exception, developers can annotate their exceptions with @ApiError and let ApiErrorKit handle the response mapping automatically.


Why ApiErrorKit?

This project was inspired by a problem I observed during my experience as a Technical Mentor, while coordinating and supporting a team of around 30–40 developers.

When many developers work on the same backend, API error-handling practices can easily become inconsistent. Different developers may return different error formats, status codes, messages, or exception-handling approaches.

Over time, this inconsistency can make debugging more difficult, increase coordination overhead, and make it harder for frontend developers and other team members to work with predictable API contracts.

I built ApiErrorKit to explore how this problem could be addressed through a reusable Spring Boot library and a common API error-handling standard.

The Problem

Without a common error-handling standard:

  • Different developers may return different error response formats.
  • The same type of exception may be handled differently across endpoints.
  • Frontend developers need to account for inconsistent API error structures.
  • Debugging becomes harder because error information is not standardized.
  • Changes to error-handling logic may need to be repeated across projects or services.
  • Sensitive exception messages may accidentally be exposed to API clients.

The Goal

ApiErrorKit aims to provide a simple, reusable foundation for consistent API error handling across Spring Boot applications.

The goal is not to replace application-specific exception handling, but to establish a common baseline that teams can extend when necessary.

✨ Features

  • Custom exception → RFC 9457 ProblemDetail
  • Simple @ApiError annotation
  • Custom HTTP status, title, and type
  • Automatic exception resolution
  • Inheritance-aware exception resolution
  • Validation error handling
  • Standard application/problem+json responses
  • Secure-by-default exception message handling
  • Configurable exception message exposure
  • Spring Boot auto-configuration
  • Custom ExceptionResolver support
  • Lightweight — no external infrastructure required

🏗️ How It Works

Custom Exception
       │
       ▼
   @ApiError
       │
       ▼
ExceptionResolver
       │
       ▼
ProblemDetailFactory
       │
       ▼
Spring ProblemDetail
       │
       ▼
application/problem+json

For example:

@ApiError(
    status = 404,
    title = "User Not Found",
    type = "https://api.example.com/problems/user-not-found"
)
public class UserNotFoundException extends RuntimeException {

    public UserNotFoundException(String message) {
        super(message);
    }
}

When this exception is thrown:

throw new UserNotFoundException("User 123 was not found");

ApiErrorKit produces a standardized response:

{
  "type": "https://api.example.com/problems/user-not-found",
  "title": "User Not Found",
  "status": 404,
  "detail": "User 123 was not found",
  "instance": "/users/123"
}

📦 Installation

Maven

Add the ApiErrorKit starter dependency to your Spring Boot application:

<dependency>
    <groupId>io.github.ashan-dissanayake</groupId>
    <artifactId>api-error-kit-spring-boot-starter</artifactId>
    <version>0.1.1</version>
</dependency>

ApiErrorKit 0.1.1 is published to Maven Central.


🚀 Usage

1. Create a Custom Exception

ApiErrorKit does not require custom exceptions to extend a library-specific base exception.

You can use your existing application exceptions.

public class UserNotFoundException extends RuntimeException {

    public UserNotFoundException(String message) {
        super(message);
    }
}

2. Add @ApiError

Annotate the exception with the API error metadata:

@ApiError(
    status = 404,
    title = "User Not Found",
    type = "https://api.example.com/problems/user-not-found"
)
public class UserNotFoundException extends RuntimeException {

    public UserNotFoundException(String message) {
        super(message);
    }
}

3. Throw the Exception

@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id) {

    throw new UserNotFoundException(
        "User " + id + " was not found"
    );
}

ApiErrorKit automatically converts the exception into a ProblemDetail response.


🔐 Exception Message Security

ApiErrorKit is secure by default.

Exception messages are not exposed to API clients unless explicitly enabled.

Default:

api-error-kit:
  include-exception-message: false

The response contains:

{
  "status": 500,
  "title": "Internal Server Error",
  "detail": "An unexpected error occurred"
}

This helps prevent accidental exposure of sensitive internal information such as:

  • database details
  • internal service information
  • implementation details
  • stack-related messages
  • infrastructure information

Enable Exception Messages

For environments where exposing exception messages is appropriate:

api-error-kit:
  include-exception-message: true

Then an annotated exception such as:

throw new UserNotFoundException("User 123 was not found");

can produce:

{
  "type": "https://api.example.com/problems/user-not-found",
  "title": "User Not Found",
  "status": 404,
  "detail": "User 123 was not found",
  "instance": "/users/123"
}

✅ Validation Errors

ApiErrorKit also handles Spring validation failures.

For example:

public class CreateUserRequest {

    @NotBlank
    private String name;

    @Email
    @NotBlank
    private String email;

    // getters and setters
}

Invalid input:

{
  "name": "",
  "email": "invalid-email"
}

Produces:

{
  "title": "Validation Failed",
  "status": 400,
  "detail": "Request validation failed",
  "instance": "/users",
  "errors": [
    {
      "field": "name",
      "message": "must not be blank"
    },
    {
      "field": "email",
      "message": "must be a well-formed email address"
    }
  ]
}

🧩 Custom Exception Resolution

ApiErrorKit uses an ExceptionResolver abstraction.

The default implementation is:

AnnotationExceptionResolver

Applications can provide their own implementation when custom exception-resolution rules are required.

Example:

@Component
public class CustomExceptionResolver
        implements ExceptionResolver {

    @Override
    public Optional<ResolvedApiError> resolve(
            Throwable exception) {

        // Custom resolution logic

        return Optional.empty();
    }
}

ApiErrorKit's default resolver is only registered when an application does not provide its own implementation.


⚙️ Configuration

Available configuration:

Property Default Description
api-error-kit.include-exception-message false Controls whether exception messages are included in API error responses

Example:

api-error-kit:
  include-exception-message: false

📋 Standard Error Response

ApiErrorKit is built around Spring's ProblemDetail and the RFC 9457 problem-details format.

Typical response:

{
  "type": "https://api.example.com/problems/user-not-found",
  "title": "User Not Found",
  "status": 404,
  "detail": "User 123 was not found",
  "instance": "/users/123"
}

Validation errors additionally contain an errors extension property.


🧪 Testing

The project includes unit and integration tests covering:

  • Annotated exception resolution
  • Unannotated exception fallback
  • Inherited @ApiError metadata
  • ProblemDetail creation
  • Null exception messages
  • Empty exception messages
  • Secure exception-message handling
  • Validation errors
  • HTTP response status and content type
  • RFC 9457 response fields

Run the test suite with:

./mvnw test

On Windows:

.\mvnw.cmd test

Current test suite:

Tests run: 12
Failures: 0
Errors: 0
Skipped: 0

🔗 External Consumption

ApiErrorKit 0.1.1 has been published to Maven Central and successfully verified through a separate Spring Boot consumer project.

The consumer project resolves the library directly from Maven Central and verifies auto-configuration, custom exception handling, validation errors, and RFC 9457 responses.

🏛️ Project Structure

src
├── main
│   ├── java
│   │   └── com.apierrorkit
│   │       ├── annotation
│   │       │   └── ApiError.java
│   │       │
│   │       ├── config
│   │       │   ├── ApiErrorKitAutoConfiguration.java
│   │       │   └── ApiErrorKitProperties.java
│   │       │
│   │       ├── handler
│   │       │   └── ProblemExceptionHandler.java
│   │       │
│   │       ├── problem
│   │       │   └── ProblemDetailFactory.java
│   │       │
│   │       └── resolver
│   │           ├── AnnotationExceptionResolver.java
│   │           ├── ExceptionResolver.java
│   │           └── ResolvedApiError.java
│   │
│   └── resources
│       └── META-INF
│           └── spring
│               └── org.springframework.boot.autoconfigure.AutoConfiguration.imports
│
└── test
    └── java
        └── com.apierrorkit
            ├── integration
            ├── problem
            └── resolver

🎯 Design Goals

ApiErrorKit intentionally focuses on a small set of responsibilities:

  1. Standardize API error responses.
  2. Reduce repetitive exception-handler code.
  3. Support existing custom exceptions.
  4. Follow RFC 9457 problem-details conventions.
  5. Avoid exposing sensitive exception information by default.
  6. Remain lightweight and easy to integrate.
  7. Provide extension points without introducing unnecessary complexity.

The project intentionally does not require external infrastructure such as:

  • Redis
  • Kafka
  • Elasticsearch
  • Log aggregation platforms
  • Authentication providers
  • External databases

🛠️ Technology Stack

  • Java 17
  • Spring Boot 4.x
  • Spring MVC
  • Spring ProblemDetail
  • Jakarta Bean Validation
  • Maven
  • JUnit
  • MockMvc
  • GitHub Actions
  • Maven Central

📌 Project Status

Current version: 0.1.1

ApiErrorKit is published to Maven Central and has been verified through an external Spring Boot consumer project.


📄 License

This project is licensed under the MIT License.

About

Lightweight Spring Boot library for standardized RFC 9457 API error responses.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages