ahor ahor - 15 days ago 9
reST (reStructuredText) Question

How to log request payload when using Camel Rest?

I'd like to log the original 'raw' request body (e.g. JSON) while using Camel Rest endpoints. What's the proper way to do this?

My setup (RouteBuilder) looks like this:

restConfiguration().component("jetty")
.host(this.host)
.port(this.port)
.contextPath(this.contextPath)
.bindingMode(RestBindingMode.json);

rest("myService/").post()
.produces("application/json; charset=UTF-8")
.type(MyServiceRequest.class)
.outType(MyServiceResponse.class)
.to(SERVICE_CONTEXT_IN);

from(SERVICE_CONTEXT_IN).process(this.serviceProcessor);


My problem here is that the mechanics such as storing the request as an Exchange property are 'too late' in terms of using this approach, any processors are too late in the route, i.e., the binding already took place and consumed the Request. Also the CamelHttpServletRequest's InputStream has already been read and contains no data.

The first place to use the log EIP is directly before the single processor:

from(SERVICE_CONTEXT_IN).log(LoggingLevel.INFO, "Request: ${in.body}")
.process(this.serviceProcessor);


but at that point the
${in.body}
is already an instance of
MyServiceRequest
. The added log above simply yields
Request: x.y.z.MyServiceRequest@12345678
. What I'd like to log is the original JSON prior to being bound to a POJO.

There seems to be no built-in way of enabling logging of the 'raw' request in RestConfigurationDefinition nor RestDefinition.

I could get rid of the automatic JSON binding and manually read the HTTP Post request's InputStream, log and perform manual unmarshalling etc. in a dedicated processor but I would like to keep the built-in binding.

Answer

In the end I 'solved' this by not using the REST DSL binding with a highly sophisticated processor for logging the payload:

restConfiguration().component("jetty")
  .host(this.host)
  .port(this.port)
  .contextPath(this.contextPath);

rest("myService/").post()
  .produces("application/json; charset=UTF-8")
  .to(SERVICE_CONTEXT_IN);

from(SERVICE_CONTEXT_IN).process(this.requestLogProcessor)
  .unmarshal()
  .json(JsonLibrary.Jackson, MyServiceRequest.class)
  .process(this.serviceProcessor)
  .marshal()
  .json(JsonLibrary.Jackson);

All the requestLogProcessor does is to read the in body as InputStream, get and log the String, and eventually pass it on.

Comments