Note that there are some explanatory texts on larger screens.

plurals
  1. POAOP or APT for overriding methods from super classes
    primarykey
    data
    text
    <p>I have a large library of wicket components that are annotated with a custom annotation <code>@ReferencedResource</code> or another annotation <code>@ReferencedResources</code>, that has a <code>ReferencedResouce[] value()</code> parameter to allow multiple annotations.</p> <p>Here is a sample code snippet:</p> <pre><code>@ReferencedResources({ @ReferencedResource(value = Libraries.MOO_TOOLS, type = ResourceType.JAVASCRIPT), @ReferencedResource(value = "behaviors/promoteSelectOptions", type = ResourceType.JAVASCRIPT) }) public class PromoteSelectOptionsBehavior extends AbstractBehavior{ ... } </code></pre> <p>So far, I use <a href="http://download.oracle.com/javase/6/docs/api/javax/annotation/processing/package-summary.html" rel="nofollow noreferrer">apt</a> to check that the referenced resources actually exist. E.g. </p> <pre><code>@ReferencedResource(value = "behaviors/promoteSelectOptions", type = ResourceType.JAVASCRIPT) </code></pre> <p>will cause a compilation failure unless the file <code>js/behaviors/promoteSelectOptions.js</code> can be found on the class path. This part works nicely.</p> <p>Now I am also a fan of DRY and I would like to use the same annotation to actually inject the resources into the Objects when they are created. Using AspectJ, I have implemented a part of this.</p> <p>The annotated Objects are always either instances of <a href="http://wicket.apache.org/apidocs/1.4/org/apache/wicket/Component.html" rel="nofollow noreferrer">Component</a> or <a href="http://wicket.apache.org/apidocs/1.4/org/apache/wicket/behavior/AbstractBehavior.html" rel="nofollow noreferrer">AbstractBehavior</a>.</p> <p>For components, things are easy, just match after the constructor. Here's an advice that does this:</p> <pre><code>pointcut singleAnnotation() : @within(ReferencedResource); pointcut multiAnnotation() : @within(ReferencedResources); after() : execution(Component+.new(..)) &amp;&amp; (singleAnnotation() || multiAnnotation()){ final Component component = (Component) thisJoinPoint.getTarget(); final Collection&lt;ReferencedResource&gt; resourceAnnotations = // gather annotations from cache this.getResourceAnnotations(component.getClass()); for(final ReferencedResource annotation : resourceAnnotations){ // helper utility that handles the creation of statements like // component.add(JavascriptPackageResource.getHeaderContribution(path)) this.resourceInjector.inject(component, annotation); } } </code></pre> <p>For behaviors however, I need to attach the resources to a response, not to the behavior itself. Here are the pointcuts I use:</p> <pre><code>pointcut renderHead(IHeaderResponse response) : execution(* org.apache.wicket.behavior.AbstractBehavior+.renderHead(*)) &amp;&amp; args(response); </code></pre> <p>And here is the advice:</p> <pre><code>before(final IHeaderResponse response) : renderHead(response) &amp;&amp; (multiAnnotation() || singleAnnotation()) { final Collection&lt;ReferencedResource&gt; resourceAnnotations = this.getResourceAnnotations(thisJoinPoint.getTarget().getClass()); for(final ReferencedResource resource : resourceAnnotations){ this.resourceInjector.inject(response, resource); } } </code></pre> <p>This also works nicely if the class overrides the <a href="http://wicket.apache.org/apidocs/1.4/org/apache/wicket/behavior/AbstractBehavior.html#renderHead%28org.apache.wicket.markup.html.IHeaderResponse%29" rel="nofollow noreferrer">renderHead(response)</a> method, but in many cases that's just not necessary because a super class already implements the base functionality while the child class only adds some configuration. So one solution would be to let these classes define a method like this:</p> <pre><code>@Override public void renderHead(IHeaderResponse response){ super.renderHead(response); } </code></pre> <p>I would hate this, because this is dead code, but currently this is the only working option I see, so I am looking for other solutions.</p> <p>EDIT:</p> <p>I have created a working solution using APT and sun javac calls. However, this leads to the next problem: <a href="https://stackoverflow.com/questions/3660547/apt-and-aop-in-the-same-project-using-maven">Running APT and AspectJ in the same project using maven</a>.</p> <p>Anyway, as soon as I have some free time, I'll post the answer to this question (or parts of it).</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload