1

I have a simple resource , it return a Uni < Response >

@POST
@Path("/test2")
public Uni<Response> test2(SampleEntity test) {
    List<SampleEntity> recordList = new ArrayList<>();
    recordList.add(new SampleEntity("cat", 12));
    recordList.add(new SampleEntity("dog", 14));
    return Uni.createFrom().item(Response.ok(recordList).build());
}

and I have a sample Interceptor, Used to log the request/response as json

    @AroundInvoke
public Object resourceLog(InvocationContext context) throws Exception {
    timer.restart();
    log.info(StrUtil.format("request->[{}]", JSONUtil.toJsonStr(context.getParameters())));
    Object response = context.proceed();
    log.info(StrUtil.format("response->[{}]", response));
    return response;
}

When I send a json request :

{
"name": "cat",
"age": 12
}

The log printed out is :

2021-04-09 10:29:34,529 INFO  [cof.gei.int.ResourceInterceptor] (vert.x-eventloop-thread-4) request->[[{"name":"cat","age":12}]]
2021-04-09 10:29:34,529 INFO  [cof.gei.int.ResourceInterceptor] (vert.x-eventloop-thread-4) response->[io.smallrye.mutiny.operators.uni.builders.UniCreateFromKnownItem@a0122dd]

The question I want to ask is: How to print out the json content of a response when the interceptor intercepts a response that is a Uni< Response >

This is my current solution :

        Object response = context.proceed();
    if(response instanceof Uni uni) {
        uni.subscribe().with(body -> log.info(StrUtil.format("response->Uni:[{}]", JSONUtil.toJsonStr(body))));
    }else {
        log.info(StrUtil.format("response->[{}]", JSONUtil.toJsonStr(response)));
    }

But I think it's ugly.

jiayaoO3O
  • 53
  • 1
  • 5

1 Answers1

1

The best way to do this would be to not use a CDI interceptor, but a JAX-RS ContainerResponseFilter.

It would look something like:

@Provider
public class YourFilter implements ContainerResponseFilter {

    @Override
    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext)
            throws IOException {
        Object entity = responseContext.getEntity(); // this will contain the body of the response
        // print it
    }
}
geoand
  • 60,071
  • 24
  • 172
  • 190
  • When I print to context.proceed() in the interceptor, the log content is: `{"headers":{},"stringHeaders":{},"entity":[{"id":"cat","age":111},{"id":"dog","age":222}],"status":200}` When I print the responseContext.getEntity() in the filter, the contents of the log are: `{"id":"cat","age":111},{"id":"dog","age":222}` It seems that the object in the interceptor will have more information than the object in the filter – jiayaoO3O Apr 09 '21 at 07:07
  • The interceptor will have the whole `Response`, but is that really what you want? The `ContainerResponseContext` has the headers and response code if you need to print that information as well – geoand Apr 09 '21 at 08:22
  • I just want to simply print out the entire Response – jiayaoO3O Apr 10 '21 at 04:11
  • 1
    My point is that you don't really know what `Response` will print, so it's best to print what you need – geoand Apr 10 '21 at 05:55