Announcement Announcement Module
Collapse
No announcement yet.
How to enable AspectJ nature in a Spring project with annotated and .aj aspects? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • How to enable AspectJ nature in a Spring project with annotated and .aj aspects?

    Hi,

    I have a Spring 3.0.6 project which uses some AspectJ annotated Spring aspects for Spring AOP. Everything works fine. My JUnit tests compile and run as expected, and all my aspects are called according to their pointcuts.

    However, I have recently run into the need for some AspectJ aspects. So I created my .aj aspects and pointcuts and enabled AspectJ nature on my project.

    Now, suddenly, I'm running into trouble. My Junit tests instantiate my Spring @Aspects twice; once properly (all beans are properly injected) and once incorrectly (nothing is injected). When subsequent calls are made to the advice, it fails as the improper bean/aspect/advice is called (the bean with nothing injected) and all my injected values are null.

    If I removed the AspectJ nature, then the project runs properly, but my AJ aspect is not woven.

    I am using Maven and have the following aspectj related configuration in my pom.xml:

    Code:
    ...
    ...
    		<!-- Aspect Oriented Programming (AOP) Framework (depends on spring-core, 
    			spring-beans) Define this if you use Spring AOP APIs (org.springframework.aop.*) -->
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-aop</artifactId>
    			<version>${org.springframework.version}</version>
    		</dependency>
    
    		<!-- Support for AspectJ Annotations -->
    		<dependency>
    			<groupId>org.aspectj</groupId>
    			<artifactId>aspectjweaver</artifactId>
    			<version>${org.aspectj}</version>
    		</dependency>
    
    		<!-- AspectJ weaving -->                        
    	    <dependency>
    	      <groupId>org.aspectj</groupId>
    	      <artifactId>aspectjrt</artifactId>
    	      <version>${org.aspectj}</version>
    	    </dependency>
    	    
    		<dependency>
    			<groupId>org.aspectj</groupId>
    			<artifactId>aspectjtools</artifactId>
    			<version>${org.aspectj}</version>
    		</dependency>	  
    
    ...
    ...
    ...
    	      <plugin>
    	        <groupId>org.codehaus.mojo</groupId>
    	        <artifactId>aspectj-maven-plugin</artifactId>
    	        <version>1.4</version>
    	        <configuration>
    				<source>1.6</source>
    				<target>1.6</target>
    	          <weaveDependencies>
    	            <weaveDependency>
    					<groupId>commons-pool</groupId>
    					<artifactId>commons-pool</artifactId>
    	            </weaveDependency>
    	          </weaveDependencies>
    	        </configuration>
    	        <executions>
    	          <execution>
    	            <goals>
    	              <goal>compile</goal>
    	              <goal>test-compile</goal>
    	            </goals>
    	          </execution>
    	        </executions>
    	      </plugin>
    Is there some special way to configure this?

    Thanks!
    Eric

  • #2
    Hi Eric,

    I guess this is also your thread about the same thing on stackoverflow:
    http://stackoverflow.com/questions/1...pring-aop-bean

    I don't know the answer myself but I know someone to ask so I'll do that today. Hopefully I'll have feedback soon or you'll see a direct reply from them here.

    cheers,
    Andy

    Comment


    • #3
      I did speak to someone I thought would know, but he didn't have a magic solution for this. I can immediately of something you can try:

      Avoid including the spring controlled aspects in compile time compilation

      An 'aop.xml' file is traditionally for loadtime weaving but it does actually work in compile time weaving too. There are some screenshots in here http://www.eclipse.org/ajdt/whatsnew201/ (see 'AJDT support for passing aop.xml file'). Basically you are switching the project to say that instead of weaving in all the aspects it can find, it should only weave the ones you list explicitly. To get this to work, add '-xmlConfigured' to the Project Properties 'Non-standard compiler options' and then in AspectJBuild>'aop.xml management' point it at a simple aop.xml file:

      <aspectj>
      <aspects>
      <aspect name="com.fooMyNewNoneSpringAspect"/>
      </aspects>
      </aspectj>

      Just use it to list the non spring aspects you want to weave in, and don't list the ones you are wanting the Spring framework to deal with. Another way to set things up to check if this is the problem (that too many things are being woven in) would be to temporarily move your service bean thing into a separate project and have it on the classpath of your main project - on the classpath means spring will find it but the AspectJ builder won't.

      As I re-read the stackoverflow entry I do recall some jira from a while back about a wrong bean ids/instances problem related to Aspects usage. Have you tried a search in the Spring Framework jira? ( https://jira.springsource.org/secure/Dashboard.jspa )

      Andy

      Comment


      • #4
        Oh, and in terms of maven - another way to achieve a similar thing is described here:

        http://stackoverflow.com/questions/3...-configuration

        you could use that to exclude your Service bean @Aspect thing to avoid it being included in the compile time weave that maven performs.

        cheers
        Andy

        Comment


        • #5
          Thanks for the reply. Indeed, the stackoverflow link is mine. I don't have any explicit parameters set for LTW, so unless AJDT automatically enables LTW for launch configurations, I don't think I'm currently using LTW. I have double checked my launch configs for my unit tests and there is nothing specified in the VM/nonVM parameters. Consequently, I am assuming this is all happening at CTW.

          So here's the odd thing. If I remove AJ Capability, the unit test runs properly. Which leads me to believe it is something with the AJDT. Looking at the build path, I noticed that enabling AJDT adds the aspectjrt.jar lib explicitly to the build path (even though it is already part of my Maven Dependencies). Not surprisingly, removing it makes no difference (since it is already part of the Maven dependencies).

          Adding the <exclude> tags to the plugin definition doesn't make a difference either. However, by enabling the aop.xml (ie: <outputxml>true</outputxml>), I can validate that the Spring aspects are not actually included in the build. Even disabling the plugin for test (ie: only include compile as maven execution goal and not test-compile) makes no difference either.

          Specifying "-xmlConfigured" without specifying an aop.xml in aop.xml management still doesn't work either. However, creating an aop.xml file and specifying does finally work!


          So now the question becomes why does using the <exclude> tag in the plugin options not work, and I am still required to use the extra aop management to run JUnit tests? It would appear that there is something that is not working between maven and AJDT. It also means that for my project to be portable (to others working on it), I now need to share my .project which is something I prefer not doing considering that my pom.xml is supposed to have the complete project configuration.

          Any suggestions?

          Thanks,

          Eric

          Comment


          • #6
            Hi Eric,

            I saw you also posted to the AJDT mailing list today - those posts are typically handled by the same group of us that hang out here on the STS forum. We do make it over to stackoverflow but not regularly.

            So, you have it working with -xmlConfigured and an aop.xml - so it is what we thought it was, that is good.

            In the maven scenario - do I assume you are using the 'full maven' support in STS? So you are using maven to build the project rather than having just run 'mvn eclipse:eclipse' and importing the result. In this case I am expecting the maven2Builder (in .project) to build the code - and not the ajbuilder.

            Are you finding you have both these builders in your .project file?

            If you remove the ajbuilder entry, do things improve?

            With both of them active, they'll both need configuring (the exclude section in the pom for maven and the -xmlConfigured for the ajbuilder)

            Andy

            Comment


            • #7
              Originally posted by Andy Clement View Post
              I saw you also posted to the AJDT mailing list today - those posts are typically handled by the same group of us that hang out here on the STS forum. We do make it over to stackoverflow but not regularly.
              Sorry; I didn't realize that. I didn't want to add congestion to the STS forum with what appeared to be an m2e/AJDT issue. But if it is the same people, I would rather just keep everything centralized in one place here.

              So, you have it working with -xmlConfigured and an aop.xml - so it is what we thought it was, that is good.
              Yes - I have tried it in a couple of different sandboxes, and adding -xmlConfigured and a custom aop.xml does alleviate the problem.

              In the maven scenario - do I assume you are using the 'full maven' support in STS? So you are using maven to build the project rather than having just run 'mvn eclipse:eclipse' and importing the result. In this case I am expecting the maven2Builder (in .project) to build the code - and not the ajbuilder.
              I'm not entirely sure what you mean by "full maven support", but I am only using m2e to import and configure my .project files. I do not use `mvn eclipse:eclipse` at all.

              In my .project, I do have both ajbuilder and maven2Builder defined (I am posting the complete .project file here in case the natures have some bearing on this as well):
              Code:
              <?xml version="1.0" encoding="UTF-8"?>
              <projectDescription>
              	<name>LendingSimulationService</name>
              	<comment></comment>
              	<projects>
              		<project>CalculatorBlazeWrapper</project>
              	</projects>
              	<buildSpec>
              		<buildCommand>
              			<name>org.eclipse.wst.jsdt.core.javascriptValidator</name>
              			<arguments>
              			</arguments>
              		</buildCommand>
              		<buildCommand>
              			<name>org.eclipse.ajdt.core.ajbuilder</name>
              			<arguments>
              			</arguments>
              		</buildCommand>
              		<buildCommand>
              			<name>org.eclipse.wst.common.project.facet.core.builder</name>
              			<arguments>
              			</arguments>
              		</buildCommand>
              		<buildCommand>
              			<name>org.eclipse.wst.validation.validationbuilder</name>
              			<arguments>
              			</arguments>
              		</buildCommand>
              		<buildCommand>
              			<name>org.eclipse.m2e.core.maven2Builder</name>
              			<arguments>
              			</arguments>
              		</buildCommand>
              	</buildSpec>
              	<natures>
              		<nature>org.eclipse.ajdt.ui.ajnature</nature>
              		<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
              		<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
              		<nature>org.eclipse.jdt.core.javanature</nature>
              		<nature>org.eclipse.m2e.core.maven2Nature</nature>
              		<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
              		<nature>org.eclipse.wst.jsdt.core.jsNature</nature>
              	</natures>
              </projectDescription>
              If you remove the ajbuilder entry, do things improve?
              Not really; in fact, if I remove the ajbuilder entry (ie: the entire AJ buildCommand block), then I find myself unable to build anything in the project. No errors are generated; just no class files are created. A little more playing around and I noticed that when I remove AJ Capability, the ajbuilder entry is removed, but a javabuilder entry is added. Of course, with just the javabuilder entry in place (ie: no AJ Capability enabled on the project), the test runs as expected, but I do not get my AJ aspects woven. I even added an <include>**/*.aj</include> block to the aspectj-maven-plugin to be certain, but the aspect is still not run.

              With both of them active, they'll both need configuring (the exclude section in the pom for maven and the -xmlConfigured for the ajbuilder)
              I have no issues with configuring the pom for the maven builder, but I would have expected the ajbuilder configuration to be extracted from the maven configuration directly. One of the fantastic things with Maven and the m2e plugins is that I can easily share my source code with anyone else using any other IDE and be confident that it is built the same way. I don't have to worry about individual project configurations (ex: in Eclipse, make sure you do ..... And in Netbeans make sure you do .... and in IntelliJ make sure you do ....). However, if I need to configure the ajbuilder independently, I lose that flexibility.

              Is this a bug of the m2e AJDT plugin or a configuration problem on my side?

              Thanks,

              Eric

              Comment


              • #8
                After puzzling through it, I think I can see what is happening here.

                The exclude configuration in the pom is for excluding files from compilation AND weaving. The -xmlConfigured option in Eclipse is only for configuring files to exclude from weaving, they are still compiled. The exclude section from a pom could map onto a build path exclude in eclipse but then your spring aspect wouldn't be getting compiled (and so spring weaving wouldn't work because it couldn't find it).

                So, (1) it is probably a missing piece of configurator functionality that it is not mapping the pom exclude to a build path exclude.

                But if it did, that wouldn't sort out your problem as the aspect wouldn't be getting compiled.

                (2) the aspectj maven plugin needs a way to express that certain classes should be excluded from weaving (but not from compilation). Once this exists the configurator can be extended to support it.

                Basically by manually configuring -xmlConfigured you are making up for the missing pom config (and related configurator) support.

                > I would have expected the ajbuilder configuration to be extracted from the maven configuration directly.

                Yep, I agree with that. When I get a minute I'll raise some jiras for my pieces of that but at the moment we don't own the aspectj maven plugin so aren't responsible for it (we keeping thinking we should pick it up, just haven't had the time).

                Hope some of that makes sense, even though it may not be the ideal answer right now.

                cheers,
                Andy

                Comment


                • #9
                  Thanks for the insight. That actually makes a lot of sense. I don't know who owns the plugin, hence my scattering of posts here and there trying to find the right group(s).

                  Please post the Jira issues once you've opened them so I can keep track of them, and so can others if they find this thread.

                  In the meantime, looks like my Junit will just fail within Eclipse (unless team members understand how to properly configure the project).

                  Thanks again!

                  Eric

                  Comment

                  Working...
                  X