1

I use AspectJ for logging controller and service class. I need to pass @RequestBody field to my advice method, but I can not find the right way. There are some solutions but none of them works for me.

How to log request body using spring boot and aspect

How can I hook into Spring's @RequestBody argument resolving to resolve my own argument using the body of the request

Here is my REST controller:

public ResponseEntity<Employee> add(@RequestBody Employee body) {
  //do something
}

Employee class:

@Setter
@Getter
@AllArgsConstructor
@NoArgsConstructor
public class Employee {
  public Integer id;
  public String name;
}

My aspect:

@Before(value = "execution(* ir.co.example.controllers.EmployeeController.*(..))")
public void beforeAdvice(JoinPoint joinPoint) {
  //do logging
}

I tried to get @RequestBody as args() in @Before, for example:

@Before(value = "execution(* ir.co.example.controllers.EmployeeController.*(..)) && args(body)")
public void beforeAdvice(JoinPoint joinPoint, Employee body) {
  System.out.println("User whit id = {} enter ", body.getId());
}

but beforeAdvice() method does not call before my controller class.

I also tried this approach:

@Before(value = "execution(* ir.co.example.controllers.EmployeeController.*(..))")
public void beforeAdvice(JoinPoint joinPoint) {
  HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
  //do logging
}

But in this solution I can not retrieve body. (I need Employee.)

How can I solve this problem?

kriegaex
  • 63,017
  • 15
  • 111
  • 202
mahdieh
  • 156
  • 3
  • 13
  • Don't just say "I tried and it does not work" or mention multiple solutions which do not work for you without proof. Please publish what you tried and explain your problems. And please, don't just publish small code snippets but a full [MCVE](https://stackoverflow.com/help/mcve), so I can reproduce your problem. – kriegaex Jul 21 '20 at 07:20
  • I edit question.I hope it will help.Thanks @kriegaex – mahdieh Jul 21 '20 at 10:59
  • This is still an incoherent set of snippets and not an [MCVE](https://stackoverflow.com/help/mcve). I cannot just copy, compile and run it. Anyway, does the simple aspect version work (without trying to get the request body)? You did not mention that. I need to know first before we go on, because I want to make sure that Spring AOP configuration itself or trying to intercept methods in non-Spring components are not the problem. – kriegaex Jul 22 '20 at 00:52
  • yes simple aspect without request body works fine @kriegaex – mahdieh Jul 22 '20 at 04:59
  • This is kind of hard to believe because if the same aspect without `args()` intercepts the `ResponseEntity add(@RequestBody Employee body)` method, it should also work with `args()`, the pointcut & advice look okay. There must be something else I don't see here, so I am asking for the 3rd and last time: Where is your MCVE? Ideally, push it to GitHub, so I can clone the repository, build and verify your project (or a simplified version of it, just enough to reproduce the problem). – kriegaex Jul 22 '20 at 05:31

1 Answers1

4

You can solve it like this:

@SneakyThrows
@Around("metrics() && args(.., @RequestBody body)")
public Object around(final ProceedingJoinPoint joinPoint, final Object body) {
  startUp();

  final HttpServletRequest request =
    ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();

  data.put("host", request.getRemoteHost());
  data.put("request-method", request.getMethod());
  data.put("request-uri", request.getRequestURI());
  data.put("request-query_params", request.getQueryString());
  data.put("request-headers", getRequestHeaders(request));
  data.put("method-name", joinPoint.getSignature().getName());

  if (!request.getMethod().equals(GET) && body != null) {
    data.put("request-body", objectMapper.writeValueAsString(body));
  }

  return joinPoint.proceed();
}
dos4dev
  • 429
  • 2
  • 10
  • 26