Here is my controller class for GetMapping and PostMapping
public class Controller{
@CrossOrigin(origins = "*")
@PostMapping(value = "/tran", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Map<String,Object>> createTransaction(@RequestHeader(required = false,name="request-id") String requestId,
@RequestHeader(required = false,name="request-datetime") String requestDate,
@RequestHeader(required = false,name= "request-channel") String requestChannel,
@RequestBody TransactionRequestEntity createTransactionRequest,
HttpServletRequest req) throws Exception {
///// Some Code /////
}
@CrossOrigin(origins = "*")
@GetMapping(value = "/getTran", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Map<String,Object>> getByTransactionId(@RequestHeader(required = false,name="request-id") String requestId,
@RequestHeader(required = false,name="request-datetime") String requestDate,
@RequestHeader(required = false,name= "request-channel") String requestChannel,
@RequestParam(name="transactionId") String transactionId,
@RequestParam(name="transactionSource") TransactionSourceEnum transactionSource,
HttpServletRequest req) throws Exception {
///// Some Code /////
}
}
Here is the LoggingAspect class for above PostMapping and GetMapping
public class LoggingAspect {
private static final ch.qos.logback.classic.Logger LOGGER = LoggingUtils.getLogger(LoggingAspect.class.getName());
@Around("@annotation(org.springframework.web.bind.annotation.PostMapping) && args(.., @RequestHeader header1,@RequestHeader header2,@RequestHeader header3, @RequestBody body, request)")
public Object logPostMethod(ProceedingJoinPoint joinPoint, String header1,String header2,String header3, Object body, HttpServletRequest request) throws Throwable {
LOGGER.info("Start {} {} : Request Id : {} : Request DateTime: {}: Request Channel : {} ", request.getMethod(), request.getRequestURI(), header1,header2,header3);
ObjectMapper mapper = new ObjectMapper();
String jsonString = mapper.writeValueAsString(body);
LOGGER.debug("{} {} : Request Body : {}", request.getMethod(), request.getRequestURI(), jsonString);
Object result;
result = joinPoint.proceed();
LOGGER.debug("End {} {} : Response: {}", request.getMethod(), request.getRequestURI(), result);
String response = mapper.writeValueAsString(result);
JSONParser parser = new JSONParser();
JSONObject responseHeader = (JSONObject) ((JSONObject) ((JSONObject) parser.parse(response)).get("body")).get("responseHeader");
LOGGER.info("End {} {} : Response Header : {}", request.getMethod(), request.getRequestURI(), responseHeader);
return result;
}
@Around("@annotation(org.springframework.web.bind.annotation.GetMapping) && args(.., @RequestHeader header1,@RequestHeader header2,@RequestHeader header3, @RequestParam param1,@RequestParam param2 , request)")
public Object logGetMethod(ProceedingJoinPoint joinPoint, String header1, String header2, String header3 ,String param1, TransactionSourceEnum param2 , HttpServletRequest request) throws Throwable {
LOGGER.info("Start {} {} : Request Id : {} :Request DateTime : {} :Request Channel : {} : Request Transaction Id : {} : Transaction Source : {} ", request.getMethod(), request.getRequestURI(), header1,header2,header3,param1,param2);
ObjectMapper mapper = new ObjectMapper();
Object result;
result = joinPoint.proceed();
LOGGER.debug("End {} {} : Response: {}", request.getMethod(), request.getRequestURI(), result);
String response = mapper.writeValueAsString(result);
JSONParser parser = new JSONParser();
JSONObject responseHeader = (JSONObject) ((JSONObject) ((JSONObject) parser.parse(response)).get("body")).get("responseHeader");
LOGGER.info("End {} {} : Response Header : {}", request.getMethod(), request.getRequestURI(), responseHeader);
return result;
}
}
The code run without any issue....But there are duplicate line. I want to remove that's duplicates. So how to write common method for above GetMapping and PostMapping.
Why not just extract the common code into a helper method and call it from both advice methods? I did not test this because I didn't want to create a test project with Logback and Spring from scratch just to resolve the imports, but basically something like this:
@Around("@annotation(org.springframework.web.bind.annotation.PostMapping) && args(.., @RequestHeader header1,@RequestHeader header2,@RequestHeader header3, @RequestBody body, request)")
public Object logPostMethod(ProceedingJoinPoint joinPoint, String header1, String header2, String header3, Object body, HttpServletRequest request) throws Throwable {
LOGGER.info("Start {} {} : Request Id : {} : Request DateTime: {}: Request Channel : {} ", request.getMethod(), request.getRequestURI(), header1, header2, header3);
LOGGER.debug("{} {} : Request Body : {}", request.getMethod(), request.getRequestURI(), new ObjectMapper().writeValueAsString(body));
return proceedAndLogResult(joinPoint, request);
}
@Around("@annotation(org.springframework.web.bind.annotation.GetMapping) && args(.., @RequestHeader header1,@RequestHeader header2,@RequestHeader header3, @RequestParam param1,@RequestParam param2 , request)")
public Object logGetMethod(ProceedingJoinPoint joinPoint, String header1, String header2, String header3, String param1, TransactionSourceEnum param2, HttpServletRequest request) throws Throwable {
LOGGER.info("Start {} {} : Request Id : {} :Request DateTime : {} :Request Channel : {} : Request Transaction Id : {} : Transaction Source : {} ", request.getMethod(), request.getRequestURI(), header1, header2, header3, param1, param2);
return proceedAndLogResult(joinPoint, request);
}
public Object proceedAndLogResult(ProceedingJoinPoint joinPoint, HttpServletRequest request) {
Object result = joinPoint.proceed();
LOGGER.debug("End {} {} : Response: {}", request.getMethod(), request.getRequestURI(), result);
String response = new ObjectMapper().writeValueAsString(result);
JSONObject responseHeader = (JSONObject) ((JSONObject) ((JSONObject) new JSONParser().parse(response)).get("body")).get("responseHeader");
LOGGER.info("End {} {} : Response Header : {}", request.getMethod(), request.getRequestURI(), responseHeader);
return result;
}
Disclaimer:
I am not a Spring user and will not comment on whether or not it is efficient to get the objects to be logged in the way you do, others know better. I was just concentrating on the aspect refactoring part because you asked for it.
I am also not saying anything in detail about your coding style and the very specific pointcut signature which might break if you want to intercept methods with slightly different signatures.
One thing seems odd to me though and I want to mention it: You are logging things as "response" which are actually taken from the request
object. I am not sure you should do that. But it is unrelated to the refactoring problem as such.