Skip to main content

Response Processors

The REST Server API uses the concept of registered response processors for converting objects returned by REST methods or set through RestResponse.setContent(Object) into appropriate HTTP responses. By default, REST resource classes are registered with the following response processors:

AsyncResponseProcessorReaderProcessorInputStreamProcessorThrowableProcessorProblemDetailsProcessorHttpResponseProcessorHttpResourceProcessorHttpBodyProcessorResponseBeanProcessorPlainTextPojoProcessorSerializedPojoProcessor

Custom response processors can be associated with REST resources via the following:

RestresponseProcessors

Response processors can be used to process POJOs that cannot normally be handled through Juneau serializers, or because it's simply easier to define response processors for special cases.

The following example shows how to create a response processor to handle special Foo objects outside the normal Juneau architecture.

@Rest(responseProcessors=FooProcessor.class)
public class MyResource {

@RestGet("/getFoo")
public Foo getFoo() {
return new Foo("Some value");
}

public static class FooProcessor implements ResponseProcessor {
@Override
public int process(RestOpContext opContext, RestRequest req, RestResponse res) {
Object output = res.getContent(Object.class);
if (output instanceof Foo) {
try {
Foo foo = (Foo)output;
// Set some headers.
res.setHeader("Foo-ID", foo.getId());
// Set the real content.
res.setContent("Special handling for Foo object: " + foo.getValue());
} catch (Exception e) {
throw new InternalServerError(e);
}
return FINISHED; // We handled it.
}
return CONTINUE; // Let next processor handle it.
}
}
}

Renderer ordering​

View renderers — processors implementing ViewRenderer — are automatically repositioned to run before the catch-all serializer (SerializedPojoProcessor, which implements CatchAllResponseProcessor) during ResponseProcessorList construction. This means a @RestOp method returning a typed View subtype (JspView, ThymeleafView, MustacheView, FreemarkerView) reaches the corresponding renderer without any explicit ordering annotation or chain enumeration.

Third-party view renderers gain the same guarantee by implementing ViewRenderer.

@Rest(path="/app", mixins=JspMixin.class)
public class AppResource extends RestServlet {

@RestGet("/hello/{name}")
public View hello(@Path String name) {
return JspView.of("hello.jsp").attr("name", name);
}
}
// GET /app/hello/Bob → rendered hello.jsp (not a bean-HTML dump of JspView)

The auto-prepend invariant applies even when the user provides an explicit @Rest(responseProcessors=...) list — any ViewRenderer in a custom list is still ordered before any CatchAllResponseProcessor in that list.