1

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.

2 Answers 2

2

That's a lot of work you're doing.

Here's is what I do:

Declare an annotation:

@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Logged { } 

Declare your Aspect:

@Aspect @Configuration public class Logger { @Around("@annotation(fully.qualified.name.of.Logged)") public Object log(ProceedingJoinPoint joinPoint) { // get request object HttpServletRequest req = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()) .getRequest(); //do whatever you've to do with your req object //process further return someobject } 

You controller class:

public class Controller{ @Logged //<-- Just a single annotation at your controller. This can be applied on all other methods irrespective of HTTP methods @CrossOrigin(origins = "*") @PostMapping(value = "/tran", produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity<Map<String,Object>> createTransaction(...........) { } 
Sign up to request clarification or add additional context in comments.

1 Comment

That is not an answer to the question and also introduces an extra annotation to the code for each target joinpoint, scattering across the whole code base. I.e. you are polluting your application code with AOP-related annotations. An ideal aspect works without the application knowing about it. I am not saying that your approach is not okay, but IMO the OP's original approach is cleaner from an AOP perspective because the application is completely agnostic of the aspect.
1

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.

2 Comments

Thanks, actually this method remove that duplicate lines. But this is not a common method for logging
But this is exactly what you asked for! Quote: "there are duplicate line. I want to remove that's duplicates" If now suddenly your question focus changed, please accept my answer first (click the grey check mark beside the answer, making it green) and ask another question if now you want to know something else. This is how it works here on SO. You cannot just change the question after having received two different answers already.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.