I use Spring Integration and have a flow described in some #Configuration annotated class (#Bean and #Autowired marked methods), f.e. CustomFlow.class.
If any element in flow throw exception I would like to intercept it with #AfterThrowing advice and do some actions (notification, write smth to DB, etc).
So the question is - how to write proper pointcut to get all beans in this case?
#Aspect
public class LoggingAspect {
#AfterThrowing(
pointcut = "execution(*(..))",
throwing= "error")
public void logAfterThrowing(JoinPoint joinPoint, Throwable error) {
//...
}
}
and then the configuration:
<aop:after-throwing method="logAfterThrowing" throwing="error" />
Related
I would like to wrap all the repository calls in my service with an Around aspect for creating some metrics.
All of my JpaRepositories are annotated with org.springframework.stereotype.Repository, so I tried something like this:
#Configuration
#Aspect
public class RepositoryMetrics {
#Around("#annotation(org.springframework.stereotype.Repository)")
public void logQueryTime(ProceedingJoinPoint joinPoint) throws Throwable {
//Some logic here
joinPoint.proceed();
//Some logic here
}
}
But seems like the aspect method never runs. What do I miss?
Assuming you have the JpaRepository classes annotated as follows
#Repository
public interface JpaEmployeeRepository extends CrudRepository<JpaEmployee, Long> {
...
}
Following Aspect would intercept all method calls happening to that class
#Component
#Aspect
public class RepositoryAspect {
#Pointcut("#within(org.springframework.stereotype.Repository)")
public void repositoryAnnotationPointCut() {}
#Around("repositoryAnnotationPointCut()")
public void logQueryTime(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("logged for "+pjp.toLongString());
pjp.proceed();
}
}
Please note that a Configuration class be better left for configuration entries and you may create a separate class for Aspect and annotate the same with #Component as given in the example.
Make sure you have #ComponentScan to auto detect the Aspect and #EnableAspectJAutoProxy on the Configuration class. Something as follows
#Configuration
#EnableAspectJAutoProxy
#ComponentScan(basePackageClasses= {RepositoryAspect.class})
public class AppConfig {
...
}
Update
Following are the reasons , your code didn't work as expected
1.
Pointcut designator #annotation
#annotation: Limits matching to join points where the subject of the
join point (the method being executed in Spring AOP) has the given
annotation.
In this case method is not annotated.
2.
The Configuration class RepositoryMetrics is not annotated with #EnableAspectJAutoProxy . I assume Spring AOP was not enabled in any of the Configuration classes.
I have two projects. One is a Spring Boot service, and the other is a library which is making use of Spring AOP. I have created a custom annotation to be executed whenever a method is annotated with this custom annotation. As I want this annotation to be used in lots of services, it lives inside the library. My code looks something like this:
Service:
#MyCustomAnnotation
public void doSomething() {
log.info("Do something is invoked!");
}
#EnableAspectJAutoProxy
public class ApplicationConfig {
...
}
Library:
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface MyCustomAnnotation {
...
}
#Aspect
public class ContinueTraceFromSpringKafkaEventAspect {
#Pointcut("#annotation(MyCustomAnnotation)")
public void executeMyCustomAnnotation() { }
#Before("executeMyCustomAnnotation()")
public void beforeAnnotation(JoinPoint joinPoint) {
log.info("Before annotation");
}
#After("executeMyCustomAnnotation()")
public void afterAnnotation(JoinPoint joinPoint) throws Throwable {
log.info("After annotation");
}
}
The annotation would successfully execute when the code lived inside the service but, ever since extracting it to a library (and having the library on the classpath of the service via Maven dependency), it doesn't execute - I suspect the pointcut expression needs amending.
Any ideas?
I have a Spring boot application, and I want to log some info what happens when a Controller method id invoked.
For some reason, my Aspect is not working.
Here is my #Component class annotated with #Aspect:
#Pointcut("within(#org.springframework.stereotype.Controller *)")
public void controller() {
}
#Pointcut("execution(* *.*(..))")
protected void allMethod() {
}
#Before("controller()&& allMethod()")
public void logBefore(JoinPoint joinPoint) {
}
The logBefore method is not called, when any Controller method is called with REST.
Important: As you've stated you are using a Spring Boot setup, my assumption is that you've implemented the Spring AOP module instead of the "actual" AspectJ library. The difference is significant, as the implementation of AOP differs between them. Spring uses the AspectJ annotations to apply proxying, while AspectJ "weaves" the code into your application. In short, Spring AOP might be easier to implement, while AspectJ offers more fine-grained functionality (such as compile-time weaving). A comparison can be found here.
I have tried out the configuration from the code snippet you provided in your post. The advice was invoked after I added several annotations:
#SpringBootApplication
// Be sure to add EnableAspectJAutoProxy and set proxyTargetClass to true
#EnableAspectJAutoProxy(proxyTargetClass = true)
public class DemoApplication {
...
}
// Be sure to add #Aspect and #Component
#Component
#Aspect
public class DemoAop {
private static Logger logger = LoggerFactory.getLogger(DemoAop.class);
#Pointcut("within(#org.springframework.stereotype.Controller *)")
public void controller() {
}
#Pointcut("execution(* *.*(..))")
protected void allMethod() {
}
#Before("controller()&& allMethod()")
public void logBefore(JoinPoint joinPoint) {
logger.info("TEST");
}
}
At runtime your controller is annotated with #RestController but not #Controller.
Simply changing the Pointcut to RestController works:
#Pointcut("within(#org.springframework.web.bind.annotation.RestController *)")
public void controller() {
}
I have created a custom annotation:
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface ValidateBeforeBuild {
}
And an aspect as:
#Aspect
#Component
public class AspectForBuildInBuilders {
private static final Logger LOGGER = LoggerFactory.getLogger(AspectForBuildInBuilders.class);
#Before("#annotation(validateBeforeBuild )")
public void validateBusinessModelAdvice(JoinPoint jp, ValidateBeforeBuild validateBeforeBuild ) throws Throwable {
LOGGER.info("Executing class: {}", jp);
}
}
I have a build() that is marked with above annotation. When I am trying to call the build(), I am not getting the log message from the validateBusinessModelAdvice(). I also have #EnableAspectJAutoProxy in one of the configuration classes. Am I missing something? Is there any more information required?
You defined your annotation as ValidateBeforeBuild and in your aspect you specified validateBeforeBuild (notice the upper V in your annotation)
Try changing
#Before("#annotation(validateBeforeBuild)")
for
#Before("#annotation(ValidateBeforeBuild)")
I want to have a AspectJ pointcut for methods annotated with #Scheduled. Tried different approaches but nothing worked.
1.)
#Pointcut("execution(#org.springframework.scheduling.annotation.Scheduled * * (..))")
public void scheduledJobs() {}
#Around("scheduledJobs()")
public Object profileScheduledJobs(ProceedingJoinPoint joinPoint) throws Throwable {
LOG.info("testing")
}
2.)
#Pointcut("within(#org.springframework.scheduling.annotation.Scheduled *)")
public void scheduledJobs() {}
#Pointcut("execution(public * *(..))")
public void publicMethod() {}
#Around("scheduledJobs() && publicMethod()")
public Object profileScheduledJobs(ProceedingJoinPoint joinPoint) throws Throwable {
LOG.info("testing")
}
Can anyone suggest any other way to have around/before advice on #Scheduled annotated methods?
The pointcut that you are looking for can be specified as below:
#Aspect
public class SomeClass {
#Around("#annotation(org.springframework.scheduling.annotation.Scheduled)")
public void doIt(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("before");
pjp.proceed();
System.out.println("After");
}
}
I am not sure whether that's all you require or not. So I'm going to post the other parts of the solution as well.
First of all, notice the #Aspect annotation on the class. It is required for the methods in this class to be applied as advice.
Also, you need to make sure that the class that has the #Scheduled method is detectable via scanning. You can do so by annotation that class with #Component annotation. For ex:
#Component
public class OtherClass {
#Scheduled(fixedDelay = 5000)
public void doSomething() {
System.out.println("Scheduled Execution");
}
}
Now, for this to work, the required parts in your spring configuration would be as follows:
<context:component-scan base-package="com.example.mvc" />
<aop:aspectj-autoproxy /> <!-- For #Aspect to work -->
<task:annotation-driven /> <!-- For #Scheduled to work -->