Class ProblemDetailsProcessor

java.lang.Object
org.apache.juneau.rest.server.processor.ProblemDetailsProcessor
All Implemented Interfaces:
ResponseProcessor

public class ProblemDetailsProcessor extends Object implements ResponseProcessor
Response processor that serializes RFC 7807 / 9457 Problem payloads as application/problem+json.

Fires when the response content is one of the following (in order):

  • A Problem bean — serialized directly. Honors the client Accept header.
  • A ProblemException — unwrapped via ProblemException.getProblem(). Honors the client Accept header.
  • A BasicHttpException — adapted via a registered ProblemMapper (if any matches), else via ProblemAdapters.fromException(BasicHttpException). This branch handles the common throw path where the operation handler throws a BasicHttpException and the framework sets it as the response content. Gated by isProblemDetails() on the RestOpContext (per-op @RestGet(problemDetails) / @RestPost(problemDetails) / etc., falling back to the resource-level @Rest(problemDetails) opt-in via tri-state inheritance). When opted-in, the Accept header is ignored on this branch (errors always emit application/problem+json; see RFC 7807).
  • Any other Throwable — only when an explicit ProblemMapper matches its class hierarchy. Gated by the same opt-in. Mappers that return null are skipped and the chain continues; if no mapper matches, the processor returns NEXT.
Mapper discovery

The processor pulls registered ProblemMappers from the resource's bean store in this order:

  • A ProblemMapperList bean — treated as the authoritative ordered registry. Recommended when more than one mapper is registered, since the underlying @Bean bean-store walk pairs each factory method with its return type and so collapses multiple @Bean public ProblemMapper foo() entries on the same resource into a single slot.
  • A single ProblemMapper bean (via BeanStore.getBean(ProblemMapper.class)) — the conventional single-mapper registration pattern.

For a given thrown exception the processor walks the collected mappers and picks the one whose ProblemMapper.getExceptionType() sits closest to the thrown class in the hierarchy (most-specific wins; ties broken by registration order). The chosen mapper's ProblemMapper.map(Throwable) return value replaces the default adaptation; a null return falls through to the next-most-specific mapper, and ultimately to the built-in ProblemAdapters.fromException(BasicHttpException) fallback for BasicHttpException subclasses.

Localization seam

Before serializing, the processor consults the bean store for a ProblemLocalizationStrategy bean and passes the resolved Problem (and RestRequest.getLocale()) through it. The default behavior is ProblemLocalizationStrategy.IDENTITY (pass-through) — this is a future-work seam intentionally shipped without a built-in Messages/resource-bundle implementation. A null strategy return is treated as "no opinion" and the pre-localization Problem is used instead.

Status code policy. When Problem.getStatus() is non-null, the processor calls RestResponse.setStatus(int) with that value. Otherwise it leaves the existing status alone — RestSession.run() normalizes 0 to 200 so per-op default codes (e.g. @RestPost default of 200) still flow through.

type field policy. Serialized as-is. A null type is omitted from the JSON output rather than synthesized as "type":"about:blank" on the wire (preserves the absent-vs-explicit distinction).

See Also:
  • Constructor Details

  • Method Details

    • process

      public int process(RestOpSession opSession) throws IOException
      Description copied from interface: ResponseProcessor
      Process this response if possible.
      Specified by:
      process in interface ResponseProcessor
      Parameters:
      opSession - The HTTP call.
      Returns:
      One of the following codes:
      • 0 - The processor could not handle the request.
      • 1 - The processor was able to fully handle the request.
      • 2 - The processor was able to partially handle the request by replacing the output. The response processors should start over.
      Throws:
      IOException - If low-level exception occurred on output stream.
      Results in a HttpServletResponse.SC_INTERNAL_SERVER_ERROR error.