In this part of the tutorial we are going to see what JBoss AOP classes and methods are involved in the call of advices, so you know how to interpret those when they appear during debugging.
Which classes call advice and trigger intercepted joinpoints?When a joinpoint is weaved, its code is replaced by code generated by JBoss AOP. This new code wraps the original joinpoint code, in a way that your original joinpoint is still going to execute, but a few steps later. As this code is generated by JBoss AOP, you will not be able of seeing the code lines being executed during debugging. That is ok. You should keep in mind only what are the main tasks involved in each step and press
F5
/
F6
/
F7
until you enter your advice or joinpoint code.
This is the sequence of the elements involved in the execution stack when a weaved joinpoint is executed:
Advisor
->
JoinPoint
-> advice + joinpoint
As you can see, there are two helper classes involved. One of them is the Advisor class. Specifically, the wrapper method contained in this class is responsible for calling methods on the
JoinPoint
class. And the
JoinPoint
class is the one that is actually going to invoke your advice and your joinpoint, the points that you want to be able of debugging.
AdvisorsAn
Advisor
is responsible for managing interception of your classes. There is an
Advisor
per intercepted class, which manages all the advice stacks related to that specific class. Similarly, there is an
Advisor
per instance and this advisor is going to appear at your execution stack only when there is specific configuration per instance, which is rare.
From version 2.0 on, the default weaving mode is the generated-advisor mode. From this point on, we will assume you are using this mode. In this mode, advisors are also responsible for generating code that will invoke your advice and joinpoint, and for invoking this code as well.
It is very easy to identify an advisor on the debugging stack trace. The advisor of class POJO
is called POJOAdvisor
, and is an internal class of POJO
. In this case, you are going to see POJO$POJOAdvisor
as the name of the advisor class in the stack trace.
Wrapper Methods
Every time a joinpoint is weaved by JBoss AOP, this joinpoint execution is replaced by a call to a wrapper method. These methods know what to do to trigger execution of your advice and the intercepted joinpoint.
The signature of a wrapper methods varies according to the type of joinpoint you are intercepting. For example, the wrapper of a method called public void run(Withdrawal) would have the signature:
public void run_N_8003352271541955702(Withdrawal)
Once you start debugging, you
will get used to the signatures of wrapper methods and will start recognizing them right away. For now, there is a simple rule you can use to identify those. They are part of generated advisors and are the first extra item that will appear on the stack trace when you are debugging an intercepted joinpoint.
That said, if the method run
of the previous example belongs to a class named Withdrawal
, you are going to see something like this:
Note that for some types of joinpoints, such as field read and constructor execution, you are going to see an extra wrapper method at the stack. This extra wrapper has the same signature as the wrapper belonging to the Advisor
class, but it will instead belong to the class that contains the joinpoint being executed:
In this picture, we see that there are two wrappers: intField_w_$aop(Object, int)
, belonging to the POJO
class, and POJO$POJOAdvisor$intField_w_$aop(Object, int)
, belonging to to the POJOAdvisor
class.
Notice that those method names do not indicate a exotic taste, as they are made this way so we can avoid crashing with any name of other classes/fields/methods you may have included in your application. Plus, those method names make it easier to identify code generated inside of JBoss AOP.
JoinPoint classes
A JoinPoint
class is generated for each joinpoint of your system. Their names always start with "Joinpoint"
, followed by something that identifies the joinpoint they represent, like the example below:
JoinPoint_run_N_80033522715419555702_2
JoinPoint
is your main class of interest here. Despite the fact that you ca not see its code or the lines being executed when debugging, this class is responsible for calling your aspects and invoking the joinpoint they represent as well. So, if you have advice A and B intercepting execution of, say, void myMethod()
, it is the JoinPoint
class that will invoke A
, B
and myMethod
as well.
The entry point for the JoinPoint
class is the invokeJoinPoint
method:
When debugging this method, and the inner methods it calls, you want to use F5
so you can enter your advice and joinpoint codes in order to debug them.
Noise over the line The elements presented in the previous section are not the only ones you are going to face when debugging your weaved joinpoint. Other calls will appear in the stack. While the elements you are going to see are important for the inner working of JBoss AOP applications, they are not your focus of interest when debugging.
So, the following elements of the stack trace are not going to take you to the execution of advice or the weaved joinpoint, and that is why we say they are “noise over the line”:
- Info classes: are helper classes that contain information related to each joinpoint (such whether there are advice to be applied to that joinpoint, and which advice are those). Sometimes, the
JoinPoint
class will enter an info class to query that type of information. The main info classes are: FieldInfo
, MethodInfo
, ConstructorInfo
, MethodByMethodInfo
, ConByMethodInfo
, ConByConInfo
, and MethodByConInfo
.
- Constructors: as you probably know, they are represented by the word on the stack trace;
- Concurrent lock code: code that makes sure that interception is thread-safe;
- JoinPoint class generation: the
JoinPoint
class we mentioned in a previous section is generated at the first time a specific joinpoint is reached:
- Call to any other JDK class: though it is rare, you may run into a call to a JDK class when debugging a weaved joinpoint
All the points contained in the previous list should be skipped. So, whenever you see those, just press F7
to return to one of the points mentioned in the “Which classes call advice and trigger intercepted joinpoints?” section.
Debugging a joinpoint
Once you are more familiar with the elements presented in the previous sections, you are
ready to start.
Before continuing, lets recall what are the keys you can use during Eclipse debugging and what they represent:
F5: Step into
F6: Step over
F7: Step return
These are the steps you must follow when a weaved joinpoint is reached:
The joinpoint is reached. The first thing you will notice is that, despite you can see the joinpoint code in your application, Eclipse will flag that it cannot find the line correspondent to the joinpoint. This is expected and indicates that your joinpoint has been weaved. Press F5
to enter the wrapper method.
Now you can see the wrapper method of the Advisor
class in the execution stack. This is the method that is going to invoke the JoinPoint
class, so press F5
again.
This is the tricky part. Besides invoking the JoinPoint
class, the wrapper method performs a couple of other actions: enabling concurrent lock and invoking code to generate the joinpoint class are a few of those. Those actions are what we called “noise over the line”. Whenever you enter a block that is not part of the JoinPoint
class, press F7
to return to the wrapper method.
When you finally get into the JoinPoint class, press F5
constantly, until you enter your advice.
If , before getting to your advice or joinpoint, you run into constructors (
elements in the stack), info methods, or any call to a JDK class, you should press F7
to return to the Joinpoint
class;
When you enter an advice, Eclipse will start recognizing the line numbers again and you will be able of debugging your advice just as any normal method of your application.
The same holds for your joinpoint. If your joinpoint is a method or constructor, you are going to be able of entering those and debugging them normally.
Once all advice and the joinpoint have been executed, the JoinPoint
class is done with its work and execution will return to the wrapper method. When this happens, press F7
until you return to your normal application code.
TIP: When debugging around advice, remember of pressing F5
on the call to Invocation.invokeNext()
. Or you won't be able of seeing the execution of other around advice, nor the execution of the joinpoint being intercepted.
In the next part of our tutorial, we are going to illustrate the steps above, walking you through a debugging process over Eclipse. See you there!