Vaadin 8 with Spring Framework

Post on 11-Apr-2017

221 views 0 download

Transcript of Vaadin 8 with Spring Framework

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