Using CDI Beans in Instantiated Components

When using Vaadin CDI, most objects instantiated by framework become managed beans. The framework uses the CDI BeanManager to get references to beans. This means they are fully-fledged CDI contextual instances.

The add-on looks up the CDI bean by type (component class) and @Any.

If the type is not found as a CDI bean - for example, because it is ambiguous or does not have a no-arg public constructor - instantiation falls back to the default Vaadin behavior, and the component is instantiated as a POJO. Dependency injection is performed after instantiation and injects still work, but other CDI features do not. The reason is that the instantiated component is not a contextual instance.

Note
Methods annotated with @PreDestroy in Dependent beans instantiated by the framework are not run.

Using Router Components

All route targets, router layouts, and exception targets become managed beans when the add-on is used. The components look and behave the same as without the add-on, but CDI features are available.

Example: Using the @Inject annotation on a basic route target.

Java

  1. @Route
  2. public class MainView extends VerticalLayout {
  3. @Inject
  4. public MainView(Greeter greeter) {
  5. add(new Span(greeter.sayHello()));
  6. }
  7. }
Note
Vaadin scans for router components on startup and is unaware of CDI beans. Using producers or the @Typed annotation causes issues with this kind of bean.

Using Components Injected into Polymer Templates

Components injected into Polymer template classes using the @id annotation become managed beans when the add-on is used.

Example: Using the @Id annotation to inject the DependentLabel component into TestTemplate class.

Java

  1. public class TestTemplate
  2. extends PolymerTemplate<TemplateModel> {
  3. @Id
  4. private DependentLabel label;
  5. }

Example: DependentLabel class.

Java

  1. @Dependent
  2. @Tag("dependent-label")
  3. public class DependentLabel extends Label {
  4. @Inject
  5. private Greeter greeter;
  6. @PostConstruct
  7. private void init() {
  8. setText(greeter.sayHello());
  9. }
  10. }

Example: TestTemplate.html Polymer template.

js

  1. import {PolymerElement,html} from
  2. '@polymer/polymer/polymer-element.js';
  3. class TestTemplate extends Polymer.Element {
  4. static get template() {
  5. return html`
  6. <div>
  7. <dependent-label id="label"/>
  8. </div>`;
  9. }
  10. static get is() { return 'test-template' }
  11. }
  12. customElements.define(TestTemplate.is, TestTemplate);
Important
The managed bean injected into the template should not exist before the template is instantiated. If it does exist at this time, it may not bind to its element, and this may result in an incorrect component tree.

Using a Custom UI

It is not necessary to define a custom UI subclass for your application, but it is possible to define one using the corresponding servlet parameter, if needed.

The custom UI subclass is instantiated by Vaadin as a POJO (not as a managed bean), but it is still possible to achieve dependency injection. Use BeanManager in your overridden UI.init method, for example BeanProvider.injectFields(this) (in Deltaspike).