We have built some REST (jax-rs) web services using Apache CXF. They return a JSON response.
I now need to modify some of the request parameters, and response content. (Basically we need to encode/encrypt some of the data that is returned by the service; and decode/decrypt the same data when it is used as a parameter in a subsequent service call.)
It seems I have at least 4 options here:
I've used Servlet Filters before, and understand exactly how to modify request params and response body, so I'm leaning toward that. However, I'm open to using a CXF Interceptor or JAX-RS filter if that is the more 'correct' way to solve this when using CXF. But based on the documentation, I don't really understand how to do this. For example, do I use the setContent method of the Message object to change the JSON response? What is the format parameter in that case, just String.class?
Answering my own question here ... I ended up using a JAX-RS filter, and it worked well, once I got past the lack of documentation. I used the (rather sparse) documentation from http://cxf.apache.org/docs/jax-rs-filters.html . Note despite it's name, a JAX-RS filter is a CXF-specific beast, not part of the JAX-RS standard (as far as I can tell).
Here is some example code:
@Context
private HttpServletRequest httpRequest;
@Context
private UriInfo uriInfo;
/**
* @see org.apache.cxf.jaxrs.ext.ResponseHandler#handleResponse(org.apache.cxf.message.Message, org.apache.cxf.jaxrs.model.OperationResourceInfo, javax.ws.rs.core.Response)
*/
public Response handleResponse(Message message, OperationResourceInfo opResourceInfo, Response response) {
try {
// log the injected context data; useful for debugging CXF problems
logContextData(httpRequest, uriInfo);
OutputStream os = message.getContent(OutputStream.class);
String relevantData = getDataFromRequest(httpRequest);
message.setContent(OutputStream.class, new MyOutputStreamWrapper(os, relevantData));
} catch (CustomException e) {
// return some status that is related to CustomException
return Response.status(Status.UNAUTHORIZED).build();
} catch (Exception e) {
return Response.status(Status.INTERNAL_SERVER_ERROR).build();
}
return response;
}
/**
* @see org.apache.cxf.jaxrs.ext.RequestHandler#handleRequest(org.apache.cxf.message.Message, org.apache.cxf.jaxrs.model.ClassResourceInfo)
*/
public Response handleRequest(Message message, ClassResourceInfo classResourceInfo) {
try {
// log the injected context data; useful for debugging CXF problems
logContextData();
String updatedQueryString = buildNewQueryString(this.uriInfo, httpRequest);
message.put(Message.QUERY_STRING, updatedQueryString);
// returning null tells CXF to continue the request (i.e. a non-null value would halt the request)
return null;
} catch (CustomException e) {
// return some status that is related to CustomException
return Response.status(Status.UNAUTHORIZED).build();
} catch (Exception e) {
return Response.status(Status.INTERNAL_SERVER_ERROR).build();
}
}
I should note that the implementation of MyOutputStreamWrapper is the important part in modifying the response content. I couldn't include that source here (in fact my implementation has a different name) due to security considerations.