Skip to content

Core library implementing Problem model according to RFC7807 (aka RFC9457)

License

Notifications You must be signed in to change notification settings

problem4j/problem4j-core

Repository files navigation

Problem4J Core

Build Status Sonatype License

This library provides a minimal, framework-agnostic Java model of the RFC 7807 "Problem Details" object, with an immutable Problem class and a fluent ProblemBuilder for convenient construction.

Note that RFC 7807 was later extended in RFC 9457, however core concepts remain the same.

It is intended to be used as a foundation for other libraries or applications that add framework-specific behavior (e.g. Jackson, Spring - see Problem4J Links chapter).

Table of Contents

Features

  • ✅ Immutable Problem data model.
  • ✅ Dedicated unchecked ProblemException to be used in error handling.
  • ✅ Builder pattern for fluent construction.
  • ✅ Static Problem.of(...) factory methods for in-place creation convenience (since v1.4.0).
  • @ProblemMapping annotation and ProblemMapper to allow declarative approach in converting exception instances into Problem objects.
  • ✅ Serializable and easy to log or format.
  • ✅ HTTP-agnostic (no external dependencies).
  • ✅ Follows RFC 7807 semantics:
    • type (URI),
    • title (short summary),
    • status (numeric code),
    • detail (detailed description),
    • instance (URI to the specific occurrence),
    • custom field extensions.
  • ✅ Integrated with JSpecify annotations for nullability and Kotlin interop (since v1.4.0).
  • ✅ Supports Java version 8+, but due to producing multi-release JAR, can support Java Platform Module System if using Java version 9+ (since v1.4.0).

Example

Throw an instance of ProblemException.

import io.github.problem4j.core.Problem;
import io.github.problem4j.core.ProblemException;

// using fully-fledged builder

Problem problem =
    Problem.builder()
        .type("https://example.com/errors/invalid-request")
        .title("Invalid Request")
        .status(400)
        .detail("not a valid json")
        .instance("https://example.com/instances/1234")
        .build();
throw new ProblemException(problem);

// using convenience factory method

throw new ProblemException(Problem.of("Invalid Request", 400, "not a valid json"));

Throw an exception annotated with @ProblemMapping.

import io.github.problem4j.core.ProblemMapping;
import io.github.problem4j.core.ProblemMapper;

@ProblemMapping(
        type = "https://example.org/test/problem",
        title = "Test problem",
        status = 400,
        detail = "failed: {message}",
        extensions = {"subject"})
public class MessageException extends RuntimeException {

    private final String subject;

    public MessageException(String subject, String message) {
        super(message);
        this.subject = subject;
    }
}

MessageException ex = new MessageException("sub", "boom");

ProblemMapper mapper = ProblemMapper.create();
Problem problem = mapper.toProblemBuilder(ex).build();

If using Java module system, add the following requires directive to your module-info.java file.

module org.example.project {
    requires io.github.problem4j.core;
}

Usage

Add library as dependency to Maven or Gradle. See the actual versions on Maven Central. Java 8 or higher is required to use this library.

  1. Maven:
    <dependencies>
        <dependency>
            <groupId>io.github.problem4j</groupId>
            <artifactId>problem4j-core</artifactId>
            <version>1.4.2</version>
        </dependency>
    </dependencies>
  2. Gradle (Groovy or Kotlin DSL):
    dependencies {
        implementation("io.github.problem4j:problem4j-core:1.4.2")
    }

Project Status

Status: Feature Complete

Problem4J Core is considered feature complete. Only bug fixes will be added. New features may be included only if there is a strong justification for them; otherwise, future projects are expected to build on this one as a dependency.

Problem4J Links

  • problem4j.github.io - Full documentation of all projects from Problem4J family.
  • problem4j-core - Core library defining Problem model and ProblemException.
  • problem4j-jackson - Jackson module for serializing and deserializing Problem objects.
  • problem4j-spring - Spring modules extending ResponseEntityExceptionHandler for handling exceptions and returning Problem responses.

Building from source

Expand...

Gradle 9.x+ requires Java 17 or higher to run. For building the project, Gradle automatically picks up Java 25 via toolchains and the foojay-resolver-convention plugin. This Java version is needed because the project uses ErrorProne and NullAway for static nullness analysis.

The produced artifacts are compatible with Java 8 thanks to options.release = 8 in the Gradle JavaCompile task. This means that regardless of the Java version used to run Gradle, the resulting bytecode remains compatible.

The default Gradle tasks include spotlessApply (for code formatting) and build (for compilation and tests).The simplest way to build the project is to run:

./gradlew

To execute tests use test task. Tests do not change options.release so newer Java API can be used.

./gradlew test

To format the code according to the style defined in build.gradle.kts rules use spotlessApply task. Note that building will fail if code is not properly formatted.

./gradlew spotlessApply

Note that if the year has changed, add -Pspotless.license-year-enabled flag to update the year in license headers. The publishing GitHub Action will fail if the year is not updated, but for local development and builds you can choose to skip it and update the year later.

./gradlew spotlessApply -Pspotless.license-year-enabled

To publish the built artifacts to local Maven repository, use publishToMavenLocal task.

./gradlew publishToMavenLocal

Note that for using Maven Local artifacts in target projects, you need to add mavenLocal() repository.

repositories {
    mavenLocal()
    mavenCentral()
}

About

Core library implementing Problem model according to RFC7807 (aka RFC9457)

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Contributors 2

  •  
  •