Upload
peter-lehto
View
221
Download
0
Embed Size (px)
Citation preview
VA A D I N W I T H S P R I N G
THINK WITH BEANS!
@peter_lehto
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
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
W h a t D e p e n d e n c y I n j e c t i o n ?
Dependency Injection (DI) is a runtime mechanism
Dependency Injection (DI) is a runtime mechanism
Dependency Injection (DI) is a runtime mechanism where dependency between the client object and the dependent object does not occur directly.
Dependency Injection (DI) is a runtime mechanism where dependency between the client object and the dependent object does not occur directly.
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.
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.
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
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
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.
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.
T L ; D R
public interface MainMenu { … }
T L ; D R
public interface MainMenu { … }
public class DefaultMainMenu implements MainMenu { … }
T L ; D R
public interface MainMenu { … }
public class DefaultMainMenu implements MainMenu { … }
public class ResponsiveMainMenu implements MainMenu { … }
T L ; D R
public interface MainMenu { … }
public class DefaultMainMenu implements MainMenu { … }
public class ResponsiveMainMenu implements MainMenu { … }
@Autowiredprivate MainMenu mainMenu;
W h y ?
• Loose coupling• Dependency inversion• High Abstraction • Highly cohesive modules• Deployment time config
H o w ?
@SpringComponentpublic class DefaultMainMenu implements MainMenu { … }
D e f i n e B e a n
@SpringComponent@UIScopepublic class DefaultMainMenu implements MainMenu { … }
D e f i n e B e a n
@Configurationpublic class ComponentConfiguration {
@Bean @Primary public MainMenu provideDefaultMenu { return new DefaultMainMenu(); }
D e f i n e B e a n
@Bean @Responsive public MainMenu provideResponsiveMenu { return new ResponsiveMainMenu(); }}
W i t h @ A u t o w i r e d a n d
MANAGED BEANS
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
Automatic discoveryand lookup
UI AS BEAN@SpringUIpublic class DevDayTestUI extends UI {
path attribute forURL binding
UI AS BEAN
@SpringUI(path = "app")public class DevDayTestUI extends UI {
@SpringUIpublic class DevDayTestUI extends UI {
localhost:8080/context
UI AS BEAN
localhost:8080/context/app @SpringUI(path = "app")public class DevDayTestUI extends UI {
@SpringUIpublic class DevDayTestUI extends UI {
HorizontalLayoutContentAreaMenu
View1
View2
View3
HorizontalLayoutView1Menu
View1
View2
View3
HorizontalLayoutView2Menu
View1
View2
View3
HorizontalLayoutView3Menu
View1
View2
View3
Implement View andannotate with @SpringView
VIEW AS BEAN@SpringView(name = "customers")public class CustomerView extends VerticalLayout implements View {
Wrapper for ViewComponent in UI
VIEWDISPLAY@SpringViewDisplaypublic class DevDayViewDisplay extends VerticalSplitPanel implements ViewDisplay {
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
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 ?
WITH SCOPES
@ S e s s i o n S c o p e
WITH SCOPES
@Autowiredprivate User currentUser;
@ S e s s i o n S c o p e
@ S e s s i o n S c o p e@ U I S c o p e
WITH SCOPES
public interface MainMenu { … }
@Autowiredprivate MainMenu mainMenu;
@SpringComponent@UIScopepublic class DefaultMainMenu implements MainMenu { … }
@ U I S c o p e
@ 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
@SpringComponent@ViewScopepublic class DataTable {
@Autowired private EventBus.ViewEventBus eventBus;
@ V i e w S c o p e
@ 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@ R e q u e s t S c o p e
WITH SCOPES
public interface HttpRequestStopWatch { … }
@ R e q u e s t S c o p e
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
S p r i n g V i e w P r o v i d e r
SPRING NAVIGATOR
@Autowiredprivate Navigator navigator;
navigator.navigateTo(“customers”);
N a v i g a t o r
V i e w b e a n d i s c o v e r y b y @ S p r i n g V i e w
SPRING NAVIGATOR
public interface ViewAccessControl;public interface ViewInstanceAccessControl;
C o n t r o l l i n g a c c e s s t o v i e w s
public interface ViewAccessControl;public interface ViewInstanceAccessControl;
C o n t r o l l i n g a c c e s s t o v i e w s
WITHOUT SPRING SECURITY
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
E n a b l i n g S p r i n g S e c u r i t yw i t h S p r i n g B o o t
@EnableVaadinManagedSecurity
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
E n a b l i n g S p r i n g S e c u r i t yw i t h S p r i n g B o o t
@EnableVaadinSharedSecurity
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
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
E v e n t B u s@SpringComponent@ViewScopepublic class DataEditor<DTO> {
}
E v e n t B u s@SpringComponent@ViewScopepublic class DataEditor<DTO> {
@Autowiredprivate EventBus.ViewEventBus eventBus;
…}
E v e n t B u s@SpringComponent@ViewScopepublic class DataEditor<DTO> {
@Autowiredprivate EventBus.ViewEventBus eventBus;
protected void onSaveClicked() {eventBus.publish(this, new EditorSaveEvent());
}…
}
@SpringComponent@ViewScopepublic class DataTable<DTO> extends Grid<DTO> {
@Autowiredprivate EventBus.ViewEventBus eventBus;
}
@SpringComponent@ViewScopepublic class DataTable<DTO> extends Grid<DTO> {
@Autowiredprivate EventBus.ViewEventBus eventBus;
@PostConstructprotected void initialize() {eventBus.subscribe(this);
}
}
@SpringComponent@ViewScopepublic class DataTable<DTO> extends Grid<DTO> {
@Autowiredprivate EventBus.ViewEventBus eventBus;
@PostConstructprotected void initialize() {eventBus.subscribe(this);
}
@EventBusListenerMethodprotected void onSaveEvent(EditorSaveEvent e) {getDataProvider().refreshAll();
}}
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
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… {
…}
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));
}
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)));
}
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()); }); }
Va a d i n I 1 8 N S u p p o r t
@EnableI18N
Va a d i n I 1 8 N S u p p o r t
@EnableI18N
@BeanI18N i18n() { return new I18N(context);}
Va a d i n I 1 8 N S u p p o r t
@EnableI18N
@BeanI18N i18n() { return new I18N(context);}
@BeanCompositeMessageSource messageSource() { return new CompositeMessageSource(context);}
Va a d i n I 1 8 N S u p p o r t
@BeanMessageProvider provideTranslations() { return new ResourceBundleMessageProvider (“com.foo.path.to.bundle”, "UTF-8");}
P r o g r a m m a t i c B e a n L o o k u p
@Componentpublic class GenericBeanResolver { … }
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
T H A N K Y O U !
PLEASE RATE THE TALK @
FLIP CHART BY THE DOOR!
@peter_lehto