AspectJ OR Operator Doesn't Seem to be Functioning - aop

I'm having a little trouble getting a logging aspect set up using SpringAOP + AspectJ. I would like an "Around" method to fire when either a class or method is annotated with the #Loggable annotation. Below is my advice code:
#Around(value = "execution( * *(..)) && target(bean) && #annotation(loggable)", argnames "bean, loggable")
public void test1(ProceedingJoinPoint method, Object bean, Loggable loggable) { }
#Around(value = "execution( * *(..)) && target(bean) && #within(loggable)", argnames "bean, loggable")
public void test2(ProceedingJoinPoint method, Object bean, Loggable loggable) { }
#Around(value = "execution( * *(..)) && target(bean) && (#annotation(loggable) || #within(loggable))", argnames "bean, loggable")
public void test3(ProceedingJoinPoint method, Object bean, Loggable loggable) { }
test1 and test2 fire. test3 does not, and it's the one that I really want. Any thoughts on why this might be?

First of all, there are syntax errors in your pointcuts. It is not lower-case argnames but argNames and you are missing an = in between parameter name and value. So it must be argNames = "bean, loggable".
Secondly if your advice returns void it will only match methods returning void as well. The more general case is to return Object in the advice to really match all methods.
Last but not least, you should see a warning which explains the problem with the third pointcut. This is displayed in your Eclipse IDE or on the AspectJ compiler's (ajc) log output:
ambiguous binding of parameter(s) loggable across '||' in pointcut
This means that you cannot say "bind one value or the other to the parameter 'loggable'". What if both conditions match? Which one should be assigned? You have two options, assuming your fully-qualified class name is de.scrum_master.app.Loggable:
A) No reference to #Loggable annotation needed:
This is the simple case. If #Loggable does not have any parameters you need to read, it is not necessary to bind it to a parameter. BTW, if you want your pointcut to also capture static methods, you should not bind target() either because the target would be null. Maybe in Spring-AOP this is irrelevant because it only works with Spring Beans anyway, but in full-featured AspectJ it would make a difference because it is more powerful.
#Around(value = "execution(* *(..)) && (#annotation(de.scrum_master.app.Loggable) || #within(de.scrum_master.app.Loggable))")
public Object withoutLoggableReference(ProceedingJoinPoint thisJoinPoint) {
Object bean = thisJoinPoint.getTarget();
System.out.println(thisJoinPoint + " -> " + bean);
return thisJoinPoint.proceed();
}
Or, equivalently:
#Around(value = "execution(* (#de.scrum_master.app.Loggable *.*)(..)) || execution(#de.scrum_master.app.Loggable * *.*(..))")
public Object withoutLoggableReference(ProceedingJoinPoint thisJoinPoint) {
Object bean = thisJoinPoint.getTarget();
System.out.println(thisJoinPoint + " -> " + bean);
return thisJoinPoint.proceed();
}
B) Reference to #Loggable annotation needed:
You have no other choice than to go with two separate pointcuts if you want to bind the annotations to parameters. Maybe you could use a utility method doing the actual logging in order to avoid code duplication in your advice.

Related

How to figure out which methods IDynamicMemberReferenceOperation refers to?

I have the following function in my OperationWalker:
public override void VisitDynamicInvocation(IDynamicInvocationOperation operation)
{
var memberReferenceOp = (IDynamicMemberReferenceOperation)operation.Operation;
switch (memberReferenceOp.Instance.Type)
{
case INamedTypeSymbol type:
{
var memberName = memberReferenceOp.MemberName;
var members = type.GetMembers(memberName);
if (members.Length > 1)
{
// WHAT DO I DO HERE ???
}
else
{
Result.Add((IMethodSymbol)members[0]);
}
break;
}
case IDynamicTypeSymbol dynamicType:
Unresolved.Add((operation.Syntax, memberReferenceOp.MemberName));
break;
}
}
I am clueless when a method on a normal type (non dynamic) is called with a dynamic parameter and there is a choice of target methods with the same name. E.g.:
class A
{
public void Get(int i){}
public void Get(string s){}
public void Get(object o){}
public void Get(double s, int precision){}
}
...
dynamic x = ...;
A a;
a.Get(x)
In this case any of the first 3 A.Get methods may be called, depending on the actual type of x. But not the fourth method.
Is there a way in Roslyn to get this information? Specifically in this example, I would like to get the symbols for first 3 Get methods.
The logic is non trivial, because one needs to take into account:
Default parameters, so just counting the arguments may not be enough
Type conversions
Visibility Scope
Number of arguments
Parameters may be passed using the named syntax in arbitrary order
Combining it all together we get non trivial logic. Is there anything in the SemanticModel or anywhere else to help get the answer?
I figured it out and it is straightforward - SemanticModel.GetSymbolInfo. When there is exact match its Symbol property returns it. When there are multiple candidates, as may be the case when one of the passed arguments is dynamic, then the property CandidateSymbols holds all the options.
I have not tested it with extension methods, so it is possible there is a gap there.

