I am having some strange problems using spring and Load-Time-Weaving using AspectJ.
In one of my Apsects, I wanted to react on invocations of the "doAuthentication" Method of the class org.springframework.flex.security3.SpringSecurityLoginCommand. Therefore I created a method:
#Around("execution(* org.springframework.flex.security3.SpringSecurityLoginCommand.doAuthentication(..))")
public Object aroundDoAuthentication(ProceedingJoinPoint pjp) throws Throwable {
...
This aspect is woven correctly if I use the aspectj-weaver agent, but is ignored if I use the spring-weaver. Unfortunately I have to use the spring-weaver, if I want correct aspect-spring integration. The only way I found out to get my aspect woven is to weave it around every method of the target class and to programatically filter the aspect calls:
#Around("execution(* org.springframework.flex.security3.SpringSecurityLoginCommand.*(..))")
public Object aroundDoAuthentication(ProceedingJoinPoint pjp) throws Throwable {
final String methodName = pjp.getSignature().getName();
if("doAuthentication".equals(methodName)) {
...
Using the above code, I managed to weave everythgin correctly, but I am not sattisfied with this as it seems to be a big hack to me.
Could anyone please explain why using the Spring-Weaver I am not able to weave the same as with the aspectj-weaver?
Chris
I don't know the code, but this seams to be the same old question.
Spring AOP is per default proxy based.
This means only invocations of methods that come from outside of the bean go though the proxy. Therefore only this invocation can trigger the AOP advice.
Related
I read that Spring AOP cannot intercept private and protected methods but it is intercepting them in a weird way why is that?
I have these functions i want to intercept:
public String getName(String string) {
System.out.println("Name : " + name + string);
return name;
}
protected String getNamesprotected(String string) {
System.out.println("Name : " + name + string);
return name;
}
This is my #Aspect code:
#Aspect
public class Logging {
#Before("execution(* com.tutorialspoint.Student.*Name*(..))")
public void beforeAdvice(JoinPoint joinPoint){
System.out.println("Going to setup student profile."+joinPoint.getSignature().toString());
}
}
When this code is executed both getName and getNamesprotected are intercepted but when I execute this code :
#Aspect
public class Logging {
#Before("execution(* com.tutorialspoint.Student.getNamesprotected(..))")
public void beforeAdvice1(JoinPoint joinPoint){
System.out.println("Going to setup student profile."+joinPoint.getSignature().toString());
}
}
Then nothing is intercepted. I also tried replacing getNamesprotected with *getNamesprotected* but still it does not intercept. It only intercepts when *Name* is there.
Can anyone explain me why this is happening?
Because the OP (Prateek Gupta) seemed to be unable (rather unwilling) to create a little SSCCE reproducing the problem and I was just bored during a tea break, I quickly created one by myself with Spring Boot and was very surprised that indeed Spring AOP, in contradiction to the documentation, at least under certain circumstance matches against protected methods when CGLIB proxies are involved.
Thus, I registered myself an account for Spring's Jira issue tracker and reported this regression as SPR-15354. You might want to subscribe for updates on that ticket if interested in answers by the Spring development team.
Update: The person answering to my ticket told me that this is a documentation issue. As SPR-1611 from 2006 tells us, this was already changed on purpose for Spring 1.2.7 but has never found its way into the documentation. Bottom line: Protected methods can be captured via Spring AOP, it is not an accident but has been undocumented for 12 years.
Update 2: The updated documentation text will be in the next Spring release. If you want to read the fixed text today, it is quoted in SPR-1611.
Can anyone explain me why this is happening?
Due to the proxy-based nature of Spring’s AOP framework, protected methods are by definition not intercepted, neither for JDK proxies (where this isn’t applicable) nor for CGLIB proxies (where this is technically possible but not recommendable for AOP purposes).
As a consequence, any given pointcut will be matched against public methods only!
If your interception needs include protected/private methods or even constructors, consider the use of Spring-driven native AspectJ weaving instead of Spring’s proxy-based AOP framework.
When this code is executed both getName and getNamesprotected are
intercepted
#Before("execution(* com.tutorialspoint.Student.*Name*(..))")
Here the preceding wildcard matches methods with any modifier (public, protected, and private) and any return type. The two dots in the argument list match any number of arguments.
Try this it should execute your protected method
#Pointcut("execution(protected * *.*(..))")
Also you can try this if it works for you (I am not 100% sure)
#Before("execution(* com.tutorialspoint.Student+.getNamesprotected(..))")
I'm using Spring's CrudRepository in combination with the annotation #RepositoryRestResource to implement a simple CRUD-app that can be used throught a RESTful API. I now want to add an AspectJ pointcut on my repository, so that some functionalities will be executed whenever a CRUD-method from the interface is called.
First, I extend Spring's CrudRepository to add some custom functionalities in my own interface:
#RepositoryRestResource(collectionResourceRel = "customers", path = "customers")
public interface CustomerRestRepository extends CrudRepository<Customer, Integer>{
Customer findOneByGuid(#Param("customerGuid") String customerGuid);
//Other custom methods.
}
Everything is working fine and I'm able to call this method via my REST client. I do not have to implement the interface CustomerRestRepository since Spring is doing the job as a miracle in behind. This is one of the crucial advantages of extending Springs's CrudRepository.
The problem, I'm facing now, is to add an AspectJ pointcut on this custom method findOneByGuid() that will, for example, log every call of the method after it's execution.
What I've tried by so far is:
#Aspect
public aspect AfterCustomerCrudAspect {
#Pointcut(
"execution(* com.x.y.z.CustomerRestRepository.findOneByGuid(..))")
public void customerCrudMethod() {}
#AfterReturning("customerCrudMethod()")
public void doSomething() {
//Do something
}
}
I've also tried:
1) execution(* com.x.y.z.CustomerRestRepository+.findOneByGuid(..))
2) execution(* org.springframework.data.repository.Repository+.*(..))
3) within(com.x.y.z.CustomerRestRepository)
4) annotation(RepositoryRestResource)
...and many others I do not remember. All with the same frustrating result: The advice is never applied.
By the way, I do not face any exceptions and if I try execution(* *.*(..)), the advice is working well - but, of course, not limited to the method findOneByGuid(). Thus, I think my code is correct in general.
I know that it is not possible to set pointcuts on interfaces. But since I do not have to implement the interface CustomerRestRepository by my own to get things working, I need to find a way to set a pointcut on an interface's method - or to find some other solution.
Well, one possible solution to that would be to implement the interface CustomerRestRepository. But then I've to do all the implementation work for the repository by my own and skip using the advantages of Spring's CrudRepository.
Thus, my question is, if there is a possibility to set a AspectJ pointcut on methods in a Spring CrudRepository.
Many thanks in advance for all the answers.
Well, I solved my problem in a different way.
Sometimes, things are less complicated than expected. Adding an AspectJ pointcut on a Spring CRUD-repository to execute some functionalities, whenever an entity is changed was not the best idea. (And at the best of my knowledge, it is not possible at all.)
There is a much more easier way to implement my requirement: The package javax.persistence provides the annotation #EntityListeners that suites perfectly to this job. So, annotate the entity class with the listener and implement the needed functionalities within the listener class:
#Entity
#EntityListeners(CustomerEntityListener.class)
//#Table, #NamedQueries and other stuff ...
public class Customer implements Serializable {
...
}
Implementation of the EntityListener:
public class CustomerEntityListener {
#PostPersist
public void customerPostPersist(Customer customer) {
//Add functionalities
}
}
The EntityListeneralso provides annotation for #PostUpdate, #PostRemove and so on - visit this site for more information.
I'm currently trying to add a pointcut around calls to HttpServletResponse.sendRedirect (api doc http://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletResponse.html) using aspectj and spring aop. The code for the class and pointcut are as follows:
#Aspect
#Log4j
class ExampleAspect {
#Before("execution(* javax.servlet.http.HttpServletResponse.sendRedirect(..))")
void logRedirectBeforeSending() {
log.warn('holy cow batman, its a redirect!')
}
}
Currently although the above code compiles it doesn't actually ever execute (as evidenced by a lack of warn output in the log and debug breakpoints in the advice code never being hit).
Although I've omitted them here just for the sake of simplicity the aspect contains other pointcuts which do correctly fire so I have ruled out aspect configuration as a potential cause (which is why I am not including my spring bean configuration).
Further, I have double checked via debugging that a class which implements HttpServletResponse.sendRedirect() is being called when I'm testing my pointcut (if it helps, one of the implementing classes being called is org.apache.catalina.connector.Response https://tomcat.apache.org/tomcat-6.0-doc/api/org/apache/catalina/connector/Response.html).
Is there something I'm missing in my pointcut definition that's required when defining a pointcut around an interface? Best I could tell from the Spring AOP documentation it shouldn't require any special syntax.
I've been playing around with variations in the pointcut definition but haven't had any luck yet.
All in all I'm stumped, any ideas?
I expect that your response object is not coming from the Spring application context and as such it would not be subject to your aspect.
It doesn't matter that the call is being initiated from a Spring bean. It matters that the call is being invoked on a Spring bean. If you for example wrote a point cut to be applied to the append method in StringBuffer and then you did something like new StringBuffer().append('something'), your point cut would not be applied because the StringBuffer that you are interacting with is not a Spring bean. I don't know how your app is put together but unless your response is coming out of the Spring context, I don't expect your point cut to be applied.
I'm newbie to Spring AOP. I do understand the concept behind it and i also do understand the concept of #Before or #After etc usage. What i am so confused is still the usage of Spring AOP. Think of the below method of a class.
public void test(int x) {
:
x++;
logger.info("This is a test" + x);
:
try {
:
} catch (Exception e) {
throw new ...
}
:
}
The old way of capturing the log is as shown above.
Here's my questions:
If i were to implement the above method using Spring AOP, this logger will be removed but then does Spring AOP able to capture this log message? (from what i know Spring AOP does not look inside a method)
If answer to clause 1) is yes then how is it done?
If answer is no what's the point of using Spring AOP. Usage of #Before is useless unless you want to capture the information like parameters prior to execution of the method. Most of the time we want to capture some log inside a method itself.
Forget about AspectJ. I do know that AspectJ can do the above job.
I just want to know what's the point of using Spring AOP if it cannot do the very fundamental thing of capturing logs inside a method.
Any help is appreciated.
Further note:
I assume after implementating Spring AOP the above code would be like this. The logger call is no longer in the test method since it will be taken care of by the aspect class. Isn't that the purpose of AOP? To remove cross cutting concern from objects (since it's not related to the actual service of the object) and be taken care of by the aspect class?
public void test() {
:
try {
:
} catch (Exception e) {
throw new ...
}
:
}
If Spring AOP cannot do this what's the point of having a AOP?
I am having difficulty understanding what you are asking for here. In general, I don't know what it means to 'capture logs inside a method', but I think I can provide some assistance anyways.
It sounds to me like you want to arbitrarily insert code into random points in a method, not necessarily at the beginning or the end of the method. In general, Spring AOP cannot do this, and I am not sure that AspectJ will be able to help with either, but I am less familiar with that to give you a definitive answer.
Spring AOP, like you said, can inject before/after/around various JoinPoints in your codebase. These JoinPoints are going to be methods, and only in Spring managed classes.
So if you have a method like the following, you can add logging (via System.out in this case) around it via an #Around aspect.
The code:
public void test() {
System.out.println("I am in a method now");
}
The aspect:
#Around("execution(public * *(..))")
public void publicMethods(ProceedingJoinPoint pjp) {
System.out.println("before in an aspect");
pjp.proceed();
System.out.println("after in an aspect");
}
This essentially turns the initial method into this (as well as adding these System.out's to all public methods):
public void test() {
System.out.println("before in an aspect");
System.out.println("I am in a method now");
System.out.println("after in an aspect");
}
Depending on the layout of your code, you may be able to effectively insert arbitrarily by creating methods at the points that you want to insert. I wouldn't recommend this, but it certainly is possible.
Finally, here are the answers to your questions:
You could replace the logger with a #Before aspect, assuming the logging line is the first code in the method. If you were to do that, you would then be able to remove the logging from within the method. I don't quite know what you are asking for with the last sentence, but no, Spring AOP does not look 'inside' a method.
Spring AOP is able to 'capture' it because Spring will proxy the class.
The point of Spring AOP is to be able to 'intercept' method calls. You may not see a real use for it, but it is extremely useful. I would beg to differ on the last sentence, when using Spring AOP, I want to be able to examine what is going into my method, or what is coming out.
EDIT:
You are correct, the log call can be removed, and taken care of by the aspect. The thing that must be noted is that the only opportunities for the log method to be called by the aspect are either before or after the actual method invocation.
I'm trying to use Spring AOP with AspectJ support to weave methods with a certain annotation. I know it's easy to do so by using a pointcut #annotation(classname)
But I need to create weavers based on properties of the annotation. The annotation in question is Spring's #RequestMapping, and I need to check the method property of it.
I know I could access it inside the body of the advice, but what I really would like is to create one advice per matched annotation.
Is this possible?
There doesn't seem to be a way to do it, but you can check the parameters of the annotation immediately on entry and immediately pass it on if they're not satisfied.
#Around("execution(public * *(..)) && #annotation(reqMap)")
public Object myMethod(ProceedingJoinPoint pjp, RequestMapping reqMap)
throws Throwable {
if (notRightPropertyValue(reqMap))
return pjp.proceed();
// Do your stuff here
}
If this is too inelegant, consider inventing an extra annotation to mark just the methods that you're really interested in.