Why is DI so great? Learn about the basics concepts of Dependency Injection and how to efficiently utilise it with Vaadin 8. This talk is from Vaadin DevDay series and features some cool ideas how developers can be the most out of Vaadin and Spring Framework
1. VA A D I N W I T H S P R I N G
THINK WITH BEANS!
@peter_lehto
2. Session’s content
• Dependency Injection (DI) Briefly
• Setting up UI, ViewDisplay and Views as Beans
• Navigation, ViewAccessControl
• Securing with Spring Security
• EventBus and other DI Extensions
• Tips and Tricks for Springifying your Vaadin app
3. Session’s content
• Dependency Injection (DI) Briefly
• Setting up UI, ViewDisplay and Views as Beans
• Navigation, ViewAccessControl
• Securing with Spring Security
• EventBus and other DI Extensions
• Tips and Tricks for Springifying your Vaadin app
4. W h a t D e p e n d e n c y I n j e c t i o n ?
7. Dependency Injection (DI) is a runtime mechanism
where dependency between the client object and the
dependent object does not occur directly.
8. Dependency Injection (DI) is a runtime mechanism
where dependency between the client object and the
dependent object does not occur directly.
9. Dependency Injection (DI) is a runtime mechanism
where dependency between the client object and the
dependent object does not occur directly.
With DI the client object does not necessarily manage
the lifecycle of the dependent object.
10. Dependency Injection (DI) is a runtime mechanism
where dependency between the client object and the
dependent object does not occur directly.
With DI the client object does not necessarily
manage the lifecycle of the dependent object.
11. Dependency Injection (DI) is a runtime mechanism
where dependency between the client object and the
dependent object does not occur directly.
With DI the client object does not necessarily
manage the lifecycle of the dependent object.
Instead with DI a special DI container takes care of the
object lifecycle management
12. Dependency Injection (DI) is a runtime mechanism
where dependency between the client object and the
dependent object does not occur directly.
With DI the client object does not necessarily
manage the lifecycle of the dependent object.
Instead with DI a special DI container takes care of
the object lifecycle management
13. Dependency Injection (DI) is a runtime mechanism
where dependency between the client object and the
dependent object does not occur directly.
With DI the client object does not necessarily
manage the lifecycle of the dependent object.
Instead with DI a special DI container takes care of
the object lifecycle management where clients
reference managed and possibly shared objects.
14. Dependency Injection (DI) is a runtime mechanism
where dependency between the client object and the
dependent object does not occur directly.
With DI the client object does not necessarily
manage the lifecycle of the dependent object.
Instead with DI a special DI container takes care of
the object lifecycle management where clients
reference managed and possibly shared objects.
16. T L ; D R
public interface MainMenu { … }
public class DefaultMainMenu implements MainMenu { … }
17. T L ; D R
public interface MainMenu { … }
public class DefaultMainMenu implements MainMenu { … }
public class ResponsiveMainMenu implements MainMenu { … }
18. T L ; D R
public interface MainMenu { … }
public class DefaultMainMenu implements MainMenu { … }
public class ResponsiveMainMenu implements MainMenu { … }
@Autowired
private MainMenu mainMenu;
26. W i t h @ A u t o w i r e d a n d
MANAGED BEANS
27. Session’s content
• Dependency Injection (DI) Briefly
• Setting up UI, ViewDisplay and Views a Beans
• Navigation, ViewAccessControl
• Securing with Spring Security
• EventBus and other DI Extensions
• Tips and Tricks for Springifying your Vaadin app
29. path attribute for
URL binding
UI AS BEAN
@SpringUI(path = "app")
public class DevDayTestUI extends UI {
@SpringUI
public class DevDayTestUI extends UI {
35. Implement View and
annotate with
@SpringView
VIEW AS BEAN
@SpringView(name = "customers")
public class CustomerView extends VerticalLayout
implements View {
36. Wrapper for View
Component in UI
VIEWDISPLAY
@SpringViewDisplay
public class DevDayViewDisplay
extends VerticalSplitPanel
implements ViewDisplay {
37. S p r i n g B o o t
AUTO CONFIGURATION
S e t s e v e r y t h i n g u p
38. H o w a r e t h e b e a n
i n s t a n c e s m a n a g e d ?
42. @ S e s s i o n S c o p e
@ U I S c o p e
WITH SCOPES
43. public interface MainMenu { … }
@Autowired
private MainMenu mainMenu;
@SpringComponent
@UIScope
public class DefaultMainMenu implements MainMenu { … }
@ U I S c o p e
44. @ S e s s i o n S c o p e
@ U I S c o p e
@ V i e w S c o p e
WITH SCOPES
48. Session’s content
• Dependency Injection (DI) Briefly
• Setting up UI, ViewDisplay and Views a Beans
• Navigation, ViewAccessControl
• Securing with Spring Security
• EventBus and other DI Extensions
• Tips and Tricks for Springifying your Vaadin app
49. S p r i n g V i e w P r o v i d e r
SPRING NAVIGATOR
54. Session’s content
• Dependency Injection (DI) Briefly
• Setting up UI, ViewDisplay and Views a Beans
• Navigation, ViewAccessControl
• Securing with Spring Security
• EventBus and other DI Extensions
• Tips and Tricks for Springifying your Vaadin app
55. E n a b l i n g S p r i n g S e c u r i t y
w i t h S p r i n g B o o t
@EnableVaadinManagedSecurity
56. Va a d i n M a n a g e d S e c u r i t y
• Vaadin will manage Spring’s SecurityContext
• Disable auto configuration for SpringSecurity
• Vaadin app is the only web app secured
• Signing in and out takes place through Vaadin UI
• @PreAuthorize and @Secured
57. E n a b l i n g S p r i n g S e c u r i t y
w i t h S p r i n g B o o t
@EnableVaadinSharedSecurity
58. Va a d i n S h a r e d S e c u r i t y
• Vaadin behaves as regular web app secured by Spring
• Signing in and out may take place outside Vaadin
• Manual Spring Security configuration needed
• Web Socket based @Push not available due to HTTP Filters
• @PreAuthorize and @Secured
59. Session’s content
• Dependency Injection (DI) Briefly
• Setting up UI, ViewDisplay and Views a Beans
• Navigation, ViewAccessControl
• Securing with Spring Security
• EventBus and other DI Extensions
• Tips and Tricks for Springifying your Vaadin app
60. E v e n t B u s
@SpringComponent
@ViewScope
public class DataEditor<DTO> {
}
61. E v e n t B u s
@SpringComponent
@ViewScope
public class DataEditor<DTO> {
@Autowired
private EventBus.ViewEventBus eventBus;
…
}
62. E v e n t B u s
@SpringComponent
@ViewScope
public class DataEditor<DTO> {
@Autowired
private EventBus.ViewEventBus eventBus;
protected void onSaveClicked() {
eventBus.publish(this, new EditorSaveEvent());
}
…
}
66. Session’s content
• Dependency Injection (DI) Briefly
• Setting up UI, ViewDisplay and Views a Beans
• Navigation, ViewAccessControl
• Securing with Spring Security
• EventBus and other DI Extensions
• Tips and Tricks for Springifying your Vaadin app
67. S e t t i n g u p m e n u a u t o m a t i c a l l y
@MenuDefinition(icon=, name=, order=)
@SpringView(name=“customers”)
public class CustomerViewBean implements View… {
…
}
68. S e t t i n g u p m e n u a u t o m a t i c a l l y
private void findAndPopulateMenuItems() {
List<String> beanNames = Arrays.asList(context.
getBeanNamesForAnnotation(MenuDefinition.class));
}
69. S e t t i n g u p m e n u a u t o m a t i c a l l y
private void findAndPopulateMenuItems() {
List<String> beanNames = Arrays.asList(context.
getBeanNamesForAnnotation(MenuDefinition.class));
Map<String, MenuDefinition> definitionsToNames = beanNames.stream().
collect(Collectors.toMap(Function.identity(),
beanName -> context.findAnnotationOnBean(beanName, MenuDefinition.class)));
Map<String, SpringView> viewsToNames = beanNames.stream().
collect(Collectors.toMap(Function.identity(),
beanName -> context.findAnnotationOnBean(beanName, SpringView.class)));
}
70. S e t t i n g u p m e n u a u t o m a t i c a l l y
private void findAndPopulateMenuItems() {
List<String> beanNames = Arrays.asList(context.
getBeanNamesForAnnotation(MenuDefinition.class));
Map<String, MenuDefinition> definitionsToNames = beanNames.stream().
collect(Collectors.toMap(Function.identity(),
beanName -> context.findAnnotationOnBean(beanName, MenuDefinition.class)));
Map<String, SpringView> viewsToNames = beanNames.stream().
collect(Collectors.toMap(Function.identity(),
beanName -> context.findAnnotationOnBean(beanName, SpringView.class)));
beanNames.forEach(beanName -> {
MenuDefinition menuDefinition = definitionsToNames.get(beanName);
SpringView viewDefinition = viewsToNames.get(beanName);
addMenuItem(menuDefinition.name(), menuDefinition.icon(),
viewDefinition.name());
});
72. Va a d i n I 1 8 N S u p p o r t
@EnableI18N
@Bean
I18N i18n() {
return new I18N(context);
}
73. Va a d i n I 1 8 N S u p p o r t
@EnableI18N
@Bean
I18N i18n() {
return new I18N(context);
}
@Bean
CompositeMessageSource messageSource() {
return new CompositeMessageSource(context);
}
74. Va a d i n I 1 8 N S u p p o r t
@Bean
MessageProvider provideTranslations() {
return new ResourceBundleMessageProvider
(“com.foo.path.to.bundle”, "UTF-8");
}
75. P r o g r a m m a t i c B e a n L o o k u p
@Component
public class GenericBeanResolver { … }
76. Lessons learned
• DI is a powerful mechanism to decouple code
• Following DI almost certainly guarantees that best practices
are followed
• Vaadin supports DI with Spring and CDI, both through their
own integration addons
• Lot of Spring functionality is based on Beans
• Structuring Vaadin app with Bean approach can provide
great flexibility and robustness
77. T H A N K Y O U !
PLEASE RATE THE TALK
@
FLIP CHART BY THE DOOR!
@peter_lehto