Background We have a Java project which uses Maven as the build tool. The project structure has a Parent POM and then various Child POMs.
I am working on creating a child POM project where I want to define a set of Aspects which can be used in existing child projects.
I got it working with the help of - http://www.mojohaus.org/aspectj-maven-plugin/examples/libraryJars.html#
Question - If I want to log runtime argument values of a method execution then how can I do it in the Library without it depending on any other Child POM projects?
For instance:
Parent Project:
Classes in Child-1:
package org.example;
class Item {
// fileds, getters, setters
}
package org.example;
class Business {
public void logic(Item b) {
// logic
}
}
Class in AspectJ-Library
package org.example;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class LoggingAspect {
@Before("execution(* org.example.Business.logic(..))") // Will be moving this to annotation based PointCut
public void logBeforeAllMethods(JoinPoint joinPoint)
{
// How to log values of various fields of object of class Item?
}
}
How to log values of various fields of object of class Item in the logBeforeAllMethods
method above?
Your question has nothing to do with Maven modules or AspectJ Maven plugin. If I understand correctly, you simply want to know how to log argument details for an intercepted method. How about using parameter binding via args()
?
package de.scrum_master.app;
public class Item {
private int id;
private String name;
public Item(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
}
package de.scrum_master.app;
public class Business {
public void logic(Item item) {}
public static void main(String[] args) {
new Business().logic(new Item(11, "Jane"));
new Business().logic(new Item(22, "John"));
}
}
package de.scrum_master.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import de.scrum_master.app.Item;
@Aspect
public class LoggingAspect {
@Before("execution(* de.scrum_master.app.Business.logic(..)) && args(item)")
public void logBeforeAllMethods(JoinPoint joinPoint, Item item) {
System.out.println(joinPoint);
System.out.println(" Item[id=" + item.getId() + ", name=" + item.getName() + "]");
}
}
Console log:
execution(void de.scrum_master.app.Business.logic(Item))
Item[id=11, name=Jane]
execution(void de.scrum_master.app.Business.logic(Item))
Item[id=22, name=John]
If you had something more generic in mind, your sample code did not express it clearly, and neither did your problem description.
Maybe you noticed that my aspetc has taken care of gathering a string representation of Item
. The better ways would be to create a meaningful toString()
method (or another suitable string representation method) for Item
and simply use that in the aspect. Of course, you could use relfection in the aspect to determine fields and their values, but is that really the job of an aspect?
Besides, why did you write this?
// Will be moving this to annotation based PointCut
Why would you? It is much better to intercept methods using a pointcut describing the kinds of classes, methods, arguments etc. you want to log. Only use marker annotations as a very last resort, if there is no other way to write a pointcut. Marker annotations for AOP are vastly overused by developers not thinking about other ways to define the set of joinpoints they wish to intercept. Marker annotations seem to be easy, because you do not need to think much when using them. But the consequence of using them is that you pollute your whole code base with aspect-related information, which is the very thing AOP strives to avoid.