What is ProblemDetail in Spring MVC, and what RFC / media type does it implement?
answer
- RFC 7807 / RFC 9457
- type, title, status, detail, instance
- application/problem+json
- org.springframework.http.ProblemDetail
- forStatus / forStatusAndDetail / setProperty
basics
~10 sProblemDetail is a Spring class (org.springframework.http.ProblemDetail) that models a standard error body from RFC 7807. It is serialized as application/problem+json with fields like type, title, status, detail, and instance.
solid answer
~40 sProblemDetail (org.springframework.http.ProblemDetail, added in Spring Framework 6 / Boot 3) is Spring's representation of RFC 7807 'Problem Details for HTTP APIs'. Instead of every service inventing its own error JSON, RFC 7807 defines a standard shape with five fields: type (a URI identifying the problem kind, default 'about:blank'), title (a short human-readable summary), status (the HTTP status code), detail (a human-readable explanation of this specific occurrence), and instance (a URI for this specific occurrence). It is sent with the media type application/problem+json (MediaType.APPLICATION_PROBLEM_JSON) so clients know it is a structured error. You build one with factory methods like ProblemDetail.forStatus(HttpStatus.NOT_FOUND) or forStatusAndDetail(...), and you can attach extra fields via setProperty(name, value).
code
java · 11 linesimport org.springframework.http.HttpStatus;
import org.springframework.http.ProblemDetail;
import java.net.URI;
ProblemDetail pd = ProblemDetail.forStatusAndDetail(
HttpStatus.NOT_FOUND, "Order 42 was not found");
pd.setTitle("Order not found");
pd.setType(URI.create("https://api.example.com/errors/order-not-found"));
pd.setInstance(URI.create("/orders/42"));
pd.setProperty("orderId", 42); // RFC 7807 extension member
// Serialized as application/problem+jsongo deeper
Know the five fields, the media type, and that it comes from RFC 7807 via org.springframework.http.ProblemDetail.
Know the factory methods and setProperty for extensions, plus that it works in both MVC and WebFlux.
Discuss how type URIs should be stable/documented and how status in body must match the response status line.
Weigh RFC 7807 adoption vs a bespoke envelope, and note RFC 9457 supersession and cross-service consistency.
## The problem RFC 7807 solves Before a standard existed, every REST API returned errors in its own ad-hoc JSON shape (`{"error": "..."}`, `{"message": "...", "code": 42}`, etc.). Clients had to learn each API's quirks. **RFC 7807 'Problem Details for HTTP APIs'** (later superseded by RFC 9457, but Spring's docs still reference 7807) defines one canonical error body so clients and tools can parse errors uniformly. ## The five standard fields `org.springframework.http.ProblemDetail` (introduced in **Spring Framework 6 / Spring Boot 3**) models exactly these fields: - **type** — a URI (as a `java.net.URI`) that identifies the *category* of problem. Default is `about:blank`, which per the spec means 'no specific type; just use the status code'. A real type like `https://api.example.com/errors/out-of-credit` can point to documentation. - **title** — a short, human-readable summary of the problem type. Should stay the same for a given `type` (e.g. 'You do not have enough credit'). - **status** — the HTTP status code as an integer (e.g. `404`), duplicated in the body for convenience. - **detail** — a human-readable explanation *specific to this occurrence* (e.g. 'Your balance is 30 but the cost is 50'). - **instance** — a URI identifying the *specific occurrence* (e.g. `/account/12345/msgs/abc`). All fields are optional per the spec; Spring populates `status` and `title` sensibly by default. ## The media type A ProblemDetail response is sent with `Content-Type: application/problem+json` (constant `MediaType.APPLICATION_PROBLEM_JSON`). The `+json` structured-suffix tells generic tooling it is JSON while the `problem` prefix flags it as an error body. There is also an XML variant, `application/problem+xml`. ## Creating one ```java ProblemDetail pd = ProblemDetail.forStatus(HttpStatus.NOT_FOUND); pd.setDetail("Order 42 was not found"); pd.setType(URI.create("https://api.example.com/errors/order-not-found")); ``` Factory methods: `forStatus(HttpStatusCode)`, `forStatus(int)`, `forStatusAndDetail(HttpStatusCode, String)`. There is no public constructor you would normally use — go through the factories. ## Extension members RFC 7807 lets you add arbitrary extra fields. In Spring you call `pd.setProperty("balance", 30)` and it is serialized as a top-level JSON member alongside the standard fields. This is how you carry domain-specific data (a correlation id, a list of validation errors, etc.). ## Returning it From a `@RestController` or `@ExceptionHandler` you can return a `ProblemDetail` directly, a `ResponseEntity<ProblemDetail>`, or throw an exception that implements `ErrorResponse`. Spring's message converters serialize it with the correct content type. ## Gotchas - The `type` default `about:blank` is intentional — don't feel obligated to set a URI unless you have stable documentation to point to. - `status` in the body is informational; the *actual* HTTP status is still driven by the response status line / `ResponseEntity`. Keep them consistent. - ProblemDetail is a Spring class, not a JDK class — it lives in `spring-web`, so it is available in both Spring MVC and WebFlux.
- What is the default value of the 'type' field and what does it mean?It defaults to the URI 'about:blank', which per RFC 7807 signals there is no specific problem type and the client should rely on the HTTP status code alone.
- How do you add a custom field like a correlation id to the body?Call setProperty("correlationId", value) — RFC 7807 extension members are serialized as extra top-level JSON members.
saying these in an interview costs you the question
- Saying ProblemDetail is serialized as plain application/json (it is application/problem+json)
- Claiming there are only three fields or naming wrong fields (correct: type, title, status, detail, instance)
- Thinking ProblemDetail is a Spring Boot starter feature only, not a Spring Framework class