javaspringvaadinvaadin7

Vaadin Component as Spring bean


Question:

When Vaadin component could be a bean in spring container (@SpringComponent annotation)?

Question clarification:

I ask this question because I know that Vaadin View could be spring bean after using @SpringView. But if I annotate Button component with @SpringComponent it will be created only once. Can it make any problem?

Example:

I have a lot of JpaRepository bean:

public interface CustomerRepository extends JpaRepository<Customer, Long> 
// ...

public interface UserRepository extends JpaRepository<User, Long> {
// ...

And I want use them in different places - for example in a Tab component (in Vaadin TabSheet). So I have an idea - the tabContent can be also spring component:

@SpringView(name = "viewName")
public class SomeView extends VerticalLayout implements View {

    @Autowired
    private SomeTabContent tabContent;
    //...
    public void init() { // call every view enter()
        removeAllComponents();
        // Initialize whole view.
        tabSheet.addTab(tabContent, /* ... */);
        // ...
    }

And then I can inject all needed beans:

@SpringComponent
public class SomeTabContent extends VerticalLayout {
    @Autowired
    private CustomerRepository customerRepository;

    @Autowired
    private UserRepository UserRepository;
}

Is it correct architecture?

Note: I know that Vaadin has CDI and Data Binding features, but I don't want use them. I also know that I could manually create Spring application context in any place - but I think this is not proper way.


Solution

  • After increasing my knowledge I have some hypothesis.

    Can we use Vaadin component as Spring bean? Why not. I tried this and it works. But...

    But it cause also multiple listeners invocation - as I have class-instated Button object.

    Spring creates the instance of the component by itself and put it somewhere. So I can't do anything in component constructor. Moreover such component should be cleaned and initialized before any use. Does it sound weird? I think yes. And it might cause a lot of problems - especially in multithread environment.

    So I don't recommend making a Bean of any Vaadin components (for example Tab, Buttons...). Because they need to change their state depending on place of use.

    But how to make available all Spring beans in object which is not maintained by Spring container? This isn't new question and there are at least two solutions:

    1. Annotate such class with @Configurable and enable any weaving (compile or run time). This is explained for example here or here.

    2. Directly use of AutowireCapableBeanFactory and autowiredBeanProperty() method. A little explanation can be find here and also on SO.