Using @Async @EventListener inside Route Component

i was watching today this video https://www.youtube.com/watch?v=5YdjBWSGtbE.
it describes how you can use the Spring ApplicationEvent feature. i was thinking “great, time to replace google’s EventBus”, since its not recommended to use even by the own developers.

the code is quite simple. i replaced googles old “@Subscribe” annotation by springs “@EventListener” + “@Aysnc” annotations. and also actived the @Async" feature by adding “@EnableAsync” on my Springbootapplication class.

@Route("hello")
public class MyView extends VerticalLayout {

    @Async
    @EventListener
    public void handleEvent(NotificationEvent event) {
        accessUI(() -> Notification.show(event.getText(), 5000, Position.BOTTOM_END));
    }

    private void accessUI(Command command) {
        getUI().ifPresent(ui -> ui.access(command));
    }
}

i am getting an exception when i navigate to the route in the browser:

java.lang.ClassCastException: class jdk.proxy6.$Proxy201 cannot be cast to class com.vaadin.flow.component.Component (jdk.proxy6.$Proxy201 is in module jdk.proxy6 of loader org.springframework.boot.devtools.restart.classloader.RestartClassLoader @62ec2190; com.vaadin.flow.component.Component is in unnamed module of loader 'app')
    at com.vaadin.flow.router.internal.AbstractNavigationStateRenderer.sendBeforeEnterEvent(AbstractNavigationStateRenderer.java:550) ~[flow-server-24.3.2.jar:24.3.2]

when i comment out the “@Async” annotation i dont get this error. but then i can not handle the event in an async way?

Any ideas how to subscribe to events in a proper way on a vaadin view/route ?

using: spring boot 3.2.0
vaadin 24.3.2
java 21

You can’t: reason and workaround is described here https://github.com/vaadin/spring/issues/272

i see. i was browsing a bit the vaadin source code.

i guess i will stay on googles eventbus cause its doing exactly what is suggested as workaround. or i will try the “java.util.concurrent.Flow.Subscriber” as described in the github ticket. but i am not sure how to use it. the api looks a bit complicated for the simple task i need.

It kind of works when configuring the scope of the bean

But you have to add the ApplicationListener manually

And you get a warning

```Inner bean ‘ch.martinelli.demo.vaadin.views.GridView’ implements ApplicationListener interface but is not reachable for event multicasting by its containing ApplicationContext because it does not have singleton scope. Only top-level listener beans are allowed to be of non-singleton scope.````

The solution is to use EventBus like this, make it ApplicationScope bean when using Spring DI. Then you can autowire it to your Route’s etc. vaadin-create23/vaadincreate-ui/src/main/java/org/vaadin/tatu/vaadincreate/eventbus/EventBusImpl.java at master · TatuLund/vaadin-create23 · GitHub

Thanks for all the replies. i might consider implementing an own EvenBus like suggested by @yummy-rhino . i just need an additional option for an async event post method. maybe i can make it work with the new Virtual Thread feature.

@yummy-rhino i also have seen there is a ComponentUtil for Flow. But its only made for communitcating between vaadin components. did the vaadin team consider to provide an EventBus which works also between spring service component and vaadin components? Basically something like in the code example you posted, but with a bit more features (async support, annotation support instead making instanceof checks for the event object).

Virtual Threads will not change anything. It’s just another (more efficient) way to run threads