Bug 169699 - Is there any particular order in ITD?
Summary: Is there any particular order in ITD?
Status: NEW
Alias: None
Product: AspectJ
Classification: Tools
Component: Compiler (show other bugs)
Version: 1.5.3   Edit
Hardware: PC Linux
: P3 normal with 1 vote (vote)
Target Milestone: ---   Edit
Assignee: aspectj inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-01-05 11:17 EST by Paulo Zenida CLA
Modified: 2013-06-24 11:04 EDT (History)
1 user (show)

See Also:


Attachments
Simple testcase (3.09 KB, application/octet-stream)
2007-01-08 06:07 EST, Matthew Webster CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Paulo Zenida CLA 2007-01-05 11:17:11 EST
Hello there,

I was wondering if there is any particular order when different  
aspects inject annotations in particular constructors and methods or  
if there are possible conflicts when more than one aspect perform  
injection of annotations, when that injection depends on the existence  
or absence of another annotation. Something like "declare foo() as  
@AccessControlled if foo() is not already @AccessControlled nor  
@NotAccessControlled".

I am facing a strange behaviour which, unfortunately, I wasn't able to  
replicate in a small example... Anyway, I will try to explain the idea:

I have two projects: one project base, where I have a few generic  
aspects deployed in a jar file which is used in another concrete  
project.

In "base", I have an abstract aspect with the following declaration:

public abstract aspect AccessController<CurrentPrincipal> implements  
IAccessController<CurrentPrincipal>, IAccessControllerForQuerying,  
IAccessControllerForModifying {

  ...

    declare @constructor :
        !@AccessControlled !@NotAccessControlled !private  
(@AccessControlled *..*.*+).new(..) :
        @AccessControlled(inherited = true);

  ...

}

In "concrete", we have the aspect that extends and thus enables the  
aspect AccessController:

public aspect Concrete extends AccessController<User> {

  ...

}

Then, I create an aspect that injects annotations on my code, such as:

public aspect AccessControlRequirementsDeclarator {

    declare @type :
        pt.iscte.ciiscte.heliopolis.business.manager.AnnouncementManager :
            @AccessControlled("manage_news");

    declare @type :
        pt.iscte.ciiscte.heliopolis.business.manager.PersonManager :
            @AccessControlled("manage_people");

}

The previous works fine. However, if I try to add @NotAccessControlled  
annotations before those definitions, such as,

...

declare @constructor :
    public pt.iscte.ciiscte.heliopolis.business.manager.*.new(..) :
        @NotAccessControlled;

...

the result gets different each time I compile the application. E.g., I  
created a custom message handler that counts all distinct affected  
join points by AccessController, and the number of advised join points  
gets different with each compilation (in my case, I had 41 and 35  
different advised join points). Moreover, using reflection, I have  
realized that sometimes, my methods have both annotations. Does this  
means that the aspect Concrete was processed before? Still, I tried  
another definition for the not access controlled points, like:

declare @constructor :
    !@NotAccessControlled !@AccessControlled public  
pt.iscte.ciiscte.heliopolis.business.manager.*.new(..) :
        @NotAccessControlled;

but I had the same strange problems. Finally, something that also  
sounds really strange is that the number or declare @xxxx seems to  
have effect on the weaving result. Any ideas about what this might be?  
(I have the latest stable version of the AspectJ compiler - AspectJ  
1.5.3, November 23, 2006, in http://www.eclipse.org/ajdt/downloads/).

Thank you all for your interest.

By the way, happy new year to you all.

Paulo Zenida
Comment 1 Matthew Webster CLA 2007-01-08 06:07:34 EST
Created attachment 56542 [details]
Simple testcase
Comment 2 Matthew Webster CLA 2007-01-08 09:48:54 EST
In the testcase the pointcut in Tracing matches methods with the @Include annotation. The DeclareInclude aspects adds @Include to HelloWorld.main() but only if it doesn't have the @Exclude annotation. If this annotation is added manually there is no match (as expected) but if added my DeclareExlude the @Include annotation _is_ added and the pointcut in Tracing matches. This would seem to be a bug i.e. DeclareInclude should _not_ add the annotation.
Comment 3 Andrew Clement CLA 2007-01-08 10:18:45 EST
In Matthews case there is a case of ambiguity that we don't currently recognize:

public aspect DeclareExclude {
        declare @method : !@Exclude public void main(..) : @Exclude ;
}

public aspect DeclareInclude {
        declare @method : !@Exclude public void main(..) : @Include;
}

Both targetting the same method ... if the first one is processed first, the second one won't match.  If the second one is processed first, they will both match.  No precedence is specified - but even if it were I don't think it would make this work reliably (at the moment).  This goes back to a long discussion on the hasmember() bug report relating to a proper ordering of processing ITDs and how to identify situations like this (see, for example bug 86818 comment #12 step 3)
Comment 4 Paulo Zenida CLA 2009-05-08 15:52:09 EDT
Hello there.

Are there any news regarding this issue? 

I am working in a project, again, related to access control, and I am still facing some problems related to this bug. I have the following code in an Aspect called AccessControlAnnotationsInjector.

declare @method : !@AccessControlled !@NotAccessControlled !private * (@AccessControlled *..*+).*(..) : @AccessControlledInherited;

declare @method : !@AccessControlled !@NotAccessControlled !private * (@AccessControlled *..*+).*(..) : @AccessControlled;

I guess the strange behavior of my client code (read strange here as random) is related to the order of the code injection. I suppose that, sometimes the second line is processed prior to the first one. When that happens, my method won't have the annotation @AccessControlledInherited, causing my application not to behave as expected.

When the previous lines are in the same aspect unit, don't they execute always the same way? What I mean is, don't they execute in the order they are declared in the file?

Thank you for your attention.
Comment 5 Andrew Clement CLA 2009-05-08 17:26:14 EDT
I imagine the statements are added to a collection and due to them possibly being allocated in different areas of memory on each run, the order in which the collection is processed can change.  So the behaviour is undefined.

I suppose for statements like this from different files there should be an ambiguity error whilst for statements within one file we could use the defined ordering.
Comment 6 Andrew Clement CLA 2009-05-08 17:36:26 EDT
and maybe declare precedence can help prevent the ambiguity error for the multiple file case.
Comment 7 Paulo Zenida CLA 2009-05-13 04:49:19 EDT
I agree with the behavior you specified: 
 - "for statements within one file we could use the defined ordering"
 - "maybe declare precedence can help prevent the ambiguity error for the
multiple file case"

Have you any ideas if this will be implemented soon? At the moment, I have disabled the functionality in my project related to the injection of annotations. But I'd like to know if I need to rethink this functionality or if I can wait for updates on this issue.

Thanks, once again, for your attention and quick feedback.

Comment 8 Andrew Clement CLA 2009-05-13 12:50:46 EDT
Hi Paulo,

I don't think it will be done soon, it needs more thinking.

Bug 86818 (an old one) covers some thinking about doing the right thing for declares in the general case (see around comment 9 in that bug).

Comment 9 Andrew Clement CLA 2013-06-24 11:04:46 EDT
unsetting the target field which is currently set for something already released