Bug 271388 - Support more flexible project weaving model (vs inpath & aspectpath)
Summary: Support more flexible project weaving model (vs inpath & aspectpath)
Status: NEW
Alias: None
Product: AJDT
Classification: Tools
Component: Core (show other bugs)
Version: unspecified   Edit
Hardware: All Windows XP
: P3 enhancement (vote)
Target Milestone: ---   Edit
Assignee: AJDT-inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2009-04-06 19:08 EDT by Neale Upstone CLA
Modified: 2010-06-16 18:12 EDT (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Neale Upstone CLA 2009-04-06 19:08:09 EDT
[I'm not sure where this will lead, but I think it's worth starting a discussion given the breadth of weaving scenarios now in existence.]

The scenarios in which aspects are compiled and woven can be somewhat complex, with aspects being able to be woven at compile time, load time, or even both, but also being able to be woven in the relatively complex relationships of OSGi dependencies with Equinox Aspects (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=255682#c18)... and I haven't dared go looking for what Spring dm Server's take on EA's configuration is likely to be.

I think it's therefore worth considering what relationships exist that are equivalent in different environments, or perhaps could be.

When using AspectJ (ajc/iajc) to compile projects, we typically would specify:
- classpath: classes and jars that do not need to be woven and don't contributes aspects
- aspectpath: read-only classes and jars that contribute aspects we want to use for weaving
- inpath: pre-compiled classes and jars to be used for weaving and to be woven (and re-woven?) into
- sources: .java and .aj files that need compiling before they can be woven

These, as far as I understand, are used in the following way:
- Things that are not modified, nor contribute aspects:
  - classpath: as with javac, these are read-only java classes which we normally just need to be able to compile java.  Under ajc, we also need them to be able to establish what types within inpath and sources are candidates for weaving where a pointcut matches part of a type heirarchy.

- Things that contribute aspects
  - aspectpath, inpath and compiled sources

- Things that get woven
  - inpath and compiled sources

The output that results is therefore a folder, or jar (if outputjar is specified) containing woven .classes from the inpath and sources.

[Deep breath - maybe this should be a blog post...]

The above gives us all the tools we need to create an Ant build to compile our aspects and weave them into any existing code, and to output those to woven jars in the granularity we want [something that is actually pretty easy to set up].

However, if we want to do the above on an existing project using AJDT, and that project includes libraries, some of which we want to weave, then things get a bit tricky.

Consider the following two projects:
  org.foo.base [JDT]
   /src/ClassA.java etc
   /lib/boring.jar
   /lib/interesting.jar
and
  org.bar.cleverstuff [AJDT]
   /aspects/Trace.aj, OnlyForInteresting.aj

Our application is the result of weaving cleverstuff into interesting.jar and org.foo.base/src/*, and boring.jar is not something we're looking to trace.

org.foo.base happens to be a project that is used in a non-AJ context most of the time, hence we keep it as a JDT project.

How do we configure our AJDT project to give us what we want, such that the correct woven classes end up in a JAR export, or included as JARs in a web project that depends on cleverstuff?

The obvious approach is to put org.foo.base and org.foo.base/lib/interesting.jar in the inpath of cleverstuff, but this then leaves us with lots of warnings about AJ not being able to resolve the classes where base/src or base/lib/interesting.jar reference base/lib/boring.jar's classes.  We clearly need to add boring to cleverstuff's classpath.

AJ needs (quite understandably) to be able to see all of base's classpath, some on inpath and some on classpath (otherwise we end up with missingType lint errors)

So.  A first enhancement could be: Can we automate the use of classpath elements for inpath projects?


That'll do me for now.  What interests me next is how the above scenario maps on to tooling for LTW and Equinox Aspects deployment.
Comment 1 Andrew Eisenberg CLA 2009-04-06 20:03:44 EDT
(In reply to comment #0)
> - Things that contribute aspects
>   - aspectpath, inpath and compiled sources

I think that you mean to exclude in path here.


> So.  A first enhancement could be: Can we automate the use of classpath
> elements for inpath projects?

AJDT has full control over what in/aspect/classpath it hands to the compiler.  So, it could be possible that AJDT can recursively look at projects on the inpath and add all of its classpath elements to the classpath (regardless of whether or not it is actually exported).

The nice thing about this is that from JDT's point of view, these extra secret classpath entries won't bleed into the editor because JDT does not use AJDT's classpath resolution.  (I think this is the case, I obviously have not tried it out.)

Would this be sufficient to solve the problem?

Let's go back to your example

org.foo.base [JDT]
   /src/ClassA.java etc (exported)
   /lib/boring.jar  (not exported)
   /lib/interesting.jar  (exported)
and
  org.bar.cleverstuff [AJDT]
   /aspects/Trace.aj, OnlyForInteresting.aj

boring.jar would be on cleverstuff's classpath when sent to the compiler, but it would not be on the classpath for things like name resolution and reconciling.  So, any references to BoringClass.java in cleverstuff would be an error.

> 
> 
> That'll do me for now.  What interests me next is how the above scenario maps
> on to tooling for LTW and Equinox Aspects deployment.
> 
This is interesting...

Comment 2 Neale Upstone CLA 2009-04-07 13:51:32 EDT
(In reply to comment #1)
> (In reply to comment #0)
> > - Things that contribute aspects
> >   - aspectpath, inpath and compiled sources
> 
> I think that you mean to exclude in path here.

Mmm... that's what I thought until I read example 2.3 at http://www.eclipse.org/aspectj/doc/released/devguide/ajc-ref.html: "Aspects included in -inpath will be woven into like other .class files, *and they will affect other types as usual.*"

> 
> > So.  A first enhancement could be: Can we automate the use of classpath
> > elements for inpath projects?
> 
> AJDT has full control over what in/aspect/classpath it hands to the compiler. 
> So, it could be possible that AJDT can recursively look at projects on the
> inpath and add all of its classpath elements to the classpath (regardless of
> whether or not it is actually exported).
> 
> The nice thing about this is that from JDT's point of view, these extra secret
> classpath entries won't bleed into the editor because JDT does not use AJDT's
> classpath resolution.  (I think this is the case, I obviously have not tried it
> out.)
> 
> Would this be sufficient to solve the problem?

Yes.  That sounds very elegant.  

> 
> Let's go back to your example
> 
> org.foo.base [JDT]
>    /src/ClassA.java etc (exported)
>    /lib/boring.jar  (not exported)
>    /lib/interesting.jar  (exported)
> and
>   org.bar.cleverstuff [AJDT]
>    /aspects/Trace.aj, OnlyForInteresting.aj
> 
> boring.jar would be on cleverstuff's classpath when sent to the compiler, but
> it would not be on the classpath for things like name resolution and
> reconciling.  So, any references to BoringClass.java in cleverstuff would be an
> error.
> 

Perfect.
Comment 3 Neale Upstone CLA 2009-04-07 14:04:43 EDT
(In reply to comment #1)
> 
> Let's go back to your example
> 
> org.foo.base [JDT]
>    /src/ClassA.java etc (exported)
>    /lib/boring.jar  (not exported)
>    /lib/interesting.jar  (exported)
> and
>   org.bar.cleverstuff [AJDT]
>    /aspects/Trace.aj, OnlyForInteresting.aj
> 
> boring.jar would be on cleverstuff's classpath when sent to the compiler, but
> it would not be on the classpath for things like name resolution and
> reconciling.  So, any references to BoringClass.java in cleverstuff would be an
> error.

There's an interesting puzzle here.  What if interesting.jar is not exported, but is on cleverstuff's inpath?

I think these two cases should be different.

1) interesting.jar is not exported, but is on cleverstuff's inpath.  
In this case, it may be fair to say that aspects should be able to weave into and call into cleverstuff, but other than that, the jar should remain private to base.
The effect of weaving when org.bar.cleverstuff.Main.main() gets called should be that the woven version only, appears on the classpath. 

2) interesting.jar is exported.
In this case, I think that adding the project, base, as a dependency (and hence to the inpath), will allow it to be woven.

But... what if we want to (I don't think AJDT supports this), have cleverstuff depend on base (or some other project), but explicitly never for weaving?  

I'd say this is where we get closer to what is being discussed in bug 255682.
Comment 4 Andrew Eisenberg CLA 2009-04-07 14:45:23 EDT
(In reply to comment #2)
> Mmm... that's what I thought until I read example 2.3 at
> http://www.eclipse.org/aspectj/doc/released/devguide/ajc-ref.html: "Aspects
> included in -inpath will be woven into like other .class files, *and they will
> affect other types as usual.*"

That's news to me.  Learn something new...

(In reply to comment #1)
> AJDT has full control over what in/aspect/classpath it hands to the compiler. 
> So, it could be possible that AJDT can recursively look at projects on the
> inpath and add all of its classpath elements to the classpath (regardless of
> whether or not it is actually exported).

The more I think about this, the more I am a little concerned that unexpected results can occur.  If a project uses a "secret" type that is magically added because of the inpath, then there will be no compiler errors for it.  Editor errors (ie- reconciling errors) will occur, but they will only be seen when the particular file is being edited.  

Of course, getting to this state will be difficult since these types are essentially invisible to the editor.  So, I don't know how big of a deal this is.

The ideal solution would be for the compiler to know that certain jars and binary folders exist for name resolution only, but cannot be directly referenced in the code being compiled.

(In reply to comment #3)
> > org.foo.base [JDT]
> >    /src/ClassA.java etc (exported)
> >    /lib/boring.jar  (not exported)
> >    /lib/interesting.jar  (exported)
> > and
> >   org.bar.cleverstuff [AJDT]
> >    /aspects/Trace.aj, OnlyForInteresting.aj
> > 
> 
> 1) interesting.jar is not exported, but is on cleverstuff's inpath.  
> In this case, it may be fair to say that aspects should be able to weave into
> and call into cleverstuff, but other than that, the jar should remain private
> to base.
Are you saying that interesting.jar has its own aspects that would weave into cleverstuff???  Why would you want to do that?  :)


> The effect of weaving when org.bar.cleverstuff.Main.main() gets called should
> be that the woven version only, appears on the classpath. 

Are you confusing the runtime classpath with the compile time classpath?  What happens at runtime depends on which version of interesting.jar is first on the classpath.  In eclipse, this distinction is somewhat murky because it hides runtime classpaths inside of launch configurations.  

If base is originally compiled using a non-woven version of interesting.jar, then it *should* (assuming you haven't written stupid aspects) run using a woven version of the jar.



> 
> 2) interesting.jar is exported.
> In this case, I think that adding the project, base, as a dependency (and hence
> to the inpath), will allow it to be woven.
Yes.

> 
> But... what if we want to (I don't think AJDT supports this), have cleverstuff
> depend on base (or some other project), but explicitly never for weaving?  
> 
I think this would be done by adding interesting.jar to the classpath, and have base on the inpath.  And inside of base, interesting.jar should not be exported.


> I'd say this is where we get closer to what is being discussed in bug 255682.
> 

Comment 5 Neale Upstone CLA 2009-04-08 08:51:59 EDT
(In reply to comment #4)
> (In reply to comment #2)
> > Mmm... that's what I thought until I read example 2.3 at
> > http://www.eclipse.org/aspectj/doc/released/devguide/ajc-ref.html: "Aspects
> > included in -inpath will be woven into like other .class files, *and they will
> > affect other types as usual.*"
> 
> That's news to me.  Learn something new...

Me too.  It would make inpath a binary version of a sourceroot as far as I can tell.


> The ideal solution would be for the compiler to know that certain jars and
> binary folders exist for name resolution only, but cannot be directly
> referenced in the code being compiled.

Agree. 

> 
> (In reply to comment #3)
> > 
> > 1) interesting.jar is not exported, but is on cleverstuff's inpath.  
> > In this case, it may be fair to say that aspects should be able to weave into
> > and call into cleverstuff, but other than that, the jar should remain private
> > to base.
> Are you saying that interesting.jar has its own aspects that would weave into
> cleverstuff???  Why would you want to do that?  :)

Nope.  Interesting.jar is just plain java, in my case it happens to be itext.jar for doing PDF generation.  

> 
> 
> > The effect of weaving when org.bar.cleverstuff.Main.main() gets called should
> > be that the woven version only, appears on the classpath. 
> 
> Are you confusing the runtime classpath with the compile time classpath?  What
> happens at runtime depends on which version of interesting.jar is first on the
> classpath.  In eclipse, this distinction is somewhat murky because it hides
> runtime classpaths inside of launch configurations.  

Nope. I meant the runtime classpath. I'd noticed that both appear, and that 'feature' is something I'd say is a bug.  What I'd love to see in the UI is that when we look at a launch configuration's runtime classpath, that we can see immediately where a component is the result of weaving.

> 
> If base is originally compiled using a non-woven version of interesting.jar,
> then it *should* (assuming you haven't written stupid aspects) run using a
> woven version of the jar.
Correct.  I don't think I've worked out how to write aspects that stupid ;)

> > 
> > 2) interesting.jar is exported.
> > In this case, I think that adding the project, base, as a dependency (and hence
> > to the inpath), will allow it to be woven.
> Yes.

> 
> > 
> > But... what if we want to (I don't think AJDT supports this), have cleverstuff
> > depend on base (or some other project), but explicitly never for weaving?  
> > 
> I think this would be done by adding interesting.jar to the classpath, and have
> base on the inpath.  And inside of base, interesting.jar should not be
> exported.

That was my hunch.

I think what I need to do next is to attach some projects where these use cases are needed, and have a look 'under the hood'.  Time will be a bit limited until after easter though.
Comment 6 Andrew Eisenberg CLA 2009-05-12 17:20:55 EDT
Bug 270554 has been fixed.  This bug allows you to specify that only certain jars in a classpath container should be included on the inpath/aspectpath.  So, the entire classpath container would be on your classpath, but you can specify that only a subset be on your inpath.

A small change and I could add the same functionality to projects as well.  It's still possible to get into tricky situations as you describe above, but I do think this would go a long way to solving many of the problems you describe.
Comment 7 Andrew Eisenberg CLA 2009-09-30 14:37:45 EDT
Move to the 2.0.2 release.
Comment 8 Andrew Eisenberg CLA 2010-04-28 19:25:42 EDT
Try to solve for 2.1.0.
Comment 9 Andrew Eisenberg CLA 2010-06-16 18:12:09 EDT
Determining what will be tackled for 2.1.1 release.