Vaadin Service Interfaces as CDI Beans
Some Vaadin service interfaces can be implemented as CDI beans. If you do this, the service interface becomes a managed bean with CDI features. In which case, there is no need to register the implementation in Vaadin.
The Vaadin CDI add-on references the following interfaces:
-
I18NProvider
-
InstantiatorFactory
-
SystemMessagesProvider
-
ErrorHandler
-
Executor
To ensure the beans are recognized, they should be qualified by the @VaadinServiceEnabled
annotation. This is required because it marks a bean which is used as an I18NProvider
by the service. If there are any other I18NProvider
beans, the one that’s also used by the service is used.
An example of this is using the @VaadinServiceEnabled
annotation to qualify TestSystemMessagesProvider
.
Source code
Java
@VaadinServiceEnabled
@VaadinServiceScoped
public class TestSystemMessagesProvider
implements SystemMessagesProvider {
@Override
public SystemMessages getSystemMessages(
SystemMessagesInfo systemMessagesInfo) {
CustomizedSystemMessages messages =
new CustomizedSystemMessages();
messages.setInternalErrorMessage(
"Sorry, something went wrong :(");
return messages;
}
}
@Route
public class SampleView extends Div {
@VaadinServiceEnabled
@Inject
private TestSystemMessagesProvider messageProvider;
}
The purpose of @VaadinServiceScoped
is to define a context of the lifespan of the Vaadin service. It isn’t necessary for this kind of bean, but it’s recommended because other Vaadin contexts can be problematic.
For example, there’s no guarantee that an active Vaadin session or UI context exists when the add-on looks for any of these beans. It’s safe, though, to use standard CDI @Dependent
and @ApplicationScoped
contexts.
Configure Custom Vaadin Executor
When a Vaadin application starts in a CDI environment, the CdiVaadinServletService
overrides the createDefaultExecutor()
method to use CDI capabilities for selecting an appropriate Executor
for executing Vaadin’s internal tasks. The selection process follows this order:
-
Look for a custom
Executor
bean qualified with the@VaadinServiceEnabled
annotation -
If no custom executor is found, try to use the container’s
ManagedExecutorService
(available in Jakarta EE environments) -
If neither is available, fall back to Vaadin’s default executor implementation
To avoid ambiguity, the CDI extension enforces these rules:
-
There can be at most one
Executor
bean annotated with@VaadinServiceEnabled
-
If multiple
Executor
beans with@VaadinServiceEnabled
annotation are found, the application deployment will fail with an appropriate error message
You can provide your own task executor to customize how Vaadin executes server-side operations. This can be useful for implementing custom threading models, using specific thread pools, or integrating with other execution frameworks.
To provide a custom executor, define a CDI bean that implements the Executor
interface and annotate it with @VaadinServiceEnabled
:
Source code
Java
@ApplicationScoped
public class ExecutorConfiguration {
@Produces
@Singleton
@VaadinServiceEnabled
public Executor vaadinTaskExecutor() {
ThreadPoolExecutor customExecutor = new ThreadPoolExecutor(
16, // Core pool size
32, // Maximum pool size
120, // Keep-alive time
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(),
r -> {
Thread thread = new Thread(r, "CustomVaadinExecutor-" + r.hashCode());
thread.setDaemon(true);
return thread;
});
customExecutor.allowCoreThreadTimeOut(true);
return customExecutor;
}
}
A55D3416-D5B7-40B9-8C4A-1454E97C92F1