0

I have a requirement to intercept the REST API responses for out application and do something with them. One very obvious approach to achieve this is to define an annotation and interceptor at method level (so that it can be applied to the REST API methods). However, I could not find a way to extract/intercept the response code for API responses. I am very new to Java EE world, so might be missing something here, but didn't find anything on internet search either. Our application is based on standard JavaEE with CXF.

I have seen some examples with code similar to the following, but not sure how I can get the API response from that. Any help would be appreciated.

@AroundInvoke
public Object around(InvocationContext context) throws Exception {......
V_Singh
  • 729
  • 11
  • 22

4 Answers4

3

Suppose you are using the standard JEE solution, from the doc

@AroundInvoke
public Object logInvocation(InvocationContext ctx) throws Exception {
   String class = ctx.getMethod().getDeclaringClass().getName();
   String method = ctx.getMethod().getName();
   Logger.global.entering(class, method, ctx.getParameters());
   try {
      Object result = ctx.proceed();
      Logger.global.exiting(class, method, result);
      return result;
   }
   catch (Exception e) {
      Logger.global.throwing(class, method, e);
      throw e;
   }

}

The Object result = ctx.proceed(); is the result for you.

Liping Huang
  • 4,378
  • 4
  • 29
  • 46
  • Yes, I think this will work as long as "result" has all the necessary response data. Will try it out and confirm. Thanks. – V_Singh Sep 30 '16 at 08:16
  • @V_Singh just see you updated the question, the standard cxf interceptor will also a choose. – Liping Huang Sep 30 '16 at 08:27
3

JAX-RS server filters

Use a ContainerResponseFilter from the JAX-RS API 2.0 to intercept responses or server side:

@Provider
public class CustomResponseFilter implements ContainerResponseFilter {

    @Override
    public void filter(ContainerRequestContext requestContext, 
                       ContainerResponseContext responseContext) throws IOException {

        // Intercept the HTTP response and get the status code
        int status = responseContext.getStatus()
    }
}

The JAX-RS 2.0 API also provide the ContainerRequestFilter to intercept requests:

@Provider
public class CustomRequestFilter implements ContainerRequestFilter {

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {

        // Intercept the HTTP request
    }
}

To bind the filters to resource classes and/or methods, use name binding annotations.

Registering server filters in Apache CXF

According to the Apache CXF documentation, the filters must be registered in the cxf.xml configuration file. This file must be in the classpath of your application.

Here's an example extracted from the documentation of what your CXF configuration file can be like when registering a filter:

<beans>
    <jaxrs:server id="customerService" address="/">

        <jaxrs:serviceBeans>
          <bean class="org.CustomerService" />
        </jaxrs:serviceBeans>

        <jaxrs:providers>
          <ref bean="authorizationFilter" />
        </jaxrs:providers>

        <bean id="authorizationFilter" class="com.bar.providers.AuthorizationFilter">
            <!-- authorization bean properties -->
        </bean>

    </jaxrs:server>
</beans>

For more details, check the CXF documentation about configuration.

Community
  • 1
  • 1
cassiomolin
  • 124,154
  • 35
  • 280
  • 359
1

Although interceptors are a great way to do cross-cutting concerns for your application services, you are talking about a web application here. You are not looking at intercepting service request, you are looking at intercepting http requests.

Web applications use the servlet spec, and for such generic stuff you'd use @Webfilters. These webfilters can get the entire request and response, including the status code, as they work on the transport level, and not on the application level.

Be mindful that the servlet spec is picky: you cannot easily read requests and responses without duplicating them, and it's a bit messy code. Google a bit for it (log http request, log http response) and you should find plenty of code to create a filter which can do that.

Koos Gadellaa
  • 1,220
  • 7
  • 17
  • 1
    Thanks. Would you say the ContainerRequestFilter and ContainerResponseFilter (as mentioned by Cassio) is similar to what you are saying and can be preferred as these are from standard jax-rs pack. – V_Singh Sep 30 '16 at 08:27
0

Hi you didn't mention what technology stack. If you needed something for client side you could use Spring and Spring's ClientHttpRequestInterceptor.

@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
    ClientHttpResponse response = execution.execute(request, body);
    /**
     * response.getStatusCode();
     */
    return response;
}
  • Can't use Spring, using standard JavaEE with CXF. But I think your approach will work if someone uses Spring. Thanks! – V_Singh Sep 30 '16 at 08:17