105
@peter_lehto DI YOUR UI

Vaadin DevDay 2017 - DI your UI

Embed Size (px)

Citation preview

Page 1: Vaadin DevDay 2017 - DI your UI

5

S T O R Y A N D P H I L O S O P H Y

Software is eating the world and what most of us see of it is the user interface. The user

interface has become the key component of how the users experience the business

behind it. Competition is lost or won due to user experience. Simplicity is king and the

users get frustrated by anything ugly, slow or not working on the device they happen to

use at the time. We at Vaadin fight for simplicity and invite everyone to join this fight.

Together we want to build a user interface that puts a smile on the user’s face.

Vaadin is the technology that empowers developers to build the best web-apps for

business purposes. Our priority over everything else is developer productivity because

we believe that by simplifying the developer experience and saving the developer’s

time, they are best able to focus on building great user interfaces.

Our brand is what we want everyone to think about us. When everyone - both us and

the people around us - have a consistent understanding of what Vaadin is and what we

stand for, it enables that image to spread and amplify. This book defines what we want

that image to be. It defines what the Vaadin brand is.

I hope that You are as excited and proud of living and breathing the Vaadin brand as

I am. You are the one who is shaping what everyone thinks about Vaadin - using this

brand as a tool and a guideline every day.

Let’s fight for simplicity for both the users and the developers!

Joonas Lehtinen

Founder & CEO

Vaadin

I N T R O D U C T I O N

@peter_lehto

D I Y O U R U I

Page 2: Vaadin DevDay 2017 - DI your UI

Session’s content

Page 3: Vaadin DevDay 2017 - DI your UI

Session’s content

• What Dependency Injection, Why and How?

Page 4: Vaadin DevDay 2017 - DI your UI

Session’s content

• What Dependency Injection, Why and How?

• Vaadin UI, View and components as Beans

Page 5: Vaadin DevDay 2017 - DI your UI

Session’s content

• What Dependency Injection, Why and How?

• Vaadin UI, View and components as Beans

• Instances and Scopes

Page 6: Vaadin DevDay 2017 - DI your UI

Session’s content

• What Dependency Injection, Why and How?

• Vaadin UI, View and components as Beans

• Instances and Scopes

• EventBus and other DI Extensions

Page 7: Vaadin DevDay 2017 - DI your UI

Session’s content

• What Dependency Injection, Why and How?

• Vaadin UI, View and components as Beans

• Instances and Scopes

• EventBus and other DI Extensions

• Tips and Tricks for Springifying your Vaadin app

Page 8: Vaadin DevDay 2017 - DI your UI

Session’s content

• What Dependency Injection, Why and How?

• Vaadin UI, View and components as Beans

• Instances and Scopes

• EventBus and other DI Extensions

• Tips and Tricks for Springifying your Vaadin app

Page 9: Vaadin DevDay 2017 - DI your UI

W h a t D e p e n d e n c y I n j e c t i o n ?

Page 10: Vaadin DevDay 2017 - DI your UI

WHAT DI? private Grid<Customer> grid;

Page 11: Vaadin DevDay 2017 - DI your UI

INSTEAD OFNEW private Grid<Customer> grid;

