skip to content

What is ProblemDetail in Spring MVC, and what RFC / media type does it implement?

level: juniorimportance: must knowfreq 62%

answer

  1. RFC 7807 / RFC 9457
  2. type, title, status, detail, instance
  3. application/problem+json
  4. org.springframework.http.ProblemDetail
  5. forStatus / forStatusAndDetail / setProperty

basics

~10 s

ProblemDetail 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 s

ProblemDetail (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 lines
java
import 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+json

go deeper

for a junior

Know the five fields, the media type, and that it comes from RFC 7807 via org.springframework.http.ProblemDetail.

for a middle

Know the factory methods and setProperty for extensions, plus that it works in both MVC and WebFlux.

for a senior

Discuss how type URIs should be stable/documented and how status in body must match the response status line.

for a principal

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

context