Mockito mocking method with class parameter vs actual object parameter

What is the difference between these two as per Mockito -
Mockito.when(serviceObject.myMethod(Customer.class)).thenThrow(new
RuntimeException());
and
Customer customer = new Customer();
Mockito.when(serviceObject.myMethod(customer)).thenThrow(new
RuntimeException());
And if both serve the same purpose then using which one is considered to be best practice?
There is a misunderstanding on your side - that method specification myMethod(SomeClass.class) is only possible when the signature of that method allows for a class parameter. Like:
Whatever myMethod(Object o) {
or directly
Whatever myMethod(Class<X> clazz) {
In other words: it is not Mockito that does something special about a parameter that happens to be of class Class!
Thus your first option is not something that works "in general". Example: I put down this code in a unit test:
static class Inner {
public int foo(String s) { return 5; }
}
#Test
public void testInner() {
Inner mocked = mock(Inner.class);
when(mocked.foo(Object.class)).thenReturn(4);
System.out.println(mocked.foo(""));
}
And guess what - the above does not compile. Because foo() doesn't allow for a Class parameter. We can rewrite to
static class Inner {
public int foo(Object o) { return 5; }
}
#Test
public void testInner() {
Inner mocked = mock(Inner.class);
when(mocked.foo(Object.class)).thenReturn(4);
System.out.println(mocked.foo(""));
}
And now the above compiles - but prints 0 (zero) when invoked. Because the above would be the same as mocked.foo(eq(Object.class)). In other words: when your method signature allows for passing a Class instance and you then pass a class instance, that is a simple mocking specification for mockito. In my example: when the incoming object would be Object.class - then 4 would be returned. But the incoming object is "" - therefore the Mockito default kicks in and 0 is returned.
I am with the other answer here - I think you are mixing up that older versions of Mockito asked you to write down when(mocked.foo(any(ExpectedClass.class))) - which can nowadays be written as when(mocked.foo(any())). But when(mocked.foo(ExpectedClass.class)) is not a Mockito construct - it is a simple method specification that gives a specific object to "match on" - and that specific object happens to be an instance of class Class.
First one which uses generic Customer class to match type can also be written as:
Mockito.when(serviceObject.myMethod(Mockito.any(Customer.class))).thenThrow(new
RuntimeException());
In case of the second one, you are passing the actual object that will be used in stubbing.
Usage:
If your method myMethod throws the exception based on the state of the Customer object then you can use the latter approach, where you can set the state of the Customer object appropriately.
However If your method myMethod does not depend on the Customer object to throw the exception rather you need it only to pass it as an argument just to invoke the method, then you can take the former approach.

Adding some boolean conditions in pointcut expression

I'm using some aspect around advice methods. I have methods for controller, service and repository.
#Around("execution(* com.abc..controller..*(..)) && #annotation(audit)")
public Object controllerAround(ProceedingJoinPoint proceedingJoinPoint, Audit audit) throws Throwable {
//some code here
return output;
}
#Around("execution(* com.abc..service.*Impl.*(..))")
public Object serviceAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
//some code here
return output;
}
#Around("execution(* com.abc..persistence.*Impl.*(..))")
public Object persistenceAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
//some code here
return output;
}
I have a query that, I need to check in serviceAround method pointcut expression that, whether it's comes from the controllerAround method. I tried using some flags, but spring doesn't support aspectj's if() pointcut primitive.
Any workaround for this will be appreciated. :)
What you actually need is cflow() or cflowbelow(), not if(). But those are also not supported by Spring AOP. So the remaining solution is to use the full power of AspectJ from within Spring via LTW (load-time weaving). How this is done is nicely documented.
The pointcut would look like this:
execution(* com.abc..service.*Impl.*(..)) &&
cflow(
execution(* com.abc..controller..*(..)) &&
#annotation(customAnnotation)
)
Or simpler, assuming you do not need the annotation in the advice method:
execution(* com.abc..service.*Impl.*(..)) &&
cflow(execution(* com.abc..controller..*(..)))
Attention: cflow() only works for control flows within one thread, not if e.g. *Impl*.(..) is executed in another thread than controller..*(..).
P.S.: Your sample code would probably not work because of a parameter name mismatch between customAnnotation and audit.

