Motomine
Motomine

Reputation: 4504

Call a setter to a field which is annotated with AspectJ

I want to intercept all assignments to a field which is annotated with MyAnnotation in this case. If it works when the value is assigned with reflction is much better. This is what I tried, but it does not run, and I think that something else might be wrong:

public privileged aspect MyAnnotationAspect {

    pointcut hasAnnotation(MyAnnotation annotation) : @annotation(annotation);

    pointcut methodExecution() : execution(* *(..));

    Object around(MyAnnotation annotation) : set(String word) && methodExecution() && hasAnnotation(annotation) {
        Object result = null;
        try {
            result = proceed(annotation, "new"); //Just to try I want to assign "new" instead of the variable word
        } catch (Throwable ex) {
            throw new RuntimeException(ex);
        }
        return result;
    }

}

It says that are too many arguments for the method proceed. Can anyone help me? Thank you!

EDIT

Now it throws "Warning:(10, 0) ajc: advice defined in aspects.AnnotationAspect has not been applied [Xlint:adviceDidNotMatch]"

This is my aspect:

public aspect AnnotationAspect {

    pointcut hasAnnotation(Annotation annotation) : @annotation(annotation);

    Object around(Annotation annotation, String word) : hasAnnotation(annotation) && set(String *) && args(word) {
        Object result = null;
        System.out.println(thisJoinPoint);
        try {
            result = proceed(annotation, "intercepted");
        } catch (RuntimeException ex) {
            throw ex;
        }
        return result;
    }
}

This is the annotation:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Annotation {
}

I have a dummy in order to test it:

class DummyEntity{

  @Annotation
  var name: String =_

  def setName(n: String): Unit ={
    name = n
  }
}

And this is the test where I'm testing it:

public class AnnotationAspectTest {

    private DummyEntity dummyEntity;

    @Before
    public void setUp(){
        dummyEntity = new DummyEntity();
    }

    @Test
    public void testing(){
        dummyEntity.setName("newName");
        Assert.assertEquals("intercepted", dummyEntity.name());
    }
}

Upvotes: 0

Views: 1022

Answers (1)

kriegaex
kriegaex

Reputation: 67297

The methodExecution() is counter-productive here because you do not want to capture method executions, but field write access. Because set(..) && execution(..) are mutually exclusive, this makes no logical sense.

Furthermore, you need to bind the assigned value to a parameter via args() in order to be able to modify it.

package de.scrum_master.aspect;

import de.scrum_master.app.MyAnnotation;

public aspect MyAnnotationAspect {
  Object around(MyAnnotation annotation, String word) :
    @annotation(annotation) && set(String *) && args(word)
  {
    System.out.println(thisJoinPoint);
    Object result = null;
    try {
      result = proceed(annotation, "altered value");
    } catch (Throwable ex) {
      throw new RuntimeException(ex);
    }
    return result;
  }
}

Upvotes: 1

Related Questions