SerDesMiddleware implements Middleware<HttpRequest, HttpResponse, HttpRequest, NRES> { @Override public HttpResponse handle(HttpRequest request, MiddlewareChain<HttpRequest, NRES, ?, ?> chain) { request = MixinUtils.mixin(request, BodyDeserializable.class); MediaType responseType = ((ContentNegotiable) request).getMediaType(); try { handleRequest(request); } catch (IOException e) { return builder(HttpResponse.of(serialize(Parameters.of("title", "bad request format"), responseType))) .set(HttpResponse::setStatus, 400) .build(); } NRES response = chain.next(request); if (response instanceof HttpResponse) { return (HttpResponse) response; } else { InputStream in = serialize(extractBody(response), responseType); if (in != null) { return builder(HttpResponse.of(in)) .set(HttpResponse::setHeaders, extractHeaders(response, responseType)) .set(HttpResponse::setStatus, extractStatus(response)) .build(); } else { return builder(HttpResponse.of("Not acceptable")) .set(HttpResponse::setStatus, 406) .build(); } } }  void handleRequest(HttpRequest request); @Override HttpResponse handle(HttpRequest request, MiddlewareChain<HttpRequest, NRES, ?, ?> chain); void setBodyReaders(MessageBodyReader<?>... readers); void setBodyWriters(MessageBodyWriter<?>... writers); void setParameterInjectors(List<ParameterInjector<?>> parameterInjectors);  }
@Test public void controller() throws IOException { SerDesMiddleware<Object> middleware = builder(new SerDesMiddleware<>()) .set(SerDesMiddleware::setBodyReaders, jsonProvider) .set(SerDesMiddleware::setBodyWriters, jsonProvider) .set(SerDesMiddleware::setParameterInjectors, ParameterUtils.getDefaultParameterInjectors()) .build(); String body = "[{\"a\":1, \"b\":\"ccb\"}, {\"a\":2, \"b\":\"ooo\"}]"; HttpRequest request = MixinUtils.mixin(builder(new DefaultHttpRequest()) .set(HttpRequest::setHeaders, Headers.of("Content-Type", "application/json")) .set(HttpRequest::setBody, new ByteArrayInputStream(body.getBytes())) .build(), Routable.class, ContentNegotiable.class, BodyDeserializable.class); ContentNegotiable.class.cast(request).setMediaType(new MediaType("application", "json")); TestController controller = new TestController(); MiddlewareChain<HttpRequest, Object, ?, ?> chain = new DefaultMiddlewareChain<>(new AnyPredicate<>(), null, (Endpoint<HttpRequest, Object>) req -> tryReflection(() -> { List<TestDto> obj = BodyDeserializable.class.cast(req).getDeserializedBody(); return Routable.class.cast(req).getControllerMethod().invoke(controller, obj); })); HttpResponse resp = tryReflection(() -> { Method fooMethod = TestController.class.getMethod("foo", List.class); Routable.class.cast(request).setControllerMethod(fooMethod); return middleware.handle(request, chain); }); ObjectMapper mapper = new ObjectMapper(); Map<String, Object> res = mapper.readValue(resp.getBodyAsStream(), new TypeReference<Map<String, Object>>(){}); assertThat(res).containsEntry("a", 1); assertThat(res).containsEntry("b", "ccb"); }