{"id":36422910,"url":"https://github.com/problem4j/problem4j-core","last_synced_at":"2026-03-14T22:49:59.405Z","repository":{"id":173653879,"uuid":"631400057","full_name":"problem4j/problem4j-core","owner":"problem4j","description":"Core library implementing Problem model according to RFC7807 (aka RFC9457)","archived":false,"fork":false,"pushed_at":"2026-03-01T13:42:43.000Z","size":573,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-03-01T16:54:21.889Z","etag":null,"topics":["java-library","problem-details","problem-details-for-http-apis","rfc7807"],"latest_commit_sha":null,"homepage":"https://problem4j.github.io","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/problem4j.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-04-22T22:46:09.000Z","updated_at":"2026-03-01T13:42:45.000Z","dependencies_parsed_at":"2025-06-15T10:28:07.675Z","dependency_job_id":"ab40f4ff-a6c7-4623-b381-969c35757cdf","html_url":"https://github.com/problem4j/problem4j-core","commit_stats":null,"previous_names":["malczuuu/problem4j-core","problem4j/problem4j-core"],"tags_count":25,"template":false,"template_full_name":null,"purl":"pkg:github/problem4j/problem4j-core","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/problem4j%2Fproblem4j-core","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/problem4j%2Fproblem4j-core/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/problem4j%2Fproblem4j-core/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/problem4j%2Fproblem4j-core/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/problem4j","download_url":"https://codeload.github.com/problem4j/problem4j-core/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/problem4j%2Fproblem4j-core/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30323207,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-10T01:36:58.598Z","status":"online","status_checked_at":"2026-03-10T02:00:06.579Z","response_time":106,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["java-library","problem-details","problem-details-for-http-apis","rfc7807"],"created_at":"2026-01-11T17:45:47.028Z","updated_at":"2026-03-14T22:49:59.398Z","avatar_url":"https://github.com/problem4j.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Problem4J Core\n\n[![Build Status](https://github.com/problem4j/problem4j-core/actions/workflows/gradle-build.yml/badge.svg)](https://github.com/problem4j/problem4j-core/actions/workflows/gradle-build.yml)\n[![Sonatype](https://img.shields.io/maven-central/v/io.github.problem4j/problem4j-core)][maven-central]\n[![License](https://img.shields.io/github/license/problem4j/problem4j-core)](https://github.com/problem4j/problem4j-core/blob/main/LICENSE)\n\nThis library provides a minimal, framework-agnostic Java model of the [RFC 7807][rfc7807] \"Problem Details\" object, with\nan immutable `Problem` class and a fluent `ProblemBuilder` for convenient construction.\n\n\u003e Note that [RFC 7807][rfc7807] was later extended in [RFC 9457][rfc9457], however core concepts remain the same.\n\nIt is intended to be used as a **foundation** for other libraries or applications that add framework-specific behavior\n(e.g. Jackson, Spring - see [Problem4J Links](#problem4j-links) chapter).\n\n## Table of Contents\n\n- [Features](#features)\n- [Example](#example)\n- [Usage](#usage)\n- [Project Status](#project-status)\n- [Problem4J Links](#problem4j-links)\n- [Building from source](#building-from-source)\n\n## Features\n\n- ✅ Immutable `Problem` data model.\n- ✅ Dedicated unchecked `ProblemException` to be used in error handling.\n- ✅ Builder pattern for fluent construction.\n- ✅ Static `Problem.of(...)` factory methods for in-place creation convenience (since `v1.4.0`).\n- ✅ `@ProblemMapping` annotation and `ProblemMapper` to allow declarative approach in converting exception instances\n  into `Problem` objects.\n- ✅ Serializable and easy to log or format.\n- ✅ HTTP-agnostic (no external dependencies).\n- ✅ Follows [RFC 7807][rfc7807] semantics:\n    - `type` (URI),\n    - `title` (short summary),\n    - `status` (numeric code),\n    - `detail` (detailed description),\n    - `instance` (URI to the specific occurrence),\n    - custom field extensions.\n- ✅ Integrated with JSpecify annotations for nullability and Kotlin interop (since `v1.4.0`).\n- ✅ Supports Java version 8+, but due to producing multi-release JAR, can support **Java Platform Module System** if\n  using Java version 9+ (since `v1.4.0`).\n\n## Example\n\nThrow an instance of `ProblemException`.\n\n```java\nimport io.github.problem4j.core.Problem;\nimport io.github.problem4j.core.ProblemException;\n\n// using fully-fledged builder\n\nProblem problem =\n    Problem.builder()\n        .type(\"https://example.com/errors/invalid-request\")\n        .title(\"Invalid Request\")\n        .status(400)\n        .detail(\"not a valid json\")\n        .instance(\"https://example.com/instances/1234\")\n        .build();\nthrow new ProblemException(problem);\n\n// using convenience factory method\n\nthrow new ProblemException(Problem.of(\"Invalid Request\", 400, \"not a valid json\"));\n```\n\nThrow an exception annotated with `@ProblemMapping`.\n\n```java\nimport io.github.problem4j.core.ProblemMapping;\nimport io.github.problem4j.core.ProblemMapper;\n\n@ProblemMapping(\n        type = \"https://example.org/test/problem\",\n        title = \"Test problem\",\n        status = 400,\n        detail = \"failed: {message}\",\n        extensions = {\"subject\"})\npublic class MessageException extends RuntimeException {\n\n    private final String subject;\n\n    public MessageException(String subject, String message) {\n        super(message);\n        this.subject = subject;\n    }\n}\n\nMessageException ex = new MessageException(\"sub\", \"boom\");\n\nProblemMapper mapper = ProblemMapper.create();\nProblem problem = mapper.toProblemBuilder(ex).build();\n```\n\nIf using Java module system, add the following `requires` directive to your `module-info.java` file.\n\n```java\nmodule org.example.project {\n    requires io.github.problem4j.core;\n}\n```\n\n## Usage\n\nAdd library as dependency to Maven or Gradle. See the actual versions on [Maven Central][maven-central]. **Java 8** or\nhigher is required to use this library.\n\n[![Sonatype](https://img.shields.io/maven-central/v/io.github.problem4j/problem4j-core)][maven-central]\n\n1. Maven:\n   ```xml\n   \u003cdependencies\u003e\n       \u003cdependency\u003e\n           \u003cgroupId\u003eio.github.problem4j\u003c/groupId\u003e\n           \u003cartifactId\u003eproblem4j-core\u003c/artifactId\u003e\n           \u003cversion\u003e{version}\u003c/version\u003e\n       \u003c/dependency\u003e\n   \u003c/dependencies\u003e\n   ```\n2. Gradle (Groovy or Kotlin DSL):\n   ```groovy\n   dependencies {\n       implementation(\"io.github.problem4j:problem4j-core:{version}\")\n   }\n    ```\n\n## Project Status\n\n[![Status: Feature Complete](https://img.shields.io/badge/feature%20complete-darkblue?label=status)](#project-status)\n\n**Problem4J Core** is considered *feature complete*. Only **bug fixes** will be added. New features may be included only\nif there is a strong justification for them; otherwise, future projects are expected to build on this one as a\ndependency.\n\n## Problem4J Links\n\n- [`problem4j.github.io`](https://problem4j.github.io) - Full documentation of all projects from Problem4J family.\n- [`problem4j-core`][problem4j-core] - Core library defining `Problem` model and `ProblemException`.\n- [`problem4j-jackson`][problem4j-jackson] - Jackson module for serializing and deserializing `Problem` objects.\n- [`problem4j-spring`][problem4j-spring] - Spring modules extending `ResponseEntityExceptionHandler` for handling\n  exceptions and returning `Problem` responses.\n\n## Building from source\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eExpand...\u003c/b\u003e\u003c/summary\u003e\n\nGradle **9.x+** requires **Java 17** or higher to run. For building the project, Gradle automatically picks up **Java \n25** via **toolchains** and the `foojay-resolver-convention` plugin. This Java version is needed because the project\nuses **ErrorProne** and **NullAway** for static nullness analysis.\n\nThe produced artifacts are compatible with **Java 8** thanks to `options.release = 8` in the Gradle `JavaCompile` task.\nThis means that regardless of the Java version used to run Gradle, the resulting bytecode remains compatible.\n\nThe **default Gradle tasks** include `spotlessApply` (for code formatting) and `build` (for compilation and tests).The\nsimplest way to build the project is to run:\n\n```bash\n./gradlew\n```\n\n---\n\nTo **execute tests** use `test` task. Tests do not change `options.release` so newer Java API can be used.\n\n```bash\n./gradlew test\n```\n\n---\n\nTo **format the code** according to the style defined in [`build.gradle.kts`](./build.gradle.kts) rules use `spotlessApply`\ntask. **Note** that **building will fail** if code is not properly formatted.\n\n```bash\n./gradlew spotlessApply\n```\n\n**Note** that if the year has changed, add `-Pspotless.license-year-enabled` flag to update the year in license headers.\nThe [publishing GitHub Action](.github/workflows/gradle-publish-release.yml) will fail if the year is not updated, but\nfor local development and builds you can choose to skip it and update the year later.\n\n```bash\n./gradlew spotlessApply -Pspotless.license-year-enabled\n```\n\n---\n\nTo **publish** the built artifacts to **local Maven repository**, use `publishToMavenLocal` task.\n\n```bash\n./gradlew publishToMavenLocal\n```\n\nNote that for using Maven Local artifacts in target projects, you need to add `mavenLocal()` repository.\n\n```kotlin\nrepositories {\n    mavenLocal()\n    mavenCentral()\n}\n```\n\n\u003c/details\u003e\n\n[maven-central]: https://central.sonatype.com/artifact/io.github.problem4j/problem4j-core\n\n[problem4j-core]: https://github.com/problem4j/problem4j-core\n\n[problem4j-jackson]: https://github.com/problem4j/problem4j-jackson\n\n[problem4j-spring]: https://github.com/problem4j/problem4j-spring\n\n[rfc7807]: https://datatracker.ietf.org/doc/html/rfc7807\n\n[rfc9457]: https://datatracker.ietf.org/doc/html/rfc9457\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fproblem4j%2Fproblem4j-core","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fproblem4j%2Fproblem4j-core","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fproblem4j%2Fproblem4j-core/lists"}