Spring UI Scope
Spring UI Scope
The add-on has defined custom Spring scope: UI.
Please analyze sample application 'Simple Bank' to see how scope UI is used to create Spring powered Vaadin application in Model-View-Presenter architecture
Keep the following rules:
- Model (pojo) usually is singleton Spring bean
- Presenter (pojo) is UI-scope proxy Spring bean
- View (Vaadin component) is UI-scope Spring bean
Restrictions are cause by circular dependency between View and Presenter. Spring allows that only if one party is a proxy. If View is a proxy, Vaadin framework fails. Possible reason is that the framework use protected or package methods, which are not handled by proxy; only public methods are handled. Therefore, View must be UI-scope normal class and Presenter must be UI-scope proxy bean.
Sample code
<dependency> <groupId>com.cybercom</groupId> <artifactId>spring-ui-scope</artifactId> <version>0.0.2</version> </dependency>
@Configuration public class Conf { @Bean static UIScope uiScope() { return new UIScope(); } }
/** * Never define View bean as Spring Proxy. * That means circular dependency between 2 views is not possible with scope UI */ @Component @Scope(value = "ui") public class AccountView extends HorizontalLayout { private Table accountTable; private Table operationTable; private BeanItemContainer<Account> accounts = new BeanItemContainer<Account>(Account.class); private BeanItemContainer<Operation> operations = new BeanItemContainer<Operation>(Operation.class); @Autowired private AccountPresenter presenter; /** * @see TopView#construct() */ @PostConstruct private void construct() { accountTable = new Table("Accounts - click entry for details", accounts); accountTable.setImmediate(true); accountTable.setSelectable(true); addComponent(accountTable); accountTable.addValueChangeListener(new Property.ValueChangeListener() { @Override public void valueChange(ValueChangeEvent event) { presenter.accountClicked((Account)accountTable.getValue()); } }); operationTable = new Table("Operations", operations); addComponent(operationTable); } public void attach() { /* * There is a problem where view initialization; * 1. Presenter has logic to initialize View * 2. But Presenter cannot be called in @PostConstruct (circular reference) * * I decided to defer initialization to method attach() */ presenter.initAccounts(); super.attach(); } public BeanItemContainer<Account> getAccounts() { return accounts; } public BeanItemContainer<Operation> getOperations() { return operations; } }
/** * There is a circular reference between View and Presenter. It is typical * for MVP, but Spring guys don't like it. Only singleton beans may have circular reference. * Then, one side of relation must be proxy. View cannot be proxy because Vaadin is really confused. * Simply, Presenter must be the proxy. * */ @Component @Scope(value="ui", proxyMode=ScopedProxyMode.TARGET_CLASS) public class AccountPresenter { @Autowired private AccountView view; @Autowired private AccountModel model; public void initAccounts() { List<Account> accounts = model.getAccounts(); view.getAccounts().addAll(accounts); } public void accountClicked(Account account) { if (account == null) { view.getOperations().removeAllItems(); return; } List<Operation> operations = model.getOperations(account); view.getOperations().removeAllItems(); view.getOperations().addAll(operations); } }
Links
Compatibility
Was this helpful? Need more help?
Leave a comment or a question below. You can also join
the chat on Discord or
ask questions on StackOverflow.
Version
Just removed SNAPSHOT from uploaded files
- Released
- 2013-10-14
- Maturity
- EXPERIMENTAL
- License
- Apache License 2.0
Compatibility
- Framework
- Vaadin 7.1+
- Browser
- Browser Independent
Spring UI Scope - Vaadin Add-on Directory
Spring UI ScopeSource Code
Spring UI Scope version 0.0.1
null
Spring UI Scope version 0.0.2
Just removed SNAPSHOT from uploaded files