Search code examples
javaspringvaadinaspectjspring-aop

Is it possible to use AOP on the Button click event in Vaadin?


I’m working on a Vaadin application, and I want to use an @Around aspect to intercept the method call when a Vaadin button is clicked. Specifically, I’d like to log information about the button click event. How can I achieve this using Spring AOP and the @Around advice? Or is this even possible?

My current demo project looks like this:

AspectDemoApplication.java:

package com.example.aspectdemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@SpringBootApplication
@EnableAspectJAutoProxy
public class AspectDemoApplication {

  public static void main(String[] args) {
    SpringApplication.run(AspectDemoApplication.class, args);
  }

}

ClickInformation.java:

package com.example.aspectdemo.config;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

import java.util.Arrays;

@Aspect
@Component
@Slf4j
public class ClickInformation {

  @Around("execution(* com.vaadin.flow.component.ComponentEventListener+.onComponentEvent(..))")
  public Object logClickInformation(ProceedingJoinPoint pjp) throws Throwable{
    String method = pjp.getSignature().getName();
    String targetClass = pjp.getTarget().getClass().getName();
    String params = Arrays.toString(pjp.getArgs());
    String msg = """
                      target: %s
                      method: %s
                      parameters: %s
                    """.formatted(targetClass, method, params);
    log.info(msg);
    return pjp.proceed();
  }
}

MainView.java:

package com.example.aspectdemo.ui;

import com.vaadin.flow.component.ClickEvent;
import com.vaadin.flow.component.ComponentEventListener;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.Route;

@Route("")
public class MainView extends VerticalLayout {


  public MainView() {
    initUI();
  }

  public void initUI () {
    btnTest1 = new Button("Test1");
    btnTest2 = new Button("Test2");

    btnTest1.addClickListener(new ComponentEventListener<ClickEvent<Button>>() {

      @Override
      public void onComponentEvent(ClickEvent<Button> buttonClickEvent) {
        System.out.println("Button Test1 clicked");
      }
    });

    btnTest2.addClickListener(new ComponentEventListener<ClickEvent<Button>>() {

      @Override
      public void onComponentEvent(ClickEvent<Button> buttonClickEvent) {
        System.out.println("Button Test2 clicked");
      }
    });

    this.add(btnTest1, btnTest2);
  }


  public Button btnTest1;
  public Button btnTest2;

}

What I'm trying to achieve is to log information of the button click method call of every button click in the view using Aspect. I hope this makes it more clear.Am I missing something or is it just not possible? Thanks for your help in advance!

Best regards.


Solution

  • Spring AOP works, as implied by the name and documented, only for Spring-managed beans or components (@Component, @Bean, @Service etc.). Your anonymous listener classes are not spring-managed. Hence, Spring AOP cannot intercept them. Either make sure your target classes are in fact Spring-managed or switch to native AspectJ.