PHP Static and Normal Functions Calling [duplicate]

There are two distinct ways to access methods in PHP, but what's the difference?
$response->setParameter('foo', 'bar');
and
sfConfig::set('foo', 'bar');
I'm assuming -> (dash with greater than sign or chevron) is used for functions for variables, and :: (double colons) is used for functions for classes. Correct?
Is the => assignment operator only used to assign data within an array? Is this in contrast to the = assignment operator which is used to instantiate or modify a variable?
When the left part is an object instance, you use ->. Otherwise, you use ::.
This means that -> is mostly used to access instance members (though it can also be used to access static members, such usage is discouraged), while :: is usually used to access static members (though in a few special cases, it's used to access instance members).
In general, :: is used for scope resolution, and it may have either a class name, parent, self, or (in PHP 5.3) static to its left. parent refers to the scope of the superclass of the class where it's used; self refers to the scope of the class where it's used; static refers to the "called scope" (see late static bindings).
The rule is that a call with :: is an instance call if and only if:
the target method is not declared as static and
there is a compatible object context at the time of the call, meaning these must be true:
the call is made from a context where $this exists and
the class of $this is either the class of the method being called or a subclass of it.
Example:
class A {
public function func_instance() {
echo "in ", __METHOD__, "\n";
}
public function callDynamic() {
echo "in ", __METHOD__, "\n";
B::dyn();
}
}
class B extends A {
public static $prop_static = 'B::$prop_static value';
public $prop_instance = 'B::$prop_instance value';
public function func_instance() {
echo "in ", __METHOD__, "\n";
/* this is one exception where :: is required to access an
* instance member.
* The super implementation of func_instance is being
* accessed here */
parent::func_instance();
A::func_instance(); //same as the statement above
}
public static function func_static() {
echo "in ", __METHOD__, "\n";
}
public function __call($name, $arguments) {
echo "in dynamic $name (__call)", "\n";
}
public static function __callStatic($name, $arguments) {
echo "in dynamic $name (__callStatic)", "\n";
}
}
echo 'B::$prop_static: ', B::$prop_static, "\n";
echo 'B::func_static(): ', B::func_static(), "\n";
$a = new A;
$b = new B;
echo '$b->prop_instance: ', $b->prop_instance, "\n";
//not recommended (static method called as instance method):
echo '$b->func_static(): ', $b->func_static(), "\n";
echo '$b->func_instance():', "\n", $b->func_instance(), "\n";
/* This is more tricky
* in the first case, a static call is made because $this is an
* instance of A, so B::dyn() is a method of an incompatible class
*/
echo '$a->dyn():', "\n", $a->callDynamic(), "\n";
/* in this case, an instance call is made because $this is an
* instance of B (despite the fact we are in a method of A), so
* B::dyn() is a method of a compatible class (namely, it's the
* same class as the object's)
*/
echo '$b->dyn():', "\n", $b->callDynamic(), "\n";
Output:
B::$prop_static: B::$prop_static value
B::func_static(): in B::func_static
$b->prop_instance: B::$prop_instance value
$b->func_static(): in B::func_static
$b->func_instance():
in B::func_instance
in A::func_instance
in A::func_instance
$a->dyn():
in A::callDynamic
in dynamic dyn (__callStatic)
$b->dyn():
in A::callDynamic
in dynamic dyn (__call)
:: is used in static context, ie. when some method or property is declared as static:
class Math {
public static function sin($angle) {
return ...;
}
}
$result = Math::sin(123);
Also, the :: operator (the Scope Resolution Operator, a.k.a Paamayim Nekudotayim) is used in dynamic context when you invoke a method/property of a parent class:
class Rectangle {
protected $x, $y;
public function __construct($x, $y) {
$this->x = $x;
$this->y = $y;
}
}
class Square extends Rectangle {
public function __construct($x) {
parent::__construct($x, $x);
}
}
-> is used in dynamic context, ie. when you deal with some instance of some class:
class Hello {
public function say() {
echo 'hello!';
}
}
$h = new Hello();
$h->say();
By the way: I don't think that using Symfony is a good idea when you don't have any OOP experience.
Actually by this symbol we can call a class method that is static and not be dependent on other initialization...
class Test {
public $name;
public function __construct() {
$this->name = 'Mrinmoy Ghoshal';
}
public static function doWrite($name) {
print 'Hello '.$name;
}
public function write() {
print $this->name;
}
}
Here the doWrite() function is not dependent on any other method or variable, and it is a static method. That's why we can call this method by this operator without initializing the object of this class.
Test::doWrite('Mrinmoy');
// Output: Hello Mrinmoy.
But if you want to call the write method in this way, it will generate an error because it is dependent on initialization.
The => operator is used to assign key-value pairs in an associative array. For example:
$fruits = array(
'Apple' => 'Red',
'Banana' => 'Yellow'
);
It's meaning is similar in the foreach statement:
foreach ($fruits as $fruit => $color)
echo "$fruit is $color in color.";
The difference between static and instantiated methods and properties seem to be one of the biggest obstacles to those just starting out with OOP PHP in PHP 5.
The double colon operator (which is called the Paamayim Nekudotayim from Hebrew - trivia) is used when calling an object or property from a static context. This means an instance of the object has not been created yet.
The arrow operator, conversely, calls methods or properties that from a reference of an instance of the object.
Static methods can be especially useful in object models that are linked to a database for create and delete methods, since you can set the return value to the inserted table id and then use the constructor to instantiate the object by the row id.
Yes, I just hit my first 'PHP Parse error: syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM'. My bad, I had a $instance::method() that should have been $instance->method(). Silly me.
The odd thing is that this still works just fine on my local machine (running PHP 5.3.8) - nothing, not even a warning with error_reporting = E_ALL - but not at all on the test server, there it just explodes with a syntax error and a white screen in the browser. Since PHP logging was turned off at the test machine, and the hosting company was too busy to turn it on, it was not too obvious.
So, word of warning: apparently, some PHP installations will let you use a $instance::method(), while others don't.
If anybody can expand on why that is, please do.

How to intercept proceed() in another AspectJ aspect?

I have a situation as follows: I have a LoggingAspect with several pointcuts matching specific method executions in my main application. The corresponding advice bodies basically all look similar, causing a lot of code duplication:
void around() : download() {
String message = "Downloading, verifying (MD5) and unpacking";
SimpleLogger.verbose(message, IndentMode.INDENT_AFTER);
proceed();
SimpleLogger.verbose(message + " - done", IndentMode.DEDENT_BEFORE);
}
There is some variation, though. Sometimes the pointcut & advice have an arg or this parameter which is also printed to the log. Sometimes the "done" message is not printed if it s just a minor call not wrapping a lot of other calls, like this:
void around(BasicFilter filter) : fixFaultyLinkTargets() && this(filter) {
String message = "TOC file: checking for faulty link targets";
SimpleLogger.verbose(message, IndentMode.INDENT_AFTER);
proceed(filter);
SimpleLogger.dedent();
}
The constant thing is that I manually tell the logger
to increase the indent level after the first message is printed, i.e. directly before proceed() is called, and
to decrease the indent level before the final message is printed (if any is printed), i.e. directly after proceed() has returned.
My idea is that I would like to write a meta aspect (or call it a helper aspect) with a pointcut which intercepts the proceed() calls in LoggingAspect so as to automatically adjust the indentation level accordingly. But there seems to be no pointcut matching proceed(). I have tried call(SomeMethodInMyMainApp), even a pointcut matching everything in the logging aspect, but the pointcut matches anything I do not need, but never ever the proceed.
If anybody knows how I can do this, I would appreciate a hint or a code snippet.
An indirect way of doing this might be to intercept not the advice themselves, but the method calls (or executions) advised by those advice by creating an extra pointcut like this:
// ATTENTION: each new pointcut must also be added here
pointcut catchAll() : download() || fixFaultyLinkTargets() || ...;
void around() : catchAll() {
SimpleLogger.indent();
proceed();
SimpleLogger.dedent();
}
I would prefer another way though, without me having to remember to update the extra catchAll() pointcut everytime I change something in the logging aspect.
Suggestion wrap the proceed() in an anonymous class. And the write an aspect which adress this execution (but don't forget potential exceptions of proceed()).
My suggestion:
// AspectProceedCaller.java
public abstract class AspectProceedCaller {
public abstract Object doProceed();
};
// aspect ProceedCallerAspect.aj
aspect ProceedCallerAspect {
pointcut execProceedCaller() : execution( * AspectProceedCaller+.doProceed() );
Object around() : execProceedCaller() {
try {
SimpleLogger.indent();
return proceed();
}
finally {
SimpleLogger.dedent();
}
}
};
// Your application aspect
aspect AnyAspect {
pointcut anyPointcut() : ...;
Object around() : anyPointcut() {
AspectProceedCaller apc=new AspectProceedCaller() {
public Object doProceed() {
return proceed();
}
};
// DO Stuff before ....
Object retval = apc.doProceed();
// ... and after calling proceed.
return retval;
}
};
Best regards Marko
Please note: I am going to answer my own question here, adding more information and the additional feature of parametrisation to the solution suggested by loddar2012. Because his answer led me to the right direction, I am going to accept it even though this answer here really addresses all my needs from the original question, such as (quoting myself):
There is some variation, though. Sometimes the pointcut & advice have an arg or this parameter which is also printed to the log. Sometimes the "done" message is not printed if it s just a minor call not wrapping a lot of other calls
The basic thing we are dealing with here is what Ramnivas Laddad calls the worker object pattern in his book AspectJ in Action. His (and loddar2012's) idea is, in plain prose
to wrap a call into an instance of an anonymous class (the worker object) where
the base class or implemented interface provides a method intended to do the work,
the worker object provides a concrete implementation of the worker method and specifically calls proceed() therein,
the worker method can be called right after object creation (as we will do here) or later, maybe even in its own thread,
the worker object may be passed around or added to a scheduling queue (none of which we will need here).
An elegant solution if you need to execute your proceed() calls asynchronously would be to create instances of anonymous Runnable classes. We will use our own abstract base class LogHelper, though, because we want some more sugar in our tea, specifically the option to pass a log message and some other parameters influencing log output to each worker. So this is what I did (package names and imports not shown in the sample code):
Abstract worker base class:
abstract class LogHelper {
// Object state needed for logging
String message;
boolean logDone;
boolean indent;
LogType type;
// Main constructor
LogHelper(String message, boolean logDone, boolean indent, LogType type) {
this.message = message;
this.logDone = logDone;
this.indent = indent;
this.type = type;
}
// Convenience constructors for frequent use cases
LogHelper(String message, boolean logDone) {
this(message, logDone, true, LogType.VERBOSE);
}
LogHelper(String message) {
this(message, true);
}
// Worker method to be overridden by each anonymous subclass
abstract void log();
}
Logging advice capturing execution of worker objects:
aspect LoggingAspect
{
void around(LogHelper logHelper) :
execution(* LogHelper.log()) && this(logHelper)
{
try {
SimpleLogger.log(logHelper.type, logHelper.message);
if (logHelper.indent)
SimpleLogger.indent();
proceed(logHelper);
} finally {
if (logHelper.indent)
SimpleLogger.dedent();
if (logHelper.logDone)
SimpleLogger.log(logHelper.type, logHelper.message + " - done");
}
}
// (...)
}
As you can see, the logging advice does some things before calling proceed(logHelper) (i.e. executing the worker object's log() method) and some things afterwards, using the state information stored inside the worker object, such as
message to be logged,
log level (here called "type"),
flag specifying if indentation level should be raised before proceeding,
flag specifying if "done" message should be printed after worker execution.
Because in my use case all logged methods return void, there is no need to implement return value passing, but this would be easily possible, if necessary. The advice's return value would then just be Object and we would pass the result of proceed() back to our caller, no big deal.
Some advice capturing joinpoints to be logged and utilising parametrised worker objects to get the work done:
aspect LoggingAspect
{
// (...)
pointcut processBook() : execution(* OpenbookCleaner.downloadAndCleanBook(Book));
pointcut download() : execution(* Downloader.download());
pointcut cleanBook() : execution(* OpenbookCleaner.cleanBook(Book));
pointcut cleanChapter() : execution(* OpenbookCleaner.cleanChapter(Book, File));
pointcut initialiseTitle() : execution(* *Filter.initialiseTitle(boolean));
void around(final Book book) : processBook() && args(book) {
new LogHelper("Book: " + book.unpackDirectory) {
void log() { proceed(book); } }.log();
}
void around() : download() {
new LogHelper("Downloading, verifying (MD5) and unpacking") {
void log() { proceed(); } }.log();
}
void around() : cleanBook() {
new LogHelper("Filtering") {
void log() { proceed(); } }.log();
}
void around(final File origFile) : cleanChapter() && args(*, origFile) {
new LogHelper("Chapter: " + origFile.getName()) {
void log() { proceed(origFile); } }.log();
}
void around() : initialiseTitle() {
new LogHelper("Initialising page title", false) {
void log() { proceed(); } }.log();
}
}
The examples show how you can
instantiate an anonymous LogHelper as a worker object with one or more constructor parameters, setting its state
implement the log() method, optionally using joinpoint state bound via this() or args(),
call/run the worker object (the call will be intercepted by the logging advice's pointcut and the real logging business be done there).