How to write the Junit Mockito code for this Aspect class for maximum code coverage - spring-boot

Could someone please help me out in writing Junit for this piece of code and provide resources to learn the same. I have been trying to figure out from multiple resources but couldn't find anything. I need to mock the pointcuts and methods which are invoked within the pointcut. Is unit testing possible for this using Mockito
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import com.sample.api.rest.account.AccountResource;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.CustomLog;
import lombok.extern.slf4j.slf4j;
#Aspect
#CustomLog
public class sample {
ObjectMapper mapper = new ObjectMapper();
long startTimeController = 0L;
long endTimeController = 0L;
#Pointcut("within(com.sample.api.rest.account. .) || "
+ "within(com.sample.api.rest.metadata..') ")
public void entryController() {}
#Pointcut("within(com. sample.api.rest.user..*)")
public void entryControllerUser() {}
#Pointcut("within(com.sample.api.service. .*)")
public void entryService() {}
#Pointcut("within(com. sample.cmo.repositories..*)")
public void entryDAO() {}
#Before("entryController()")
public void beforeOtherControllerCall(JoinPoint jp) throws JsonProcessingException {
String methodName = jp.getSignature().getName();
String className = jp.getTarget().getClass().toString();
Object[] arguments = jp.getArgs();
log.info(className + " Method : " + methodName + " Arguments passed : " +
mapper.writeValueAsString(arguments));
startTimeController = System.currentTimeMillis();
}
#Before("entryControllerUser()")
public void beforeUserControllerCall(JoinPoint jp) throws JsonProcessingException {
String methodName = jp.getSignature().getName();
String className = jp.getTarget().getClass().toString();
log.info(className + " Method : " + methodName);
startTimeController = System.currentTimeMillis();
}
#After("entryController() || entryControlleruser()")
public void afterControllerCall(JoinPoint jp) throws JsonProcessingException {
endTimeController = System.currentTimeMillis();
String methodName = jp.getSignature().getName();
String className = jp.getTarget().getClass().toString();
log.info(className + " Method : " + methodName + " Values returned :");
if (endTimeController != 0) {
log.info("Time consumed in " + className + " " + methodName + " call is "
+ (endTimeController - startTimeController) + "ms");
}
}
#Around("entryService()")
public Object executionTimeService(ProceedingJoinPoint pjp) throws Throwable {
String methodName = pjp.getSignature().getName();
String className = pjp.getTarget().getClass().toString();
Object[] arguments = pjp.getArgs();
log.info(className + " Method: " + methodName + " Arguments passed :" +
mapper.writeValueAsString(arguments));
long startTime = System.currentTimeMillis();
Object obj = pip.proceed();
long endTime = System.currentTimeMillis();
log.info(className + " Method : " + methodName + " Execution time: " + (endTime -
startTime) + "ms");
log.info(className + " Method : " + methodName + " Response received : " +
mapper.writeValueAsString(obj));
return obj;
}
#Around("entryDAO()")
public Object executionTimeDAO(ProceedingJoinPoint pjp ) throws Throwable {
String methodName pjp.getSignature().getName();
String className pjp.getTarget().getClass().toString();
Object[] arguments = pjp.getArgs();
log.info(className+" Method : "+methodName+" Arguments passed :"
+mapper.writeValueAsString(arguments) );
long startTime = System.currentTimeMillis();
Object obj = pip.proceed();
long endTime = System.currentTimeMillis();
log.info(className+" method : " + methodName+" Execution time: "
+(endTime-start Time)+"ms" );
log.info(className+" Method: "+methodName+" Response received : "+
mapper.writeValueAsString(obj));
return obj;
}
}
Here is the sample of what I have tried with
#Test
public void testBeforeOtherControllerCall() throws Throwable{
JoinPoint joinPoint = mock(JoinPoint.class);
AspectLogging logging = mock(AspectLogging.class);
String[] args = {"arg1", "arg2"};
Object[] obj args)
Signature signature = mock (Signature.class);
when(joinPoint.getSignature().thenReturn(signature);
when(signature.getName().thenReturn("MethodName");
Object object = mock(Object.class);
when(joinPoint.getTarget().thenReturn(object);
when(object.getClass().thenReturn(objectClass);
when(joinPoint.getArgs().thenReturn(obj);
logging.beforeOtherControllerCali(joinPoint);
verify(joinPoint, times (1)).getSignature().getName().equals("MethodName");
}

Preface
When trying to recreate your situation, I had to
guess about which libraries and versions you use,
replace the Lombok logging annotation by a regularly created SLF4J logger, because, as the AspectJ compiler tells you in a warning message, Lombok's byte code modifications do not work with the AspectJ compiler: java: You aren't using a compiler supported by lombok, so lombok will not work and has been disabled. (...) Lombok supports: sun/apple javac 1.6, ECJ. When using Spring AOP instead, it probably works with Lombok, because there you are simply using the normal Java compiler. I however tested in native AspectJ.
fix many syntax errors in your aspect and test Java code as well as several syntax errors in your aspect pointcuts. The classes did not even compile and the aspect cannot have done anything meaningful with faulty pointcuts. If you modify original code in order to create a stand-alone example, please test before posting it. You should have a little bit more pride as a developer when presenting your work publicly. This was your free shot, because you are new on SO, but next time I will just close the question.
Please do read the MCVE article, try to understand it and ask better questions in the future.
Fixed aspect code
package de.scrum_master.aspect;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
#Aspect
public class LoggingAspect {
private static final Logger log = LoggerFactory.getLogger(LoggingAspect.class);
ObjectMapper mapper = new ObjectMapper();
long startTimeController = 0L;
long endTimeController = 0L;
#Pointcut("within(com.sample.api.rest.account..*) || within(com.sample.api.rest.metadata..*)")
public void entryController() {}
#Pointcut("within(com.sample.api.rest.user..*)")
public void entryControllerUser() {}
#Pointcut("within(com.sample.api.service..*)")
public void entryService() {}
#Pointcut("within(com.sample.cmo.repositories..*)")
public void entryDAO() {}
#Before("entryController()")
public void beforeOtherControllerCall(JoinPoint jp) throws JsonProcessingException {
String methodName = jp.getSignature().getName();
String className = jp.getTarget().getClass().toString();
Object[] arguments = jp.getArgs();
log.info(className + " Method : " + methodName + " Arguments passed : " + mapper.writeValueAsString(arguments));
startTimeController = System.currentTimeMillis();
}
#Before("entryControllerUser()")
public void beforeUserControllerCall(JoinPoint jp) throws JsonProcessingException {
String methodName = jp.getSignature().getName();
String className = jp.getTarget().getClass().toString();
log.info(className + " Method : " + methodName);
startTimeController = System.currentTimeMillis();
}
#After("entryController() || entryControllerUser()")
public void afterControllerCall(JoinPoint jp) throws JsonProcessingException {
endTimeController = System.currentTimeMillis();
String methodName = jp.getSignature().getName();
String className = jp.getTarget().getClass().toString();
log.info(className + " Method : " + methodName + " Values returned :");
if (endTimeController != 0) {
log.info("Time consumed in " + className + " " + methodName + " call is " + (endTimeController - startTimeController) + "ms");
}
}
#Around("entryService()")
public Object executionTimeService(ProceedingJoinPoint pjp) throws Throwable {
String methodName = pjp.getSignature().getName();
String className = pjp.getTarget().getClass().toString();
Object[] arguments = pjp.getArgs();
log.info(className + " Method: " + methodName + " Arguments passed :" + mapper.writeValueAsString(arguments));
long startTime = System.currentTimeMillis();
Object obj = pjp.proceed();
long endTime = System.currentTimeMillis();
log.info(className + " Method : " + methodName + " Execution time: " + (endTime - startTime) + "ms");
log.info(className + " Method : " + methodName + " Response received : " + mapper.writeValueAsString(obj));
return obj;
}
#Around("entryDAO()")
public Object executionTimeDAO(ProceedingJoinPoint pjp) throws Throwable {
String methodName = pjp.getSignature().getName();
String className = pjp.getTarget().getClass().toString();
Object[] arguments = pjp.getArgs();
log.info(className + " Method : " + methodName + " Arguments passed :" + mapper.writeValueAsString(arguments));
long startTime = System.currentTimeMillis();
Object obj = pjp.proceed();
long endTime = System.currentTimeMillis();
log.info(className + " method : " + methodName + " Execution time: " + (endTime - startTime) + "ms");
log.info(className + " Method: " + methodName + " Response received : " + mapper.writeValueAsString(obj));
return obj;
}
}
Fixed test
I sent you two links before in my comment, showing you how to write unit and integration tests. Why did you not do it more similar to my examples? Some things you did wrong are:
You created a mock for the aspect class under test. Why? You want to mock dependencies, not the thing you actually want to test. Like in my examples, you should instantiate the aspect normally, only inject a mock joinpoint when calling an advice method.
You cannot simply verify a chain of method calls on a corresponding chain of mock objects, but need to verify them separately. So, something like verify(joinPoint, times (1)).getSignature().getName().equals("MethodName") does not work.
You tried to stub when(object.getClass()).thenReturn(objectClass), which is unnecessary, because Object.getClass() returns something already. Furthermore, it is a final method of a JDK bootstrap class. You cannot simply mock that.
How about this?
package de.scrum_master.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.junit.Test;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class LoggingAspectTest {
#Test
public void testBeforeOtherControllerCall() throws Throwable {
JoinPoint joinPoint = mock(JoinPoint.class);
LoggingAspect logging = new LoggingAspect();
String[] args = { "arg1", "arg2" };
Object[] obj = args;
Signature signature = mock(Signature.class);
when(joinPoint.getSignature()).thenReturn(signature);
when(signature.getName()).thenReturn("MethodName");
Object object = mock(Object.class);
when(joinPoint.getTarget()).thenReturn(object);
when(joinPoint.getArgs()).thenReturn(obj);
logging.beforeOtherControllerCall(joinPoint);
verify(joinPoint, times(1)).getSignature();
verify(signature, times(1)).getName();
verify(joinPoint, times(1)).getTarget();
verify(joinPoint, times(1)).getArgs();
}
}
This covers the method under test and verifies the calls on the mock objects you are interested in, even though I find those verifications somewhat questionable. Do you really want to test the internals of the aspect? You should rather test for side effects or results, if any. But of course you can do it like in my example.
My IDE looks like this when running the test with coverage:

Related

Test Fallback method using sping-cloud-starter-circuitbreaker-resilience4j

public String getAlbumList() {
CircuitBreaker circuitBreaker = circuitBreakerFactory.create("circuitbreaker");
String url = "http://localhost:1234/not-real";
return circuitBreaker.run(() -> restTemplate.getForObject(url, String.class),
throwable -> getDefaultAlbumList());
}
Assume this is my code and "getDefaultAlbumList()" is returning some string "ABCD", and let say my "restTemplate.getForObject(url, String.class)" is going to call some URL which may take more than 5 second, now point is
I want to test that fallback method, how do i test it, how do i mock so that my controller return fallback response.
Thanks
I suppose that you are trying out the example from here: Quick Guide to Spring Cloud Circuit Breaker. So, I copied their service and I introduced a method to pass a null URL. Then I created a test in a spring boot project that verifies if the string value that returns is the fallback string.
#Service
public class AlbumService {
private RestTemplate restTemplate = new RestTemplate();
#Autowired
private CircuitBreakerFactory circuitBreakerFactory;
public String getAlbumList() {
return getAlbumList("https://jsonplaceholder.typicode.com/albums");
}
public String getAlbumList(String url) {
CircuitBreaker circuitBreaker = circuitBreakerFactory.create("circuitbreaker");
return circuitBreaker.run(() -> restTemplate.getForObject(url, String.class),
throwable -> getDefaultAlbumList());
}
// fallback method that reads a default json file
private String getDefaultAlbumList() {
try {
return new String(Files.readAllBytes(
Paths.get(getClass().getClassLoader().getResource("data/fallback-album-list.json").toURI())
));
} catch (Exception e) {
LOGGER.error("error occurred while reading the file", e);
}
return null;
}
}
Then the unit test should test the fallback default json string.
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, properties = {"server.port=0"})
#ExtendWith(SpringExtension.class)
#DirtiesContext
class AlbumServiceTest {
#Autowired
AlbumService albumService;
#Test
void getAlbumListFallBack() {
String result = albumService.getAlbumList(null);
assertNotNull(result);
assertTrue(result.length() > 0);
assertEquals(
"[\n" +
" {\n" +
" \"userId\": 1,\n" +
" \"id\": 1,\n" +
" \"title\": \"quidem molestiae enim\"\n" +
" },\n" +
" {\n" +
" \"userId\": 1,\n" +
" \"id\": 2,\n" +
" \"title\": \"sunt qui excepturi placeat culpa\"\n" +
" }\n" +
"]",
result);
}
}

Spring WebFlux endpoint performance logger

Do you know any good practices to log Spring WebFlux controller endpoint performance to keep reactive nature? Seems the following principle wouldn't work because it will block the IO as the ProceedingJoinPoint doesn't return Publisher<> , it returns just an object
#Aspect
#Component
#Slf4j
public class LoggingAspect
{
//AOP expression for which methods shall be intercepted
#Around("execution(* com.company.service..*(..)))")
public Object profileAllMethods(ProceedingJoinPoint proceedingJoinPoint) throws Throwable
{
MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();
//Get intercepted method details
String className = methodSignature.getDeclaringType().getSimpleName();
String methodName = methodSignature.getName();
final StopWatch stopWatch = new StopWatch();
//Measure method execution time
stopWatch.start();
Object result = proceedingJoinPoint.proceed();
stopWatch.stop();
//Log method execution time
log.info("Execution time of " + className + "." + methodName + " :: " + stopWatch.getTotalTimeMillis() + " ms");
return result;
}
}
Actually as mentioned #Toerktumlare in the comments proceedingJoinPoint.proceed() returns the type of object whatever is you controller endpoint return type, so it is possible to keep reactive nature. Note .subscribeOn(Schedulers.parallel()) is optional here, that is for my back code to support parallelism. Posting the solution for this:
#Aspect
#Component
#Slf4j
public class LoggingAspect
{
//AOP expression for which methods shall be intercepted
#Around("execution(* com.company.service..*(..)))")
public Object logEndpointPerformance(ProceedingJoinPoint proceedingJoinPoint) throws Throwable
{
MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();
//Get intercepted method details
String className = methodSignature.getDeclaringType().getSimpleName();
String methodName = methodSignature.getName();
final StopWatch stopWatch = new StopWatch();
//Measure method execution time
stopWatch.start();
Object result = proceedingJoinPoint.proceed();
if(result instanceof Mono){
return ((Mono)result).subscribeOn(Schedulers.parallel()).flatMap(r -> {
logExecutionTime(className, methodName, stopWatch);
return Mono.just(r);
});
}
else if(result instanceof Flux){
return ((Flux<Object>)result).subscribeOn(Schedulers.parallel()).collectList().flatMapMany(r -> {
logExecutionTime(className, methodName, stopWatch);
return Flux.fromIterable(r);
});
}
else{
logExecutionTime(className, methodName, stopWatch);
return result;
}
}
private void logExecutionTime(final String className, final String methodName, final StopWatch stopWatch){
stopWatch.stop();
//Log method execution time
log.debug("[ " + stopWatch.getTotalTimeMillis() + " mls ] lasted execution of" + className + "." + methodName );
}
}

Spring aop and aspectj

How to store all the logged method calls in database of a single session using spring aop and aspectj ?
In the following code i will get the method names i need to capture them and store in database for an individual session.
#Aspect
#Component
public class LoggingAspect {
// #Autowired
// private SessionFactory sessionFactory;
//
// #Autowired
// private ActionRolesService actionRolesService;
private Logger logger = LoggerFactory.getLogger(getClass());
#Pointcut(" execution(java.lang.String com.bis.sourcelead.entity..*.*()) && "
+ "!execution(java.lang.String com.bis.sourcelead.entity..*.set*()) && "
+ "!execution(java.lang.String com.bis.sourcelead.entity..*.get*())")
private void intercepterMethod() {
}
#Pointcut("execution(#javax.inject.Inject * com.bis.sourcelead.web..*.*(..))")
public void methodAnnotatedWithInjectAndInDemoPackage() {
}
#Before("intercepterMethod()")
public void logAround(JoinPoint joinPoint) throws Throwable {
logger.info("********** Action class Before Method Excution ************");
logger.info("Class name : " + joinPoint.getTarget().getClass().getSimpleName());
logger.info("Method name : " + joinPoint.getSignature().getName());
logger.info("Parameters name : " + Arrays.toString(joinPoint.getArgs()));
}
#Before("execution(* com.bis.sourcelead.service..*.*(..))")
public void logBeforeService(JoinPoint joinPoint) throws Throwable {
logger.info("**********Service Layer Before Method Excution ************");
logger.info("Class name : " + joinPoint.getTarget().getClass().getSimpleName());
logger.info("Method name : " + joinPoint.getSignature().getName());
logger.info("Parameters name : " + Arrays.toString(joinPoint.getArgs()));
}
#AfterReturning(pointcut = "execution(* com.bis.sourcelead.service..*.*(..))", returning = "result")
public void logAfterReturningService(JoinPoint joinPoint, Object result) {
logger.info("********** Service Layer After Method Exectution ************");
logger.info("Class name : " + joinPoint.getTarget().getClass().getSimpleName());
logger.info("Method name : " + joinPoint.getSignature().getName());
logger.info("Method returned value : " + result);
}
#AfterThrowing(pointcut = "execution(* com.bis.sourcelead.service.*.*(..))", throwing = "error")
public void logAfterThrowingService(JoinPoint joinPoint, Throwable error) {
logger.info("********** Service Layer Method Throwing Error ************");
logger.info("Class name : " + joinPoint.getTarget().getClass().getSimpleName());
logger.error("Method name : " + joinPoint.getSignature().getName());
logger.error("Exception : " + error);
}
#AfterThrowing(pointcut = "execution(* com.bis.sourcelead.dao.*.*(..))", throwing = "error")
public void logAfterThrowingDao(JoinPoint joinPoint, Throwable error) {
logger.info("********** Dao Layer Method Throwing Error ************");
logger.info("Class name : " + joinPoint.getTarget().getClass().getSimpleName());
logger.error("Method name : " + joinPoint.getSignature().getName());
logger.error("Exception : " + error);
}
#Around("execution(* com.bis.sourcelead.dao..*.*(..))")
public Object logAroundDao(ProceedingJoinPoint joinPoint) throws Throwable {
Object result = null;
logger.info("********** Dao Layer Before Method Excution ************");
logger.info("Class name : " + joinPoint.getTarget().getClass().getSimpleName());
logger.info("Method name : " + joinPoint.getSignature().getName());
logger.info("Parameters name : " + Arrays.toString(joinPoint.getArgs()));
long start = System.currentTimeMillis();
//result = joinPoint.proceed(); //continue on the intercepted method
result = joinPoint.proceed(joinPoint.getArgs()); //continue on the intercepted method
long elapsedTime = System.currentTimeMillis() - start;
logger.info("********** Dao Layer After Method Excution ************");
logger.info("Method execution time: " + elapsedTime + " milliseconds.");
return result;
}
#Before("execution(* com.bis.sourcelead.rest..*.*(..)) && methodAnnotatedWithInjectAndInDemoPackage() ")
public void logBeforeWebService(JoinPoint joinPoint) throws Throwable {
logger.info("**********Web Service Layer Before Method Excution ************");
logger.info("Class name : " + joinPoint.getTarget().getClass().getSimpleName());
logger.info("Method name : " + joinPoint.getSignature().getName());
logger.info("Parameters name : " + Arrays.toString(joinPoint.getArgs()));
System.out.print("Executed the #Injected method: "
+ joinPoint.getSignature() + " with value(s): ");
for (Object object : joinPoint.getArgs()) {
System.out.print(object);
}
System.out.println();
}
#AfterReturning(pointcut = "execution(* com.bis.sourcelead.rest..*.*(..))", returning = "result")
public void logAfterReturningWebService(JoinPoint joinPoint, Object result) {
logger.info("********** Web Service Layer After Method Exectution ************");
logger.info("Class name : " + joinPoint.getTarget().getClass().getSimpleName());
logger.info("Method name : " + joinPoint.getSignature().getName());
logger.info("Method returned value : " + result);
// try {
// if(joinPoint.getSignature().getName().equalsIgnoreCase("createUser"))
// logger.info("pradeep::"+actionRolesService.getActionNameUsingMethodName(joinPoint.getSignature().getName()));
// } catch (Exception e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
}
#AfterThrowing(pointcut = "execution(* com.bis.sourcelead.rest.*.*(..))", throwing = "error")
public void logAfterThrowingWebService(JoinPoint joinPoint, Throwable error) {
logger.info("********** Web Service Layer Method Throwing Error ************");
logger.info("Class name : " + joinPoint.getTarget().getClass().getSimpleName());
logger.error("Method name : " + joinPoint.getSignature().getName());
logger.error("Exception : " + error);
}
}
//end class

Use Spring AOP and get respective class name in log file

I am using Spring AOP for logging purpose. Everything is working but in the log i am only getting the name of the Aspect class. I want the respective name of the class to be printed. Here is the code snippet. What changes are required in the following code to suffice my requirement.
private static final Logger logger = Logger.getLogger(LogginAspect.class);
#After("execution(* com.app.c2pc...(..))")
public void logAfter(JoinPoint joinPoint) {
logger.info("After executing method : " + joinPoint.getSignature().getName());
logger.info("***************************************************************************");
}
#Before("execution(* com.app.c2pc..*.*(..))")
public void logBefore(JoinPoint joinPoint) {
logger.info("***************************************************************************");
logger.info("Before executing method : " + joinPoint.getSignature().getName());
}
#Around("execution(* com.app.c2pc..*.*(..)) && !execution(* com.app.c2pc.login.LoginController.*(..)) ")
public Object logAround(ProceedingJoinPoint pjp) throws Throwable {
long start = System.currentTimeMillis();
Object clazz = pjp.getTarget().getClass().getName();
String methodName = pjp.getSignature().getName();
logger.info("Entering Class " + clazz + " With Method Name " + methodName);
Object[] obj = pjp.getArgs();
int i = 0;
try {
for (Object o : obj) {
logger.info(++i + " : Parameter Name :" + (null != o ? o.toString() : ""));
}
} catch (Exception e) {
e.printStackTrace();
}
Object output = pjp.proceed(pjp.getArgs());
logger.info("Excecution Completed for method : " + methodName + " in Class : " + clazz + " with result "
+ output);
long elapsedTime = System.currentTimeMillis() - start;
logger.info("Execution time for method : " + methodName + " in Class : " + clazz + " : " + elapsedTime
+ " milliseconds.");
return output;
}
#AfterThrowing(pointcut = "execution(* com.app.c2pc..*.*(..))", throwing = "error")
public void logAfterThrowing(JoinPoint joinPoint, Throwable error) {
logger.info("Exception thrown by method : " + joinPoint.getSignature().getName());
logger.info("Exception name : " + error);
}
#AfterReturning(pointcut = "execution(* com.app.c2pc..*.*(..))", returning = "result")
public void logAfterReturning(JoinPoint joinPoint, Object result) {
logger.info("Method : " + joinPoint.getSignature().getName() + " returned value is : " + result);
}
This is the o/p i get in the log file:-
2016-07-20 23:41:20 | | INFO LogginAspect:23 - After executing method : checkSubmitEvalFlag
2016-07-20 23:41:20 | | INFO LogginAspect:24 - ***************************************************************************
2016-07-20 23:41:20 | | INFO LogginAspect:70 - Method : checkSubmitEvalFlag returned value is : 0
2016-07-20 23:41:20 | | INFO LogginAspect:40 - Entering Class com.app.c2pc.scie.daoImpl.PbdDAOImpl$$EnhancerBySpringCGLIB$$688f6ece With Method Name getBackUpUserDetails
2016-07-20 23:41:20 | | INFO LogginAspect:45 - 1 : Parameter Name :com.app.c2pc.scie.bean.SearchCriteriaBean#77ef5b02
you can use "joinPoint.getTarget().getClass().getName()" to get fully qualified class name like "com.abc.pqr.MyClass"
you can use "joinPoint.getTarget().getClass().getSimpleName()" to get only class name like "MyClass".

Logging request and response for Spring mvc Service

hi All , i Have to log all the request , response , Exception ,
Errors for my Spring services. i had searched about the
interceptors , filters , logging filters , Spring interceptors :
HandlerInterceptorAdapter logger filters :
AbstractRequestLoggingFilter.java and its sub classes
(http://www.javawebdevelop.com/1704067/),
CommonsRequestLoggingFilter.java filters : LoggerFilter.
can any body its difference, and the best approach to do so i am
confused or i need to find out the third party library to do this
?..
I used AOP for something similar in one project. I had to write a class like this:
#Component
#Aspect
public class RequestMonitor {
private static final Logger logger = LoggerFactory.getLogger(RequestMonitor.class);
#Around("#annotation(org.example.ToBeLogged)")
public Object wrap(ProceedingJoinPoint pjp) throws Throwable {
logger.info("Before controller method " + pjp.getSignature().getName() + ". Thread " + Thread.currentThread().getName());
Object retVal = pjp.proceed();
logger.info("Controller method " + pjp.getSignature().getName() + " execution successful");
return retVal;
}
}
Log4j is a java based logging utility with easy integration with Spring MVC. Log4j comes with different logging levels to allow for appropriate logging in correspondence to the development environment.
Log4j 2 is the successor to log4j and has better performance as compared to its predecessor.
Kindly refer the following link for an integration of spring MVC + Log4j
http://www.codejava.net/frameworks/spring/how-to-use-log4j-in-spring-mvc
Edit: As mentioned in comment , PFB the code for logging both request and response.
#Aspect
#Component
public class ResponseLoggerAspect {
private static final Logger logger = Logger.getLogger("requestResponseLogger");
ExclusionStrategy excludeJsonAnnotation = new JsonIgnoreAnnotationExclusionStrategy();
Gson gson = new GsonBuilder().setExclusionStrategies(excludeJsonAnnotation).create();
#Pointcut("within(#org.springframework.stereotype.Controller *)")
public void controller() {}
#Pointcut("execution(* *(..))")
public void method() {}
#Pointcut("execution(#com.company.annotation.AddLog * *(..))")
public void Loggable() {}
//This will be caught for only those controller method where #AddLog annotation is written
#Before("Loggable()")
public void printRequestLog(JoinPoint joinPoint) {
try {
Object[] argsList = joinPoint.getArgs();
String str = "[";
for(Object arg : argsList) {
if(arg instanceof Object[]) {
str += Arrays.toString((Object[])arg) + ", ";
} else {
str += String.valueOf(arg) + ", ";
}
}
str += "]";
logger.info("Request args for " + joinPoint.getSignature().getName() + " are : " + str);
} catch(Exception ex) {
logger.info("Unable to log request args", ex);
}
}
//This will be called for all controller methods after returning
#AfterReturning(pointcut = "controller() && method()", returning="result")
public void afterReturning(JoinPoint joinPoint , Object result) {
long start = System.nanoTime();
try {
logger.info("Response sent by " + joinPoint.getSignature().getName() + " are : " + gson.toJson(result));
} catch(Exception ex) {
logger.error("Returned result cant be converted in JSON " , ex);
}
long end = System.nanoTime();
logger.info("elapsed time : " + (end - start));
}
}

Resources