{"id":15284192,"url":"https://github.com/quarkiverse/quarkus-resteasy-problem","last_synced_at":"2026-02-19T09:30:18.261Z","repository":{"id":37822744,"uuid":"343698261","full_name":"quarkiverse/quarkus-resteasy-problem","owner":"quarkiverse","description":"Unified error responses for Quarkus REST APIs via Problem Details for HTTP APIs (RFC9457 \u0026 RFC7807)","archived":false,"fork":false,"pushed_at":"2024-10-29T14:06:23.000Z","size":938,"stargazers_count":68,"open_issues_count":9,"forks_count":12,"subscribers_count":6,"default_branch":"main","last_synced_at":"2024-10-29T17:12:26.923Z","etag":null,"topics":["exception-handling","quarkus-extension","rest-problem","resteasy","rfc7807","rfc9457"],"latest_commit_sha":null,"homepage":"https://docs.quarkiverse.io/quarkus-resteasy-problem/dev","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/quarkiverse.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-03-02T08:25:23.000Z","updated_at":"2024-10-29T14:06:26.000Z","dependencies_parsed_at":"2024-02-29T15:48:50.482Z","dependency_job_id":"9f03246b-2eca-4498-8fad-16ef8c2a30ab","html_url":"https://github.com/quarkiverse/quarkus-resteasy-problem","commit_stats":null,"previous_names":["quarkiverse/quarkus-resteasy-problem","tietoevry/quarkus-resteasy-problem"],"tags_count":25,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quarkiverse%2Fquarkus-resteasy-problem","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quarkiverse%2Fquarkus-resteasy-problem/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quarkiverse%2Fquarkus-resteasy-problem/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quarkiverse%2Fquarkus-resteasy-problem/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/quarkiverse","download_url":"https://codeload.github.com/quarkiverse/quarkus-resteasy-problem/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247640465,"owners_count":20971557,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["exception-handling","quarkus-extension","rest-problem","resteasy","rfc7807","rfc9457"],"created_at":"2024-09-30T14:50:37.764Z","updated_at":"2026-02-19T09:30:18.247Z","avatar_url":"https://github.com/quarkiverse.png","language":"Java","funding_links":[],"categories":["REST错误处理"],"sub_categories":["Spring Cloud框架"],"readme":"# Problem Details for HTTP APIs (RFC-7807) implementation for Quarkus / RESTeasy.\n\n[![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/quarkiverse/quarkus-resteasy-problem/blob/main/LICENSE.txt)\n\n[![Build status](https://github.com/quarkiverse/quarkus-resteasy-problem/actions/workflows/unit-tests.yaml/badge.svg)](https://github.com/quarkiverse/quarkus-resteasy-problem/actions/workflows/unit-tests.yaml)\n[![Build status](https://github.com/quarkiverse/quarkus-resteasy-problem/actions/workflows/integration-tests.yaml/badge.svg)](https://github.com/quarkiverse/quarkus-resteasy-problem/actions/workflows/integration-tests.yaml)\n[![Build status](https://github.com/quarkiverse/quarkus-resteasy-problem/actions/workflows/native-mode-tests.yaml/badge.svg)](https://github.com/quarkiverse/quarkus-resteasy-problem/actions/workflows/native-mode-tests.yaml)\n\n[RFC7807 Problem](https://tools.ietf.org/html/rfc7807) extension for Quarkus RESTeasy/JaxRS applications. It maps Exceptions to `application/problem+json` HTTP responses. Inspired by [Zalando Problem library](https://github.com/zalando/problem), originally open sourced by [Tietoevry](https://github.com/evry), now part of Quarkiverse.\n\nThis extension supports:\n- Quarkus 1, 2 and 3\n- `quarkus-rest-jackson` and `quarkus-rest-jsonb`\n- `quarkus-resteasy-jackson` and `quarkus-resteasy-jsonb`\n- OpenAPI integration (via `quarkus-smallrye-openapi`)\n- JVM and native mode\n\n## Why you should use this extension?\n- __consistency__ - it unifies your REST API error messages, and gives it much needed consistency, no matter which JSON provider (Jackson vs JsonB) or paradigm (classic/blocking vs reactive) you're using.   \n\n- __predictability__ - no matter what kind of exception is thrown: expected (thrown by you on purpose), or unexpected (not thrown 'by design') - your API consumer gets similar, repeatable experience.  \n\n- __safety__ - it helps prevent leakage of some implementation details like stack-traces, DTO/resource class names etc.\n\n- __time-saving__ - in most cases you will not have to implement your own JaxRS `ExceptionMapper`s anymore, which makes your app smaller, and less error-prone. \n\nSee [Built-in Exception Mappers Wiki](https://github.com/quarkiverse/quarkus-resteasy-problem/wiki#built-in-exception-mappers) for more details.\n\nFrom [RFC7807](https://tools.ietf.org/html/rfc7807):\n```\nHTTP [RFC7230] status codes are sometimes not sufficient to convey\nenough information about an error to be helpful.  While humans behind\nWeb browsers can be informed about the nature of the problem with an\nHTML [W3C.REC-html5-20141028] response body, non-human consumers of\nso-called \"HTTP APIs\" are usually not.\n```\n\n## Usage\n### Quarkus 3.14+\nAdd this to your pom.xml:\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003eio.quarkiverse.resteasy-problem\u003c/groupId\u003e\n    \u003cartifactId\u003equarkus-resteasy-problem\u003c/artifactId\u003e\n    \u003cversion\u003e3.32.0\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n\u003cdetails\u003e\n    \u003csummary\u003eQuarkus up to 3.13 / Java 17+\u003c/summary\u003e\n\n### Quarkus 3.X\n Quarkus             | Java | quarkus-resteasy-problem\n---------------------|------|-------------------------\n\\\u003e= 3.32            | 17+  | 3.32.0\n\\\u003e= 3.9 | 17+  | 3.21.1\n\\\u003e= 3.7  | 17+  | 3.7.0\n\u003c 3.7             | 11+  | 3.1.0\n\nMake sure proper version of JDK (look for the table above), then run:\n```shell\nmvn io.quarkus:quarkus-maven-plugin:${quarkus.version}:create \\\n    -DprojectGroupId=problem \\\n    -DprojectArtifactId=quarkus-resteasy-problem-playground \\\n    -DclassName=\"problem.HelloResource\" \\\n    -Dpath=\"/hello\" \\\n    -Dextensions=\"resteasy,resteasy-jackson\"\ncd quarkus-resteasy-problem-playground\n./mvnw quarkus:add-extension -Dextensions=\"com.tietoevry.quarkus:quarkus-resteasy-problem:3.9.0\"\n```\nOr add the following dependency to `pom.xml` in existing project:\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.tietoevry.quarkus\u003c/groupId\u003e\n    \u003cartifactId\u003equarkus-resteasy-problem\u003c/artifactId\u003e\n    \u003cversion\u003e3.9.0\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n    \u003csummary\u003eQuarkus 2.X / Java 11+\u003c/summary\u003e\n\n  Make sure JDK 11 is in your PATH, then run:\n  ```shell \n  mvn io.quarkus:quarkus-maven-plugin:2.16.10.Final:create \\\n      -DprojectGroupId=problem \\\n      -DprojectArtifactId=quarkus-resteasy-problem-playground \\\n      -DclassName=\"problem.HelloResource\" \\\n      -Dpath=\"/hello\" \\\n      -Dextensions=\"resteasy,resteasy-jackson\"\n  cd quarkus-resteasy-problem-playground\n  ./mvnw quarkus:add-extension -Dextensions=\"com.tietoevry.quarkus:quarkus-resteasy-problem:2.2.0\n  ```\n  Or add the following dependency to `pom.xml` in existing project:\n  ```xml\n  \u003cdependency\u003e\n      \u003cgroupId\u003ecom.tietoevry.quarkus\u003c/groupId\u003e\n      \u003cartifactId\u003equarkus-resteasy-problem\u003c/artifactId\u003e\n      \u003cversion\u003e2.2.0\u003c/version\u003e\n  \u003c/dependency\u003e\n  ```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n    \u003csummary\u003eQuarkus 1.X / Java 1.8+\u003c/summary\u003e\n    \n  Create a new Quarkus project with the following command:\n  ```shell \n  mvn io.quarkus:quarkus-maven-plugin:1.13.7.Final:create \\\n      -DprojectGroupId=problem \\\n      -DprojectArtifactId=quarkus-resteasy-problem-playground \\\n      -DclassName=\"problem.HelloResource\" \\\n      -Dpath=\"/hello\" \\\n      -Dextensions=\"resteasy,resteasy-jackson,com.tietoevry.quarkus:quarkus-resteasy-problem:1.0.0\"\n  cd quarkus-resteasy-problem-playground\n  ```\n  Or add the following dependency to `pom.xml` in existing project:\n  ```xml\n  \u003cdependency\u003e\n    \u003cgroupId\u003ecom.tietoevry.quarkus\u003c/groupId\u003e\n    \u003cartifactId\u003equarkus-resteasy-problem\u003c/artifactId\u003e\n    \u003cversion\u003e1.0.0\u003c/version\u003e\n  \u003c/dependency\u003e\n  ```\n\u003c/details\u003e\n\n**Hint:** you can also use `resteasy-jsonb` or reactive equivalents: `rest-jackson` / `rest-jsonb` instead of `resteasy-jackson`\n\n\nOnce you run Quarkus: `./mvnw compile quarkus:dev`, and you will find `resteasy-problem` in the logs:\n\u003cpre\u003e\nInstalled features: [cdi, resteasy, resteasy-jackson, \u003cb\u003e\u003cu\u003eresteasy-problem\u003c/u\u003e\u003c/b\u003e]\n\u003c/pre\u003e\n\nNow you can throw `HttpProblem`s (using builder or a subclass), JaxRS exceptions (e.g `NotFoundException`) or `ThrowableProblem`s from Zalando library:\n\n```java\npackage problem;\n\nimport io.quarkiverse.resteasy.problem.HttpProblem;\nimport jakarta.ws.rs.GET;\nimport jakarta.ws.rs.Path;\nimport jakarta.ws.rs.core.Response;\n\n@Path(\"/hello\")\npublic class HelloResource {\n\n    @GET\n    public String hello() {\n        throw new HelloProblem(\"rfc7807-by-example\");\n    }\n\n    static class HelloProblem extends HttpProblem {\n        HelloProblem(String message) {\n            super(builder()\n                    .withTitle(\"Bad hello request\")\n                    .withStatus(Response.Status.BAD_REQUEST)\n                    .withDetail(message)\n                    .withHeader(\"X-RFC7807-Message\", message)\n                    .with(\"hello\", \"world\"));\n        }\n    }\n}\n```\n\nOpen [http://localhost:8080/hello](http://localhost:8080/hello) in your browser, and you should see this response:\n\n```json\nHTTP/1.1 400 Bad Request\nX-RFC7807-Message: rfc7807-by-example\nContent-Type: application/problem+json\n        \n{\n    \"status\": 400,\n    \"title\": \"Bad hello request\",\n    \"detail\": \"rfc7807-by-example\",\n    \"instance\": \"/hello\",\n    \"hello\": \"world\"\n}\n```\n\nThis extension will also produce the following log message:\n```\n10:53:48 INFO [http-problem] (executor-thread-1) status=400, title=\"Bad hello request\", detail=\"rfc7807-by-example\"\n```\nExceptions transformed into http 500s (aka server errors) will be logged as `ERROR`, including full stacktrace.\n\nMore on throwing problems: [zalando/problem usage](https://github.com/zalando/problem#usage)\n\n## RestClients (available since \u003ca href=\"https://github.com/quarkiverse/quarkus-resteasy-problem/releases/tag/3.20.0\"\u003ev3.20.0\u003c/a\u003e)\nIf you use RestClients and your upstream services return `application/problem+json` responses, you can register `ThrowingHttpProblemClientExceptionMapper` for your client to get automatic deserialization and rethrowing `HttpProblem` instead of `ClientWebApplicationException` \n\n```java\n@RegisterRestClient(configKey = \"my-rest-client\")\n@RegisterProvider(value = ThrowingHttpProblemClientExceptionMapper.class)\npublic interface MyRestClient {\n    @GET\n    @Path(\"/resource\")\n    void getResource();\n}\n```\n\n## OpenAPI integration (available since \u003ca href=\"https://github.com/quarkiverse/quarkus-resteasy-problem/releases/tag/3.20.0\"\u003ev3.20.0\u003c/a\u003e)\nWhen `quarkus-smallrye-openapi` is in the classpath, this extension provides a bunch of out-of-the-box features :\n\n- complete OpenApi schema definitions for `HttpProblem` and `HttpValidationProblem` that can be used in annotations (e.g. `@Schema(implementation = HttpProblem.class)`)\n- auto-generating documentation for endpoints declaring `throws` for few common exceptions, e.g. `NotFoundException`,`ForbiddenException` or even `Exception`\n```java\n@GET\n@Path(\"/my-endpoint\")\n@APIResponse(responseCode = \"409\", description = \"Request received but there has been a conflict\")\npublic void endpoint() throws NotFoundException {}\n```\nthis endpoint will automatically get both 409 (from `@APIResponse`) and 404 (derived from `throws`) responses documented in open api.\n\n- attaching `HttpProblem` schema to endpoints declaring error api responses (4XX and 5XX) without `content` field specified:\n```java\n@APIResponse(\n  responseCode = \"409\", \n  description = \"Request received but there has been a conflict\"\n)\n```\nis an equivalent to this:\n```java\n@APIResponse(\n  responseCode = \"409\", \n  description = \"Request received but there has been a conflict\",\n  content = @Content(\n    mediaType = \"application/problem+json\",\n    schema = @Schema(implementation = HttpProblem.class)\n  )\n)\n```\n\n- if you project needs to define and document additional Problem Detail properties, you need to extend `HttpProblem`, annotate it with OpenApi annotations:\n\n```java\n@Schema(name = \"MyHttpProblem\", description = \"HTTP Problem Response according to MyProject\",\n        additionalProperties = Schema.True.class)\npublic class MyHttpProblem extends HttpProblem {\n\n    @Schema(description = \"Additional parameters providing more details about the problem\", examples = \"{\\\"timestamp\\\":\\\"2024-03-20T10:00:00Z\\\",\\\"traceId\\\":\\\"550e8400-e29b-41d4-a716-446655440000\\\"}\")\n    private SortedMap\u003cString, Object\u003e contexts;\n\n    @Schema(description = \"Original cause of error, only set when forwarding an underlying problem\")\n    private MyHttpProblem cause;\n\n}\n```\nand tell this extension which schema is default for Problem Details: \n```properties\nquarkus.resteasy.problem.openapi.default-schema=MyHttpProblem\n```\n\n## Configuration options\n\n- (Build time) Include MDC properties in the API response. You have to provide those properties to MDC using `MDC.put`\n```\nquarkus.resteasy.problem.include-mdc-properties=uuid,application,version\n```\nResult:\n```json\n{\n  \"status\": 500,\n  \"title\": \"Internal Server Error\",\n  \"uuid\": \"d79f8cfa-ef5b-4501-a2c4-8f537c08ec0c\",\n  \"application\": \"awesome-microservice\",\n  \"version\": \"1.0\"\n}\n```\n\n- (Runtime) Changes default `400 Bad request` response status when `ConstraintViolationException` is thrown (e.g. by Hibernate Validator)\n```\nquarkus.resteasy.problem.constraint-violation.status=422\nquarkus.resteasy.problem.constraint-violation.title=Constraint violation\n```\nResult:\n```json\nHTTP/1.1 422 Unprocessable Entity\nContent-Type: application/problem+json\n\n{\n    \"status\": 422,\n    \"title\": \"Constraint violation\",\n    (...)\n}\n```\n\n- (Runtime) Tuning logging\n```\nquarkus.log.category.http-problem.level=INFO # default: all problems are logged\nquarkus.log.category.http-problem.level=ERROR # only HTTP 5XX problems are logged\nquarkus.log.category.http-problem.level=OFF # disables all problems-related logging\n```\n\n## Custom ProblemPostProcessor\nIf you want to intercept, change or augment a mapped `HttpProblem` before it gets serialized into raw HTTP response \nbody, you can create a bean extending `ProblemPostProcessor`, and override `apply` method.\n\nExample:\n```java\n@ApplicationScoped\nclass CustomPostProcessor implements ProblemPostProcessor {\n    \n    @Inject // acts like normal bean, DI works fine etc\n    Validator validator;\n    \n    @Override\n    public HttpProblem apply(HttpProblem problem, ProblemContext context) {\n        return HttpProblem.builder(problem)\n                .with(\"injected_from_custom_post_processor\", \"hello world \" + context.path)\n                .build();\n    }\n    \n}\n```\n\n## Troubles?\n\nIf you have questions, concerns, bug reports, etc, please file an issue in this repository's Issue Tracker. You may also want to have a look at [troubleshooting FAQ](./TROUBLESHOOTING.md).\n\n## Contributing\n\nTo contribute, simply make a pull request and add a brief description (1-2 sentences) of your addition or change.\nFor more details check the [contribution guidelines](./CONTRIBUTING.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fquarkiverse%2Fquarkus-resteasy-problem","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fquarkiverse%2Fquarkus-resteasy-problem","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fquarkiverse%2Fquarkus-resteasy-problem/lists"}