Bug 160469 - Wrong relationship information when binary weaving
Summary: Wrong relationship information when binary weaving
Status: REOPENED
Alias: None
Product: AspectJ
Classification: Tools
Component: IDE (show other bugs)
Version: DEVELOPMENT   Edit
Hardware: PC Windows XP
: P5 normal (vote)
Target Milestone: 1.5.3   Edit
Assignee: Helen Beeken CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks: 160236
  Show dependency tree
 
Reported: 2006-10-11 08:59 EDT by Matt Chapman CLA
Modified: 2009-08-30 02:50 EDT (History)
1 user (show)

See Also:


Attachments
zip containing fix and testcases (10.66 KB, application/zip)
2006-10-13 08:31 EDT, Helen Beeken CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Matt Chapman CLA 2006-10-11 08:59:46 EDT
Testcase: 

package test;

import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.transaction.annotation.Transactional;

@Configurable
public class Sample {

  public Sample() {
  }

  @Transactional
  public void main(String[] args) {
    System.err.println("Sample");
  }

}

Add spring.jar to classpath and spring-aspects.jar to aspectpath (Spring 2)

The AJDE structure model then looks like this:

      sourceOfRelationship bug160236.generated<test{Sample.java[Sample~Sample
          relationship advised by
              target beanCreation

      sourceOfRelationship bug160236.generated<test{Sample.java[Sample~main~\[QString;
          relationship advised by
              target AnnotationTransactionAspect.class

      sourceOfRelationship {AnnotationTransactionAspect.class
          relationship advises
              target main

      sourceOfRelationship bug160236.generated<org.springframework.beans.factory.aspectj[AnnotationBeanConfigurerAspect.class (binary)}AnnotationBeanConfigurerAspect+beanCreation
          relationship advises
              target Sample

The relationship for "main" advised by AnnotationTransactionAspect.class is as expected for binary weaving, but the other relationship comes out as "Sample" (the constructor) advised by beanCreation, which is a pointcut. As pointcuts
are not the source of advice, this is incorrect. Expected the constructor to be advised by "AnnotationBeanConfigurerAspect.class"

Unfortunately a cut-down version of the spring aspects didn't show the problem.
Comment 1 Helen Beeken CLA 2006-10-12 07:16:48 EDT
The reason for the wierdness is that the after returning advice in AbstractBeanConfigurerAspect is on the same line as the concrete pointcut beanCreation in the AnnotationBeanConfigurerAspect. It is this which is causing the confusion. I can now reproduce with a simplified testcase :-)

One other thing - if we have source for everything (aspects and Simple class) then the structure model is:

     sourceOfRelationship in.one.project.generated<pkg*AbstractBeanConfigurerAspect.aj}AbstractBeanConfigurerAspect&afterReturning
          relationship advises
              target Simple

      sourceOfRelationship in.one.project.generated<test{Simple.java[Simple~Simple
          relationship advised by
              target afterReturning

Therefore, it seems to me that in the binary case we expect the constructor to also be advised by the AbstractBeanConfigurerAspect and not the concrete AnnotationBeanConfigurerAspect.
Comment 2 Helen Beeken CLA 2006-10-12 07:41:34 EDT
Given the following code:

---------------------------------------------------------------
public abstract aspect AbstractBeanConfigurerAspect {

	// advice starts on line 6
	after() returning : beanCreation() {
	}
	
	protected abstract pointcut beanCreation();

	before() : beanCreation() {
		
	}	
}

public aspect AnnotationBeanConfigurerAspect extends AbstractBeanConfigurerAspect {
	
	// pointcut is on line 6
	protected pointcut beanCreation() : initialization(*.new(..)) && !within(pkg.*);
}

public class Simple {

	public Simple() {	
	}
	
}
------------------------------------------------------------------

In the case when this is all in the same package, the ajde structure model is:

      sourceOfRelationship in.one.project.generated<pkg*AbstractBeanConfigurerAspect.aj}AbstractBeanConfigurerAspect&before!2
          relationship advises
              target Simple

      sourceOfRelationship in.one.project.generated<test{Simple.java[Simple~Simple
          relationship advised by
              target afterReturning

      sourceOfRelationship in.one.project.generated<test{Simple.java[Simple~Simple
          relationship advised by
              target before

      sourceOfRelationship in.one.project.generated<pkg*AbstractBeanConfigurerAspect.aj}AbstractBeanConfigurerAspect&afterReturning
          relationship advises
              target Simple

With the aspects in a jar file on the aspect path of the project containing Simple.jave, the ajde structure model is currently:

      sourceOfRelationship test2.generated<test{Simple.java[Simple~Simple
          relationship advised by
              target beanCreation

      sourceOfRelationship test2.generated<test{Simple.java[Simple~Simple
          relationship advised by
              target AnnotationBeanConfigurerAspect.class

      sourceOfRelationship test2.generated<pkg[AnnotationBeanConfigurerAspect.class (binary)}AnnotationBeanConfigurerAspect+beanCreation
          relationship advises
              target Simple

      sourceOfRelationship {AnnotationBeanConfigurerAspect.class
          relationship advises
              target Simple

In other words - there are two things which need fixing:

1. Simple should be advised by AbstractBeanConfigurerAspect and not AnnotationBeanConfigurerAspect
2. Can't be advised by a pointcut (although this might be fixed as a side effect of (1).
Comment 3 Helen Beeken CLA 2006-10-12 11:12:13 EDT
I think the reason this bug is occuring is that the implementation of Advice.getResolvedDeclaringAspect() is wrong. According to the javadoc of the abstract method ShadowMunger.getResolvedDeclaringAspect():

   /**
     * Returns the ResolvedType corresponding to the aspect in which this
     * shadowMunger is declared. This is different for deow's and advice.
     */

However, the implementation in Advice.java returns 'concreteAspect' (the aspect extending the aspect which defines the advice), even though Advice.getDeclaringAspect() returns the UnresolvedType corresponding to the abstract aspect in which the advice is defined. 

Note: The method getResolvedDeclaringAspect() is only used within the code which fills in the model for injar aspects
Comment 4 Helen Beeken CLA 2006-10-13 08:27:12 EDT
The fix turns out to be even more simple.....(and nicer :-))

When aspects are read in from jar files the advice is looked at and each piece of advice is allocated a declaring type. In other words, the advice knows which aspect it is declared in. In the case of advice within abstract aspects the advice knows it's declared in this abstract one. When we come to add this information to the crosscutting set we concretize each piece of advice. In this process we create a new advice object but fail to pass on the information about which type it was declared in. This is the reason why when we come to fill in the injar hierarchy the advice doesn't have a declaring type. Passing on this information in the concretization step fixes this. Consequently the whole "getResolvedDeclaringAspect" thing is redundant and can be removed. Instead, the declared type can be used both with advice and deow.
Comment 5 Helen Beeken CLA 2006-10-13 08:31:41 EDT
Created attachment 51925 [details]
zip containing fix and testcases

This zip contains the fix described above and tests:

1. pr160469-weaver.txt: apply to the weaver project. 
2. pr160469-tests.txt: apply to the tests project
3. jar_1\aspects.jar: place the aspects.jar file in the tests\model\pr160469_1 directory
4. jar_2\aspects.jar: place the aspects.jar file in the tests\model\pr160469_2 directory

(note jar_1 and jar_2 dirs were only created so I could attach everything within the same zip - do not create these directories in the pr160469_1 and pr160469_2 directories)
Comment 6 Helen Beeken CLA 2006-10-13 08:43:24 EDT
There is one final aspect to this bug which needs further thought.....with the patch in comment #5 applied the model entry for the abstract pointcut beanCreation (see comment #2) is:

        beanCreation()  [pointcut] TEST_SANDBOX\aspects.jar!pkg\AbstractBeanConfigurerAspect.class:1:

However, the line number is incorrect. 
Comment 7 Andrew Clement CLA 2006-10-16 09:01:01 EDT
patches from comment #5 are in
Comment 8 Helen Beeken CLA 2006-10-18 07:59:29 EDT
Getting the pointcut location correct is more involved. Since the pointcut in the abstract aspect is a MatchesNothingPointcut we don't record any information about its location in the class file. Therefore, when we come to read it in we have no idea where in the source file the pointcut was.
Comment 9 Helen Beeken CLA 2006-10-18 08:49:07 EDT
For the moment it's not worth fixing the line number of the pointcut within the abstract aspect since this is only going to cause a problem if the "uses pointcut/pointcut used by" relationship is reinstated (bug 148027). With the patch committed in comment #7 I'm closing this as resolve later.

This fix is in the latest aspectj dev build and will be in the next ajdt 1.4 and 1.5 dev builds.
Comment 10 Eugene Kuleshov CLA 2006-10-18 09:20:53 EDT
Helen, can you please clarify what exactly need to be fixed later? 

I am not sure why recorded pointcut is MatchesNothingPointcut. One would expect compiler to resolve it from the super classes/aspects, since code is actually woven in.
Comment 11 Helen Beeken CLA 2006-10-18 09:57:02 EDT
The abstract pointcut beanCreation in AbstractBeanConfigurerAspect (see comment #2) never matches any join points because it has no body. It is the concrete pointcut within AnnonationBeanConfigurerAspect that matches.

Currently when run within ajdt (or with the -emacssym option) a structure model is created that represents the crosscutting information. It is this information that AJDT uses for populating it's views. Up until the fix for bug 145963 the relationship information was only known for the current project. This had the limitation within AJDT that you weren't able to navigate to aspects that were on the aspectpath. Bug 145963 means that the model is now filled in for aspects on the aspectpath. Currently, we only fill in the information about advice, pointcuts and declare error and declare warning statements. In the case of an abstract pointcut we don't know the correct line number this was in the file since this isn't currently recorded in the class file and so can't set this piece of information correctly. However, the main user of this functionality is AJDT and AJDT only needs to know the line number to enable navigation for relationships. At the moment there is no relationship related to pointcuts and so there is no necessity to ensure the line number for the pointcut is correct. If a relationship relating to pointcuts is introduced in the future we will look at implementing what is required to ensure the line number for abstract pointcuts is correct. At the moment this is a fair amount of work (with the added complication that it could be changing the information saved in the class file) for no gain. Therefore, I closed this bug as "later" to indicate that if there is a use case for the pointcut work we will fix it when that use case becomes clear.

I hope this answers your questions :-)
Comment 12 Eugene Kuleshov CLA 2006-10-18 10:05:08 EDT
Well, almost. I just wonder if you can't record the line number, maybe it is at least possible to record class name that contains an applied aspect.

I also wonder if there could be some kind of signature for advice that is applied at given joinpoint, so there will be no need to track down line numbers...
Comment 13 Helen Beeken CLA 2006-11-09 06:47:37 EST
iplog
Comment 14 Eclipse Webmaster CLA 2009-08-30 02:50:33 EDT
LATER/REMIND bugs are being automatically reopened as P5 because the LATER and REMIND resolutions are deprecated.