Spring ‐ Aspect‐Oriented Programming (AOP) - Yash-777/MyWorld GitHub Wiki

Enabling @AspectJ Support with Java configuration

To enable @AspectJ support with Java @Configuration add the @EnableAspectJAutoProxy annotation:

@Configuration
@EnableAspectJAutoProxy
public class AppConfig {

}

RequestLoggingAspect
package com.github.myworld.aspects;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.annotation.Annotation;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

@Aspect
@Component
@org.springframework.context.annotation.EnableAspectJAutoProxy
public class RequestLoggingAspect {
// @Around("@annotation(org.springframework.web.bind.annotation.RequestMapping) " + //@RequestMapping(method = RequestMethod.GET)
// "|| @annotation(org.springframework.web.bind.annotation.GetMapping)" +
// "|| @annotation(org.springframework.web.bind.annotation.PostMapping)" +  // @PostMapping(value = "")
// "|| @annotation(org.springframework.web.bind.annotation.PathVariable)" +
// "|| @annotation(org.springframework.web.bind.annotation.PutMapping)" +
// "|| @annotation(org.springframework.web.bind.annotation.DeleteMapping)"
// )
    @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping) " +
            "|| @annotation(org.springframework.web.bind.annotation.GetMapping) " +
            "|| @annotation(org.springframework.web.bind.annotation.PostMapping) " +
            "|| @annotation(org.springframework.web.bind.annotation.PathVariable) " +
            "|| @annotation(org.springframework.web.bind.annotation.PutMapping) " +
            "|| @annotation(org.springframework.web.bind.annotation.DeleteMapping)")
    public void requestMapping() {
    }
    
    @Around("requestMapping()")
    public Object logRequest(ProceedingJoinPoint joinPoint) throws Throwable {
        org.aspectj.lang.reflect.MethodSignature signature = (org.aspectj.lang.reflect.MethodSignature) joinPoint.getSignature();
        System.out.println("MethodSignature:"+ signature );
        
        long startTime = System.currentTimeMillis();

        // Log request details before method execution
        logRequestDetails(joinPoint);

        logDetails(joinPoint);
        
        // Proceed with the original method execution
        Object result = joinPoint.proceed();

        // Log response details after method execution
        long endTime = System.currentTimeMillis();
        logResponseDetails(result, endTime - startTime);

        return result;
    }
    
    public void printRequestMappingParam(org.springframework.web.bind.annotation.RequestMapping requestParam) {
        //org.springframework.web.bind.annotation.RequestMapping requestParam = AnnotationUtils.findAnnotation(method, org.springframework.web.bind.annotation.RequestMapping.class);
        if (requestParam != null) {// @RequestParam
            
            String nameOfMapping = requestParam.name();
            if (nameOfMapping != null && nameOfMapping.length() > 0) {
                System.out.println("nameOfMapping:"+nameOfMapping);
            }
            
            String[] headers = requestParam.headers();
            for (String header : headers) {
                System.out.println("Header:"+header);
            }
            String[] produces = requestParam.produces();
            for (String produce : produces) {
                System.out.println("produces:"+produce);
            }
            String[] consumes = requestParam.consumes();
            for (String consume : consumes) {
                System.out.println("Consumes:"+consume);
            }
            
            RequestMethod[] requestedMethod = requestParam.method();
            for (RequestMethod requestedMeth : requestedMethod) {
                System.out.println("RequestMethod:"+requestedMeth);
            }
            String[] params = requestParam.params();
            for (String param : params) {
                System.out.println("Param:"+param);
            }
            String[] values = requestParam.value();
            for (String value : values) {
                System.out.println("values:"+value);
            }
        }
    }
    
    public Object forwordReq(ProceedingJoinPoint joinPoint) throws Throwable {
        //long startTime = System.currentTimeMillis();
        org.springframework.util.StopWatch sw = new org.springframework.util.StopWatch();
        sw.start("logExecutionTime:");
        
        Object result = joinPoint.proceed();
        
        sw.stop();
        long timeTaken = sw.getTaskInfo()[0].getTimeMillis(); //endTime = System.currentTimeMillis() - startTime;
        System.out.println("Timetaken in MilliSec:"+timeTaken);
        return result;
    }

    public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
        // Access the HttpServletRequest
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
//        log.info("Request received: Method={}, Headers={}, QueryParams={}, PathVariables={}, RequestBody={}",
//                 request.getMethod(), request.getHeaderNames(), request.getParameterMap(),
//                 pathVariables, requestObject);
        // Extract request details (headers, parameters, path variables, request body)
        // Convert request body to JSON (if applicable)
        // Log the details
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            System.out.println(headerNames.nextElement());
        }

        org.aspectj.lang.reflect.MethodSignature signature = (org.aspectj.lang.reflect.MethodSignature) joinPoint.getSignature();
        System.out.println("MethodSignature:"+ signature );
        java.lang.reflect.Method method = signature.getMethod();
        
        // HttpComponentsClientHttpRequestFactory - method.getClass()
        // AnnotationFilter JAVA_LANG_ANNOTATION_FILTER = AnnotationFilter.packages("java.lang.annotation")
        
        //@org.springframework.web.bind.annotation.RequestMapping(path=[], headers=[], method=[GET], name=, produces=[], params=[], value=[compensation/ratecard/{planId}], consumes=[])
        Annotation[] declaredAnnotations = method.getDeclaredAnnotations();
        //Annotation[] annotations = method.getAnnotations();
        for (Annotation annotation : declaredAnnotations) {
            System.out.println("annotation:"+annotation.toString());
            //@org.springframework.security.access.prepost.PreAuthorize(value=)
            if (annotation instanceof org.springframework.web.bind.annotation.PathVariable) {// @PathVariable
                org.springframework.web.bind.annotation.PathVariable pathVar = (PathVariable) annotation;
                //org.springframework.web.bind.annotation.PathVariable pathVariable = AnnotationUtils.findAnnotation(method, org.springframework.web.bind.annotation.PathVariable.class);
                System.out.println("Annotation - PathVariable - name:val = " + pathVar.name() + " : " + pathVar.value());
            }
            //Key: interface org.springframework.web.bind.annotation.RequestMapping
            //Value: @org.springframework.web.bind.annotation.RequestMapping(path=[], headers=[], method=[POST], name=, produces=[], params=[], value=[organizationalUnit], consumes=[])
            if (annotation instanceof org.springframework.web.bind.annotation.RequestParam) { // @javax.ws.rs.QueryParam
                org.springframework.web.bind.annotation.RequestParam requestPar = (RequestParam) annotation;
                System.out.println("Annotation - RequestParam - name:val = " + requestPar.name() + " : " + requestPar.value());
            }
            if (annotation instanceof org.springframework.web.bind.annotation.RequestMapping) { // @javax.ws.rs.QueryParam
                org.springframework.web.bind.annotation.RequestMapping requestParam = (RequestMapping) annotation;
                //org.springframework.web.bind.annotation.RequestMapping requestParam = AnnotationUtils.findAnnotation(method, org.springframework.web.bind.annotation.RequestMapping.class);
                System.out.println("Annotation - RequestMapping - name:val = " + requestParam.name() + " : " + requestParam.value());
                printRequestMappingParam(requestParam);
            }
        }
        
        Object result = forwordReq(joinPoint);
        return result;
    }
    public void logDetails(ProceedingJoinPoint joinPoint) throws Throwable {
        // Access the HttpServletRequest
System.out.println("----- logDetails -----");
        org.aspectj.lang.reflect.MethodSignature signature = (org.aspectj.lang.reflect.MethodSignature) joinPoint.getSignature();
        //System.out.println("MethodSignature:"+ signature );
        java.lang.reflect.Method method = signature.getMethod();
        
        // HttpComponentsClientHttpRequestFactory - method.getClass()
        // AnnotationFilter JAVA_LANG_ANNOTATION_FILTER = AnnotationFilter.packages("java.lang.annotation")
        
        //@org.springframework.web.bind.annotation.RequestMapping(path=[], headers=[], method=[GET], name=, produces=[], params=[], value=[compensation/ratecard/{planId}], consumes=[])
        Annotation[] declaredAnnotations = method.getDeclaredAnnotations();
        for (Annotation annotation : declaredAnnotations) {
            System.out.println("Method DeclaredAnnotations:"+annotation.toString());
            //@org.springframework.security.access.prepost.PreAuthorize(value=hasPermission('/commissionrun/view', 'Feature Access'))
            //@org.springframework.web.bind.annotation.RequestMapping(path=[], headers=[], method=[GET], name=, produces=[], params=[], value=[commissionrundetails/{periodName}], consumes=[])
            
            if (annotation instanceof org.springframework.web.bind.annotation.RequestMapping) { 
                org.springframework.web.bind.annotation.RequestMapping requestParam = (RequestMapping) annotation;
                //org.springframework.web.bind.annotation.RequestMapping requestParam = AnnotationUtils.findAnnotation(method, org.springframework.web.bind.annotation.RequestMapping.class);
                System.out.println("Annotation - RequestMapping - name:val = " + requestParam.name() + " : " + requestParam.value());
                printRequestMappingParam(requestParam);
            }
        }
        
/*
 * it's important to note that @QueryParam is not a Spring annotation; it's typically used in JAX-RS (Java API for RESTful Web Services).
 * In Spring, query parameters are usually handled using @RequestParam. Below is an example of a Spring Rest API method that accepts 
 * @PathVariable, @RequestParam, and a query parameter (assuming it as @RequestParam): // @javax.ws.rs.QueryParam
 */
        Annotation[] annotationsOnMethod = method.getAnnotations();
        for (Annotation annotation : annotationsOnMethod) {
            System.out.println("Method annotationsOnMethod:"+annotation.toString());
        }
//        if (annotation instanceof org.springframework.web.bind.annotation.PathVariable) {// @PathVariable
//            org.springframework.web.bind.annotation.PathVariable pathVar = (PathVariable) annotation;
//            //org.springframework.web.bind.annotation.PathVariable pathVariable = AnnotationUtils.findAnnotation(method, org.springframework.web.bind.annotation.PathVariable.class);
//            System.out.println("Annotation - PathVariable - name:val = " + pathVar.name() + " : " + pathVar.value());
//        }
//        //Key: interface org.springframework.web.bind.annotation.RequestMapping
//        //Value: @org.springframework.web.bind.annotation.RequestMapping(path=[], headers=[], method=[POST], name=, produces=[], params=[], value=[organizationalUnit], consumes=[])
//        if (annotation instanceof org.springframework.web.bind.annotation.RequestParam) { // @javax.ws.rs.QueryParam
//            org.springframework.web.bind.annotation.RequestParam requestPar = (RequestParam) annotation;
//            System.out.println("Annotation - RequestParam - name:val = " + requestPar.name() + " : " + requestPar.value());
//        }
System.out.println("----- logDetails -----");
    }



    private void logRequestDetails(ProceedingJoinPoint joinPoint) throws IOException {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes != null) {
            HttpServletRequest request = attributes.getRequest();

            // Log request method, URI, headers, query parameters, and request body
            System.out.println("Request Method: " + request.getMethod());
            System.out.println("Request URI: " + request.getRequestURI());
            System.out.println("Request Headers: " + getRequestHeaders(request));
            
            System.out.println("Query String: " + request.getQueryString()); // regionCode=TMPL
            System.out.println("Query Parameters: " + getRequestParameters(request)); // {regionCode=[TMPL]} = /commissionrundetails/202310?regionCode=TMPL
           
            // Log request body in JSON format
            if (request.getInputStream() != null) {
                // Handle the HttpServletRequest
                
                ServletInputStream inputStream = request.getInputStream();
                InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
                BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
                Stream<String> lines = bufferedReader.lines();
                Optional<String> reduce = lines.reduce(String::concat);
                if (reduce.isPresent()) { // NoSuchElementException: No value present at java.util.Optional.get(Optional.java:135)
                    String requestBody = reduce.get();
                    System.out.println("HttpServletRequest Body String: " + requestBody );
                    try {
                        ObjectMapper objectMapper = new ObjectMapper();
                        JsonNode requestBodyJson = objectMapper.valueToTree(requestBody);
                        System.out.println("HttpServletRequest Body JSON Node: " + requestBodyJson);
                    } catch (Exception e) {
                        System.err.println("Error parsing request body: " + e.getMessage());
                    }
                }
            }
        }
    }

    private void logResponseDetails(Object result, long executionTime) {
        // Log response details
        System.out.println("Response: " + result);
        System.out.println("Execution Time: " + executionTime + " ms");
    }

    private Map<String, String> getRequestHeaders(HttpServletRequest request) {
        return Collections.list(request.getHeaderNames())
                .stream()
                .collect(Collectors.toMap(name -> name, request::getHeader));
    }

    private Map<Object, Object> getRequestParameters(HttpServletRequest request) {
        return request.getParameterMap()
                .entrySet()
                .stream()
                .collect(Collectors.toMap(Map.Entry::getKey, entry -> Arrays.toString(entry.getValue())));
    }
}

⚠️ **GitHub.com Fallback** ⚠️