user4599075
user4599075

Reputation: 11

AspectJ declare parents JPanel+

I would like to make a few classes extending JPanel actually extend a class of my own in between.

So, I tried this:

public aspect MyAspect
{
   public static class MyPanel
         extends JPanel
   {
   }

   declare parents: JPanel+ extends MyPanel;
}

As is, it works. The only issue is that the aspect matches any class extending JPanel, whereas I want it to apply only on the JPanel+ classes from a package. So I tried this:

public aspect MyAspect
{
   public static class MyPanel
         extends JPanel
   {
   }

   declare parents: my.package..JPanel+ extends MyPanel;
}

and it doesn't match any JPanel+ at all ...

On the other hand I tried to target a particular JPanel+ class explicitly in a package from my.package.. and it works for this particular class, so the package path is understood by AspectJ.

I just don't understand why it won't work with my.package..JPanel+? Just my.package..JPanel (without the +) would be understandable as no JPanel exists there, but why doesn't my.package..JPanel+ work as expected (by me!)?

By the way, my.package..*_suffixFilterOnClassName works, but it really is not ideal in my opinion.

From https://eclipse.dev/aspectj/doc/released/adk15notebook/annotations-decp.html, I understand I could use an annotation as a workaround, but it's not that great either. But it would be better than just the suffix filtering.

Also, it would have been nice if the usual syntax within/withincode & so on from the pointcuts+declare warning+errors would work as for the others pointcuts, but as far as I understand the declare parents is implemented with TypePattern only!

Thanks in advance for any help!

Upvotes: 1

Views: 63

Answers (1)

kriegaex
kriegaex

Reputation: 67457

What you want is currently not possible using declare parents only, but there is a workaround, see below. my.package..JPanel+ means to look for subclasses of JPanel somewhere in a my.package, which is not where JPanel resides. So the pointcut is simply wrong. You also cannot combine the pointcut with something like within(my.package..*),but only use the naming patterns you already discovered.

There is, however, an undocumented ajc compiler parameter -xmlConfigured, which is also supported by AspectJ Maven Plugin, see here for details.

Update: AJC option -xmlConfigured is now documented here.

I have recorded as much as I know about -xmlConfigured in the old AspectJ Bugzilla issue 455014. Feel free to fully read it and also scroll to the bottom for updated links to mailing list posts no longer available under the old URLs.

What you specifically need is aspect scoping in aop.xml (Just Ctrl-F search for "scoping" on the page for follow-up information near the bottom).

I.e., something like your original declare parents: JPanel+ extends MyPanel incombination with that compiler switch and something like this in aop.xml should do the job:

<aspectj>
  <aspects>
    <aspect name="my.aspects.MyAspect" scope="my.package..*"/>
    <!-- other aspects go here, with or without scope -->
  </aspects>
</aspectj>

Update:

Actually, it is a mystery to me why JPanel+ extends MyPanel worked for you at all. For me it only does when compiling from Eclipse, but not when compiling from command line. Using ajc, there is a compilation error: 'javax.swing.JPanel'can not extend itself. I also do not see any obvious way to suppress it. The error is explained easily: SomeClass+ always includes SomeClass itself. Therefore, you will see this compilation error when using the command line or a build tool like Maven, Ant or Gradle.

As a workaround, I am using:

declare parents: (!@JavaBean JPanel+) extends MyPanel;

Or, if you want to be very precise:

declare parents: (!@JavaBean(defaultProperty = "UI", description = "A generic lightweight container.") JPanel+) extends MyPanel;

I got this idea, looking at the parent class JPanel:

@JavaBean(defaultProperty = "UI", description = "A generic lightweight container.")
@SuppressWarnings("serial") // Same-version serialization only
public class JPanel extends JComponent implements Accessible {
  // ...
}

You just need to make sure that your subclasses do not have the exact same annotation. BTW, you cannot use @SuppressWarnings for exclusion, because it has source retention.

Another thing I noticed is, that somehow scoping via aop.xml does not seem to be working for me. I will be busy today, so I am not sure when I can investigate this, but I want to look into it another time.


Update 2:

I experimented some more and found out that, as I also just wrote in a Bugzilla comment, aspect scoping never seems to have been implemented for ITD (inter-type declaration) and only has an effect on regular pointcuts. I.e., with regard to declare parents we are kind of back to square one, having to resort to naming patterns.

I created a feature request for XML-based aspect scoping to also work for ITD as AspectJ issue #253.

Upvotes: 0

Related Questions