The previous design
I had a Spring controller built like follows:
@RequestMapping(value = "/rest/funf/{datatype}", method = RequestMethod.GET)
public ModelAndView getFunfData(@PathVariable("datatype") String dataType,
WebRequest request) throws HttpException {
I also had a HandlerInterceptorAdapter
that performed pre and post-processing (modifying the returned model according to a policy). The signature for the post-process handler is the following
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
It actually worked well. The REST API returned a not-well-structured JSON payload but at least the interceptor (a Policy Enforcement Point) was able to anonymise (strip user personal data) from the model and replaced it.
The point is that with the old design I was able to retrieve response before it was sent to the output, modify and reinject it into the ModelAndView
instance. No need to post code for brevity.
The new design
Now I discovered a new design that helps me overcome a flaw in the response structure.
When I had return new ModelAndView(jacksonView_instance, "data", dataToConvertToJson)
it was structured like
{
"data": {
"myAttr1":"myVal1"
}
}
which is bad when the receiving program wants to convert the payload to JSON. So I found
@RequestMapping(value = "/rest/funf/{datatype}", method = RequestMethod.GET, produces = { "application/json" })
public @ResponseBody
Object[] getFunfData(@PathVariable("datatype") String dataType,
WebRequest request) throws HttpException {
This simplified code a little and most importantly made the response well structured, like
{
"myAttr1":"myVal1"
}
That is perfectly OK with REST design contract, but
The problem
Now the HandlerInterceptor won't be able any more to retrieve the model and thus the object I return from my API (it's a FUNF-related API that handles personal data, even sensitive, recorded on mobile devices).
So if I need to anonymise records I can't do it in the interceptor like before
The workaround
I am conscious I can kill the interceptor and perform policy enforcement right in the API, but this is not a great design, even since the PEP that performs authorization in the preHandle
and obligation enforcement in the postHandle
is currently a Spring object automagically instantiated. Copying and pasting code in the API is a bad idea when dealing with multiple APIs and the possibility in the middle-term to change/extend the PEP implementation.
Anyway, let's formulate a straight question after having explained the context well
The question is
Given a generic Spring MVC API that returns an object to be handled by a content negotiator
@RequestMapping(value = "/path/{variable}", method = RequestMethod.GET)
public @ResponseBody Object api() {
how can I intercept that returned object in an external class to perform modifications to it? (e.g. replace with a new object instance to be returned to client)