Search code examples
javamavenaopaspectjaspectj-maven-plugin

AspectJ @DeclareParents defaultImpl code is not used when using it as dependency


I am working with AspectJ at the moment. I seperated AspectJ code in a dependency. Within that dependency everything works as intended. But as soon as I import it in another project only some functionality does not work anymore. When using the defaultImpl of @DeclareParents, the interface is shown within the compiled code but not the default Implementation. Here is my code to show what I mean (every code snippet is its own File):

AspectJ code:

public interface IAspect
{
    String hello();
}

public class IAspectDefaultImpl implements IAspect
{
    @Override
    public String hello()
    {
        return "hello";
    }
}
@Aspect
public class AspectJ
{

    @DeclareParents(value = "@SomeAnnotation*", defaultImpl = IAspectDefaultImpl.class)
    private IAspect implementedInterface;
}

Target Class in a different project:

@SomeAnnotation
public class MyClass
{
    private final int myValue;

    public MyClass(final int wert)
    {
        this.myValue = wert;
    }


    public int getMyValue()
    {
        return myValue;
    }
}

Maven throws me:

The type MyClass must implement the inherited abstract method IAspect.hello()

Which implies that it works partially. When looking at the decompiled .class files the targeted Class does in fact implement IAspect. The method defined in IAspectDefaultImpl is still missing tho.

My pom is set up like in this example.

I am not sure where I should start to look for errors. Any help is apreciated.


Solution

  • Thanks for the MCVE. But hey, you don't use Git in order to commit 7z or ZIP archives, you ought to commit source code. I forked your project and fixed that, restructured and simplified your POMs and also fixed the main problem.

    See my pull request and the commits in it for further details.


    Concerning your problem, I can confirm that it occurs if you use @DeclareParents the way you do in an aspect library.

    Actually, according to AspectJ maintainer Andy Clement there are certain problems with @DeclareParents when using it to provide parent interfaces + implementations in annotation style. The native AspectJ syntax via declare parents is not affected by that, but for annotation-style syntax Andy provided an alternative called @DeclareMixin, see the AspectJ manual. There he mentions that he is even considering to deprecate the defaultImpl argument of @DeclareParents in favour of @DeclareMixin.

    So my bugfix (or workaround) for your problems is to actually replace

    @DeclareParents(value = "@de.example.aspect.SomeAnnotation *", defaultImpl = IAspectDefaultImpl.class)
    private IAspect implementedInterface;
    

    by

    @DeclareMixin("@de.example.aspect.SomeAnnotation *")
    public static IAspect createIAspectImplementation() {
        return new IAspectDefaultImpl();
    }
    

    This works with aspect libraries.

    I will discuss with Andy about whether it makes sense to file a bug ticket for your problem or if he won't fix it anyway because there is a viable and recommended alternative.