I'm new to AspectJ. Was able to create a simple JUnit and Aspect classes to log ThreadId, which logs Parent Thread Id. But I'm not able to figure out how to log Child ThreadId.
Given the following snippet of code, I'd like to log Thread Id of both parent and child using AspectJ.
JUnit:
@Test
public void testExecutorService() {
ExecutorService service = Executors.newSingleThreadExecutor();
Runnable task = new Runnable() {
@Override
public void run() {
System.out.println("working on the task");
}
};
service.submit(task);
}
Aspect: The following aspect logs Parent ThreadId.
before() :
call(* ExecutorService+.submit(..))
{
System.out.println("Parent Thread Id: "+Thread.currentThread().getId());
//System.out.println("Child Thread Id: "+??); //?? - how to capture child thread id?
}
I understand that it is using "before" advice here and also it is intercepting submit method, which might be an issue as well. How can I log child Thread Id along with Parent Thread Id using correct Pointcut expression?
What you can do is to intercept the task parameter of the submit and enhanced that task to print what you want:
Object around(Runnable task) : call(* ExecutorService+.submit(Runnable, ..)) && args( task)
{
final long parentID = Thread.currentThread().getId();
Runnable newTask = () -> {
System.out.println("Parent Thread Id: "+ parentID);
System.out.println("Child Thread Id: "+Thread.currentThread().getId()); //?? - how to capture child thread id?
task.run();
};
return proceed(newTask);
}
As soon as the asynchronous task is executed the id of the thread executing it will be print.
A Running example:
Main.java:
public class Main {
public static void main(String[] args) {
new Test().testExecutorService();
}
}
Test.java:
public class Test {
public void testExecutorService() {
ExecutorService service = Executors.newSingleThreadExecutor();
service.submit(() -> System.out.println("working on the task"));
try {
service.awaitTermination(2, TimeUnit.SECONDS);
service.shutdown();
}catch (InterruptedException ie) {
Thread.currentThread().interrupt();
}
}
}
Example.aj
public aspect Example {
Object around(Runnable task) : call(public Future<?> java.util.concurrent.ExecutorService+.submit(Runnable))
&& args(task)
{
final long parentID = Thread.currentThread().getId();
Runnable newTask = () -> {
System.out.println("Parent Thread Id: "+ parentID);
System.out.println("Child Thread Id: "+Thread.currentThread().getId());
task.run();
};
return proceed(newTask);
}
}