3

In the process of developing our app, we found ourselves doing something like this in our controller:

@RequestMapping(value = "foo", method = RequestMethod.POST)
@ResponseBody
public SimpleMasterWidget doStuff(@RequestBody ClientData clientData, ServerData serverData) throws Exception
{
        pushClientDataToServerData(clientData, serverData);
        //stuff specific to this operation on the serverData
        return whatever;
}

The pushClientDataToServerData(clientData, serverData); call gets duplicated in every POST request. Now, I understand that there really shouldn't be any need to push clientData to serverData, but there is legacy code that forces us to do this.

Currently we are implementing the HandlerMethodArgumentResolver interface to resolve the ServerData argument. To remove all the duplicated pushClientDataToServerData calls I want to be able to resolve the ServerData argument with the ClientData already pushed into it.

Now in the argument resolver, I have access to the NativeWebRequest so I could probably get the request body through there and deserialize it and all that. However, I don't want to have to reimplement what Spring is already doing with the @RequestBody annotation.

So my question boils down to this: Is there a way I can call into Spring's stuff in the argument resolver so that I can get the deserialized ClientData object and call pushClientDataToServerData right within the argument resolver? Then all the controller methods would just look like this:

@RequestMapping(value = "foo", method = RequestMethod.POST)
@ResponseBody
public SimpleMasterWidget doStuff(ServerData serverData) throws Exception
{
        //stuff specific to this operation on the serverData
        return whatever;
}

And the pushClientDataToServerData call would be in only one place.

Thanks in advance.

dnc253
  • 39,967
  • 41
  • 141
  • 157

1 Answers1

0

Looks like a good candidate for Spring AOP. Below is just an example of pointcut, you should improve it to catch all possible methods:

@Component
@Aspect
public class PushClientDataAspect {

    @Before(value = "execution(* com.xyz.myapp.dao.*.*(..) && args(clientData, serverData) && @annotation(org.springframework.web.bind.annotation.ResponseBody))")
    public void pushClientData(ClientData clientData, ServerData serverData) {
        pushClientDataToServerData(clientData, serverData);
    }   

}
hoaz
  • 9,883
  • 4
  • 42
  • 53