Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 689
jsosnowski Avatar asked Aug 14 '15 08:08

jsosnowski


2 Answers

If you use just @Component (or @SpringComponent) the class will be instantiated once for the application so, yes, you will get issues with multiple sessions sharing the resulting objects when you don't want them to. So you add @UIScope as well. That will ensure you get one instance of this class per session. You can store session data in the class (much as if you used Spring's @Session, but that requires you to use Spring's Dispatcher).

In a @UIScope class you can use @Autowired and @PostConstruct etc. I use it for extends of Windows and Layout etc. You need com.vaadin:vaadin-spring:1.0.0 on your classpath. Further info on vaadin-spring

like image 134
RogerParkinson Avatar answered Sep 16 '22 11:09

RogerParkinson


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.

like image 44
jsosnowski Avatar answered Sep 18 '22 11:09

jsosnowski