I have a requirement wherein I need to save any request and response being passed to a Rest Controller in a database, so I decided to implement Spring AOP for the same. The issue that is now being encountered is I couldn't get hold of any of the request body. Request body is being retrieved as an empty string. My Rest Controllers are all wrapped inside a Base Object and AOP only detects the outer Base class.
My Base Class :
public class BaseObject<T> {
private T data;
}
My controller methods have definition like this :
@PostMapping("/student")
public BaseObject<StudentResponse> saveStudent(@RequestBody BaseObject<StudentRequest> studentRequest) {
What I have tried till now :
private void saveRequestInDatabase(ProceedingJoinPoint joinPoint, long time) {
System.out.println("****************Inside saveRequestInDatabase method*****************");
System.out.println(Thread.currentThread().getName());
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
DataBaseRequest dataBaseRequest = new DataBaseRequest();
String className = joinPoint.getTarget().getClass().getName();
String methodName = signature.getName();
dataBaseRequest.setMethod(className + "." + methodName + "()"); // class name and method name retrieved fine
Object[] args = joinPoint.getArgs();
System.out.println("Object Arguments :- " +joinPoint.getArgs()); // only has the Outer BaseObject, the data inside it is null
LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
String[] paramNames = u.getParameterNames(method);
System.out.println("Param Names :- "+paramNames);
if (args != null && paramNames != null) {
String params = "";
for (int i = 0; i < args.length; i++) {
params += " " + paramNames[i] + ": " + args[i]; // ***paramNames[] has the studentRequest variable name***
// ***args[] has the outer BaseObject but the data inside it, is null***
}
dataBaseRequest.setParams(params);
}
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
ContentCachingRequestWrapper req = new ContentCachingRequestWrapper(request);
byte[] requestBody = req.getContentAsByteArray();
String reqBodyStr = new String(requestBody, StandardCharsets.UTF_8);
JsonObject jsonObject = new JsonObject();
String reqBody = null;
try {
reqBody = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
} catch (IOException e) {
e.printStackTrace();
}
jsonObject.addProperty("requestBody", reqBody); // ***requestBody is "" when being executed***
jsonObject.addProperty("reqBody", reqBodyStr); // ***reqBody is "" when being executed***
dataBaseRequest.setEndPoint(request.getServletPath()); // This is fetched fine
dataBaseRequest.setOperation(request.getMethod()); // fetched fine
dataBaseRequestService.saveRequest(dataBaseRequest);// saved inside database but the column to store reqObject has {data:null}
System.out.println("((((((((((((((((Done saving request)))))))))))))))))))))");
}
I have also tried this :
@Before("execution(your.package.where.is.endpoint.*.*(..)) && args(reqArgs)")
Even here, reqArgs = {BaseObject@21216}, data = null
.
The only place I could see my request body is: Inside the HttpServletRequest
request object, there is an attribute named
CachedContent = {ByteArrayOutputStream@13221}
which has my JSON request object that is being passed from Postman, i.e, all the attributes of StudentRequest
object, but I don't know how to grab hold of the same.
Please let me know how can I get the request objects (StudentObject
) and response objects (StudentResponse
) when it is wrapped around the BaseObject
.
Thanks!