protected void init(VaadinRequest request) { grid = new Grid<>(); grid.setSizeFull();

Page 12: Vaadin DevDay 2017 - DI your UI

SAY@AUTOWIRED

@Autowiredprivate Grid<Customer> grid;

protected void init(VaadinRequest request) { grid.setSizeFull();

Page 13: Vaadin DevDay 2017 - DI your UI

@Beanpublic Grid<Customer> configureBeanGrid() {BEAN

CONFIG

Page 14: Vaadin DevDay 2017 - DI your UI

@Beanpublic Grid<Customer> configureBeanGrid() {Grid<Customer> grid = new Grid<>();

BEANCONFIG

Page 15: Vaadin DevDay 2017 - DI your UI

@Beanpublic Grid<Customer> configureBeanGrid() {Grid<Customer> grid = new Grid<>();grid.addColumn(Customer::getFirstName).setCaption("First name");grid.addColumn(Customer::getLastName).setCaption("Last name");

BEANCONFIG

Page 16: Vaadin DevDay 2017 - DI your UI

@Beanpublic Grid<Customer> configureBeanGrid() {Grid<Customer> grid = new Grid<>();grid.addColumn(Customer::getFirstName).setCaption("First name");grid.addColumn(Customer::getLastName).setCaption("Last name");

return grid;}

BEANCONFIG

Page 17: Vaadin DevDay 2017 - DI your UI

Dependency Injection (DI) is a runtime mechanism

Page 18: Vaadin DevDay 2017 - DI your UI

Dependency Injection (DI) is a runtime mechanism where dependency between the client object and the dependent object does not occur directly.

Page 19: Vaadin DevDay 2017 - DI your UI

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.

Page 20: Vaadin DevDay 2017 - DI your UI

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

Page 21: Vaadin DevDay 2017 - DI your UI

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.

Page 22: Vaadin DevDay 2017 - DI your UI

W h y ?

Page 23: Vaadin DevDay 2017 - DI your UI
Page 24: Vaadin DevDay 2017 - DI your UI

• High Abstraction

Page 25: Vaadin DevDay 2017 - DI your UI

• High Abstraction• Loose coupling

Page 26: Vaadin DevDay 2017 - DI your UI

• High Abstraction• Loose coupling• Dependency inversion

Page 27: Vaadin DevDay 2017 - DI your UI

• High Abstraction• Loose coupling• Dependency inversion• Highly cohesive modules

Page 28: Vaadin DevDay 2017 - DI your UI

• High Abstraction• Loose coupling• Dependency inversion• Highly cohesive modules• Deployment time config

Page 29: Vaadin DevDay 2017 - DI your UI

H o w ?

Page 30: Vaadin DevDay 2017 - DI your UI
Page 31: Vaadin DevDay 2017 - DI your UI

HIGHABSTRACTION

interface GadgetConfiguration

Page 32: Vaadin DevDay 2017 - DI your UI

HIGHABSTRACTION

interface GadgetConfiguration

interface Gadget<C extends GadgetConfiguration>

Page 33: Vaadin DevDay 2017 - DI your UI

HIGHABSTRACTION

interface GadgetConfiguration

interface Gadget<C extends GadgetConfiguration>

interface ConfigurationDialog<C extends GadgetConfiguration>

Page 34: Vaadin DevDay 2017 - DI your UI

HIGHABSTRACTION

class NotesConfiguration implements GadgetConfiguration {}

Page 35: Vaadin DevDay 2017 - DI your UI

HIGHABSTRACTION

class NotesConfiguration implements GadgetConfiguration {}

class NotesGadget implements Gadget<NotesConfiguration> {}

Page 36: Vaadin DevDay 2017 - DI your UI

HIGHABSTRACTION

class NotesConfiguration implements GadgetConfiguration {}

class NotesGadget implements Gadget<NotesConfiguration> {}

class NotesConfigurationDialog implements ConfigurationDialog<NotesConfiguration> {}

Page 37: Vaadin DevDay 2017 - DI your UI

HIGHABSTRACTION

class NotesConfiguration implements GadgetConfiguration {}

@Componentclass NotesGadget implements Gadget<NotesConfiguration> {}

@Componentclass NotesConfigurationDialog implements ConfigurationDialog<NotesConfiguration> {}

Page 38: Vaadin DevDay 2017 - DI your UI

APPLICATIONCONTEXT

String[] getBeanNamesForType(Class<?> type);

String[] getBeanNamesForType(ResolvableType type);

Map<String, T> getBeansOfType(Class<T> type);

Map<String, Object> getBeansWithAnnotation(Class<?> annot);

Object getBean(String);

T getBean(String, Class<T> type);

Page 39: Vaadin DevDay 2017 - DI your UI

LOOSECOUPLING interface MainMenu { }

• Define abstraction

Page 40: Vaadin DevDay 2017 - DI your UI

LOOSECOUPLING interface MainMenu { }

@Componentclass DefaultMainMenu implements MainMenu {}• Define abstraction

• Define Implementations

Page 41: Vaadin DevDay 2017 - DI your UI

LOOSECOUPLING interface MainMenu { }

@Componentclass DefaultMainMenu implements MainMenu {}

@Componentclass ResponsiveMainMenu implements MainMenu {}

• Define abstraction

• Define Implementations

Page 42: Vaadin DevDay 2017 - DI your UI

DEPENDENCYINVERSION

@Autowiredprivate MainMenu mainMenu;

• Define abstraction

• Define Implementations

• Depend on Abstraction,not concrete type -> Depency Inversion

Page 43: Vaadin DevDay 2017 - DI your UI

@Componentpublic class DefaultMainMenu implements MainMenu { … }

D e f i n i n g a B e a n

Page 44: Vaadin DevDay 2017 - DI your UI

@Component@UIScopepublic class DefaultMainMenu implements MainMenu { … }

D e f i n i n g a B e a n

Page 45: Vaadin DevDay 2017 - DI your UI

@Configurationpublic class ComponentConfiguration {

@Bean @Primary @UIScope public MainMenu provideDefaultMenu { return new DefaultMainMenu(); }

… w i t h @ C o n f i g u r a t i o n

Page 46: Vaadin DevDay 2017 - DI your UI

@Bean @Responsive

@UIScope public MainMenu provideResponsiveMenu {

return new ResponsiveMainMenu(); }}

Page 47: Vaadin DevDay 2017 - DI your UI

Session’s content

• What Dependency Injection, Why and How?

• Vaadin UI, View and components as Beans

• Instances and Scopes

• EventBus and other DI Extensions

• Tips and Tricks for Springifying your Vaadin app

Page 48: Vaadin DevDay 2017 - DI your UI

Automatic discoveryand lookup

UI AS BEAN@SpringUIpublic class VaadinUI extends UI {

Page 49: Vaadin DevDay 2017 - DI your UI

path attribute forURL binding

UI AS BEAN

@SpringUI(path = "app")public class VaadinUI extends UI {

@SpringUIpublic class VaadinUI extends UI {

Page 50: Vaadin DevDay 2017 - DI your UI

localhost:8080/context

UI AS BEAN

localhost:8080/context/app @SpringUI(path = "app")public class VaadinUI extends UI {

@SpringUIpublic class VaadinUI extends UI {

Page 51: Vaadin DevDay 2017 - DI your UI

HorizontalLayoutContentAreaMenu

View1

View2

View3

Page 52: Vaadin DevDay 2017 - DI your UI

HorizontalLayoutView1Menu

View1

View2

View3

Page 53: Vaadin DevDay 2017 - DI your UI

HorizontalLayoutView2Menu

View1

View2

View3

Page 54: Vaadin DevDay 2017 - DI your UI

HorizontalLayoutView3Menu

View1

View2

View3

Page 55: Vaadin DevDay 2017 - DI your UI

Implement View andannotate with @SpringView

VIEW AS BEAN@SpringView(name = "customers")public class CustomerView extends VerticalLayout implements View {

Page 56: Vaadin DevDay 2017 - DI your UI

Wrapper for ViewComponent in UI

VIEWDISPLAY@SpringViewDisplaypublic class DevDayViewDisplay extends VerticalSplitPanel implements ViewDisplay {

Page 57: Vaadin DevDay 2017 - DI your UI

S p r i n g V i e w P r o v i d e r

SPRING NAVIGATOR

Page 58: Vaadin DevDay 2017 - DI your UI

@Autowiredprivate Navigator navigator;

navigator.navigateTo(“customers”);

N a v i g a t o r

Page 59: Vaadin DevDay 2017 - DI your UI

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

Page 60: Vaadin DevDay 2017 - DI your UI

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

Page 61: Vaadin DevDay 2017 - DI your UI

COMPONENTSAS

BEANS

@Autowiredprivate Grid<Customer> grid;

Page 62: Vaadin DevDay 2017 - DI your UI

DEMO

Page 63: Vaadin DevDay 2017 - DI your UI

Session’s content

• What Dependency Injection, Why and How?

• Vaadin UI, View and components as Beans

• Instances and Scopes

• EventBus and other DI Extensions

• Tips and Tricks for Springifying your Vaadin app

Page 64: Vaadin DevDay 2017 - DI your UI

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 ?

Page 65: Vaadin DevDay 2017 - DI your UI

WITH SCOPES

Page 66: Vaadin DevDay 2017 - DI your UI

@ S e s s i o n S c o p e

WITH SCOPES

Page 67: Vaadin DevDay 2017 - DI your UI

@Autowiredprivate User currentUser;

@ S e s s i o n S c o p e

Page 68: Vaadin DevDay 2017 - DI your UI

@ S e s s i o n S c o p e@ Va a d i n S e s s i o n S c o p e

WITH SCOPES

Page 69: Vaadin DevDay 2017 - DI your UI

@ S e s s i o n S c o p e@ Va a d i n S e s s i o n S c o p e

@ U I S c o p e

WITH SCOPES

Page 70: Vaadin DevDay 2017 - DI your UI

public interface MainMenu { … }

@Autowiredprivate MainMenu mainMenu;

@Component@UIScopepublic class DefaultMainMenu implements MainMenu { … }

@ U I S c o p e

Page 71: Vaadin DevDay 2017 - DI your UI

@ S e s s i o n S c o p e@ Va a d i n 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

Page 72: Vaadin DevDay 2017 - DI your UI

@Component@ViewScopepublic class NotesGadget {

@Autowired private EventBus.ViewEventBus eventBus;

@ V i e w S c o p e

Page 73: Vaadin DevDay 2017 - DI your UI

@ S e s s i o n S c o p e@ Va a d i n 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

Page 74: Vaadin DevDay 2017 - DI your UI

public interface HttpRequestStopWatch { … }

@ R e q u e s t S c o p e

Page 75: Vaadin DevDay 2017 - DI your UI

@SessionScope

Page 76: Vaadin DevDay 2017 - DI your UI

@SessionScope@VaadinSessionScope

Page 77: Vaadin DevDay 2017 - DI your UI

@SessionScope@VaadinSessionScope

@UIScope

Page 78: Vaadin DevDay 2017 - DI your UI

@SessionScope@VaadinSessionScope

@UIScope @ViewScope

Page 79: Vaadin DevDay 2017 - DI your UI

@SessionScope

Page 80: Vaadin DevDay 2017 - DI your UI

@ApplicationScoped@SessionScope

@Vaadin SessionScope

@Vaadin SessionScope

@Vaadin SessionScope

Page 81: Vaadin DevDay 2017 - DI your UI

@SessionScope

@Vaadin SessionScope

@Vaadin SessionScope

@Vaadin SessionScope

@UI Scope

@UI Scope

@UI Scope

@UI Scope

@UI Scope

@UI Scope

Page 82: Vaadin DevDay 2017 - DI your UI

@ View

@ View

@ View

@ View

@ View

@ View

@ View

@ View

@ View

@ View

@ View

@ View

@UI Scope

@UI Scope

@UI Scope

@UI Scope

@UI Scope

@UI Scope

@SessionScope

@Vaadin SessionScope

@Vaadin SessionScope

@Vaadin SessionScope

Page 83: Vaadin DevDay 2017 - DI your UI

Session’s content

• What Dependency Injection, Why and How?

• Vaadin UI, View and components as Beans

• Instances and Scopes

• EventBus and other DI Extensions

• Tips and Tricks for Springifying your Vaadin app

Page 84: Vaadin DevDay 2017 - DI your UI

E v e n t B u s@Component@ViewScopepublic class DataEditor<DTO> {

}

Page 85: Vaadin DevDay 2017 - DI your UI

E v e n t B u s@Component@ViewScopepublic class DataEditor<DTO> {

@Autowiredprivate EventBus.ViewEventBus eventBus;

…}

Page 86: Vaadin DevDay 2017 - DI your UI

E v e n t B u s@Component@ViewScopepublic class DataEditor<DTO> {

@Autowiredprivate EventBus.ViewEventBus eventBus;

protected void onSaveClicked() {eventBus.publish(this, new EditorSaveEvent());

}…

}

Page 87: Vaadin DevDay 2017 - DI your UI

@Component@ViewScopepublic class DataTable<DTO> extends Grid<DTO> {

@Autowiredprivate EventBus.ViewEventBus eventBus;

}

Page 88: Vaadin DevDay 2017 - DI your UI

@Component@ViewScopepublic class DataTable<DTO> extends Grid<DTO> {

@Autowiredprivate EventBus.ViewEventBus eventBus;

@PostConstructprotected void initialize() {eventBus.subscribe(this);

}

}

Page 89: Vaadin DevDay 2017 - DI your UI

@Component@ViewScopepublic class DataTable<DTO> extends Grid<DTO> {

@Autowiredprivate EventBus.ViewEventBus eventBus;

@PostConstructprotected void initialize() {eventBus.subscribe(this);

}

@EventBusListenerMethodprotected void onSaveEvent(EditorSaveEvent e) {getDataProvider().refreshAll();

}}

Page 90: Vaadin DevDay 2017 - DI your UI

Va a d i n I 1 8 N S u p p o r t

@EnableI18N

Page 91: Vaadin DevDay 2017 - DI your UI

Va a d i n I 1 8 N S u p p o r t

@EnableI18N

@BeanI18N i18n() { return new I18N(context);}

Page 92: Vaadin DevDay 2017 - DI your UI

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);}

Page 93: Vaadin DevDay 2017 - DI your UI

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");}

Page 94: Vaadin DevDay 2017 - DI your UI

Session’s content

• What Dependency Injection, Why and How?

• Vaadin UI, View and components as Beans

• Instances and Scopes

• EventBus and other DI Extensions

• Tips and Tricks for Springifying your Vaadin app

Page 95: Vaadin DevDay 2017 - DI your UI

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… {

…}

Page 96: Vaadin DevDay 2017 - DI your UI

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));

}

Page 97: Vaadin DevDay 2017 - DI your UI

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)));

}

Page 98: Vaadin DevDay 2017 - DI your UI

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()); }); }

Page 99: Vaadin DevDay 2017 - DI your UI

Lessons learned

Page 100: Vaadin DevDay 2017 - DI your UI

Lessons learned• DI is a powerful mechanism to decouple code

Page 101: Vaadin DevDay 2017 - DI your UI

Lessons learned• DI is a powerful mechanism to decouple code

• Following DI almost certainly guarantees that best practices are followed

Page 102: Vaadin DevDay 2017 - DI your UI

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 add-ons

Page 103: Vaadin DevDay 2017 - DI your UI

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 add-ons

• Lot of Spring functionality is based on Beans

Page 104: Vaadin DevDay 2017 - DI your UI

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 add-ons

• Lot of Spring functionality is based on Beans

• Structuring Vaadin app with Bean approach can provide great flexibility and robustness

Page 105: Vaadin DevDay 2017 - DI your UI

@peter_lehto

T H A N K Y O U !