0

I'm trying to do a SQL query profiling using AOP

Below is my snippet from @Aspect defenition

@Pointcut("(call(* org.springframework.jdbc.core.JdbcTemplate.query*(..)) || call(* org.springframework.jdbc.core.JdbcTemplate.update*(..)))")
public void profileQuery() {
}

@Around("profileQuery()")
public Object profile(ProceedingJoinPoint thisJoinPoint) throws Throwable {
    logger.info("profileQuery() aspect Before");
    Object pjp= thisJoinPoint.proceed();
    logger.info("profileQuery() aspect After");
    return pjp;
}

POM snippet for aspectj maven plugin

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>aspectj-maven-plugin</artifactId>
    <version>1.14.0</version>
    <configuration>
        <complianceLevel>${java.version}</complianceLevel>
        <showWeaveInfo>true</showWeaveInfo>
        <verbose>true</verbose>
        <Xlint>ignore</Xlint>
        <encoding>UTF-8 </encoding>
    </configuration>
    <dependencies>
    </dependencies> 
    <executions>
        <execution>
            <id>compile</id>
            <phase>process-classes</phase>
            <goals>
                <goal>compile</goal>
                <goal>test-compile</goal>
            </goals>    
        </execution>
    </executions>
</plugin>

POM snippet for maven compiler plugin

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
        <fork>true</fork>
        <source>${java.version}</source>
        <target>${java.version}</target>
        <useIncrementalCompilation>false</useIncrementalCompilation>
        <excludes>
          <exclude>**/*.*</exclude>
        </excludes>
    </configuration>
</plugin>

I tried using Eclipse and also tried compiling outside Eclipse Command used mvn clean install -Dmaven.test.skip=true

No issues in building and deploying it on Tomcat 8.5.83 , also the APIs are working, but the aspect is not being intercepted as expected.

Akshay Som
  • 121
  • 1
  • 5
  • It would be better to share a full sample project, not just snippets from the aspect and the POM. I want to verify that the code you want to intercept is getting called in the first place. Anyway, what I see at first glance is that you posted pseudo code. Like this, the aspect would not compile, because there is a statement after `return`. Please learn [how to ask a question on SO](https://stackoverflow.com/help/how-to-ask) and provide a [minimal, complete, and verifiable example](https://stackoverflow.com/help/mcve). Thank you. – kriegaex Dec 17 '22 at 09:33
  • "call" is not supported by Spring AOP anyway., you have to write a "real" Aspect (a "public aspect ..." in a "src/main/aspect/package/.aj" file because "execution" will not work for a method in class that is not a Spring bean (see https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#aop) – p3consulting Dec 17 '22 at 18:28
  • Please refrain from making confusing statements, if you don't know exactly what you are talking about. Nobody here is talking about Spring AOP, this question is about AspectJ. – kriegaex Dec 17 '22 at 19:58
  • Sorry it was a mistake when posting, have edited it out, I wont be able to post the original code since its belongs to a work organisation, I have uploaded similar minimal example here https://github.com/akshaysom/spring-aspectj, Hope this helps - @kriegaex – Akshay Som Dec 19 '22 at 04:48
  • Yes, it helps, because a reproducible example always does. See my upcoming answer. Besides, I never asked for your original code. Did you read the [MCVE](https://stackoverflow.com/help/mcve) link I posted before? – kriegaex Dec 19 '22 at 09:04
  • @kriegaex My issue was solved, Have added as answer ,Thanks for your support and time – Akshay Som Dec 19 '22 at 09:11

3 Answers3

1

There are several problems in your POM and code, which I fixed in this pull request, for example:

  • You configured AspectJ Maven Plugin in the pluginManagement section, but forgot to actually add the plugin to the project in a separate plugins section.

  • Your example does not contain a test base directory. Therefore, you need to remove goal test-compile in order to avoid build errors.

  • When using org.codehaus.mojo:aspectj-maven-plugin, using complianceLevel is not enough, you also need to specify source and target. Or you simply switch to the better dev.aspectj:aspectj-maven-plugin variant, then complianceLevel is enough.

  • Package name aspect is not OK for native AspectJ, because in AspectJ it is a reserved keyword. So I renamed your package to aop.

  • Your pointcut call(* service.apiInnerService(..)) is wrong, you forgot the class name and should use call(* service.MainService.apiInnerService(..)) instead.

  • A native AspectJ aspect should not have a @Component annotation, because that is used for Spring AOP proxy-based aspects. You should avoid Spring to pick it up a second time.

In addition to these changes, I also removed some cruft from your code, reformatted everything a bit and added a main method to AppConfig, so I could easily run the applicaion from my IDE and verify that the aspect works. But it should work the same in your WAR.

When running the application, now I see:

Before Around :testAspectPointcut
Innerservice
After Around
Success

I.e., the aspect is working, intercepting your private method call. But allow me to say that if you need to apply aspects to private methods, you most likely have a design problem in your application.

kriegaex
  • 63,017
  • 15
  • 111
  • 202
0

This version works:

@Aspect
public class ProfileCallAspect {
    private static final Logger LOGGER = LogManager.getLogger(ProfileCallAspect.class);
    
    @Pointcut("call(* org.springframework.jdbc.core.JdbcTemplate.query*(..)) || call(* org.springframework.jdbc.core.JdbcTemplate.update*(..))")
    public void profileQuery() {
    }

    @Around("profileQuery()")
    public Object profile(ProceedingJoinPoint thisJoinPoint) throws Throwable {
        LOGGER.info("ProfileCallAspect() Before");
        Object res =  thisJoinPoint.proceed();
        LOGGER.info("ProfileCallAspect() After");
        return res ;
    }

}

In a Spring project, you can't make it a @Component because of the "call" in the pointcut, but @Configurable works (enabling by @EnableSpringConfigured and with spring-aspects in the dependencies). As Aspect, it works without, but if you want to do something more useful than just logging you may need to inject dependencies in it. Of course, any exception during the proceed() and the "after" will not be logged, if you want that you should replace the @Around by entries: @Before @After, @AfterReturning, @AfterThrowing according to your needs. You also need the build with aspectj-maven-plugin and spring-aspects as aspectLibrary in your pom.xml. (or the equiv. for gradle)

p3consulting
  • 2,721
  • 2
  • 12
  • 10
  • I suggest to improve the around advice by using try-catch-finally around `proceed()`. That way, you can make sure to handle and/or log exceptions correctly and to always print the "after" log message in the `finally` block. That way, there is no need to split the advice into before/after advices. – kriegaex Dec 18 '22 at 12:02
  • Besides, your code is the same as the original one. Therefore, it is not going to help the OP to solve his problem. His problem is getting the compile-time weaving step with AspectJ Maven Plugin right. You wrote nothing about how to solve that, so your answer is not particularly helpful. I think that the question can only be answered if the OP posts a full, minimal sample project reproducing the issue, as I requested in my previous comment. Otherwise, there will only be speculative answers like this one. – kriegaex Dec 18 '22 at 12:06
  • One more thing: _spring-aspects_ should not be necesary here, because the OP wants to use his own aspect, not one of Spring's built-in ones. He also did not request Spring bean injection, so that is out of scope here. – kriegaex Dec 18 '22 at 12:08
  • No the code is not the same as the original because the original just doesn't compile and this one has been tested by adding it to the SpringExamples/aop one. And as I stated in the answer, spring-aspects is only needed if he wants to make a @Configurable one. So depending on that, the aspectj-maven-plugin configuration may be different but in the simplest hypothesis, the basic set-up with true just works. – p3consulting Dec 18 '22 at 12:23
  • The code is the same. The cosmetic changes you made do not make any difference. – kriegaex Dec 18 '22 at 13:27
0

I got this working after removing in pom.xml.

instead of

<pluginManagement> 
  <plugins>
    <plugin>
    </plugin>
  </plugins>
</pluginManagement> 

I changed to

 <plugins>
    <plugin>
    </plugin>
 </plugins>

In fact, the initial approach was a mistake I made in pom.xml

One point if any one else having weaving issues even after proper configuration : Compile the project outside the IDE you are using, If you build the project from IDE there will be overrides for AJC (AspectJ compiler) and the weaving might not happen

Akshay Som
  • 121
  • 1
  • 5
  • Your demo app had many more problems than just this one, see my answer. As for IDE compilation, my IDE (IntelliJ IDEA) builds and runs the code just fine, importing the build config from the POM. – kriegaex Dec 19 '22 at 09:21