vaadin devday 2017 - di your ui

Post on 22-Jan-2018

242 Views

Category:

Software

2 Downloads

Preview:

Click to see full reader

TRANSCRIPT

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

Session’s content

Session’s content

• What Dependency Injection, Why and How?

Session’s content

• What Dependency Injection, Why and How?

• Vaadin UI, View and components as Beans

Session’s content

• What Dependency Injection, Why and How?

• Vaadin UI, View and components as Beans

• Instances and Scopes

Session’s content

• What Dependency Injection, Why and How?

• Vaadin UI, View and components as Beans

• Instances and Scopes

• EventBus and other DI Extensions

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

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

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

WHAT DI? private Grid<Customer> grid;

INSTEAD OFNEW private Grid<Customer> grid;

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

SAY@AUTOWIRED

@Autowiredprivate Grid<Customer> grid;

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

@Beanpublic Grid<Customer> configureBeanGrid() {BEAN

CONFIG

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

BEANCONFIG

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

BEANCONFIG

@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

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.

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 where clients reference managed and possibly shared objects.

W h y ?

• High Abstraction

• High Abstraction• Loose coupling

• High Abstraction• Loose coupling• Dependency inversion

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

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

H o w ?

HIGHABSTRACTION

interface GadgetConfiguration

HIGHABSTRACTION

interface GadgetConfiguration

interface Gadget<C extends GadgetConfiguration>

HIGHABSTRACTION

interface GadgetConfiguration

interface Gadget<C extends GadgetConfiguration>

interface ConfigurationDialog<C extends GadgetConfiguration>

HIGHABSTRACTION

class NotesConfiguration implements GadgetConfiguration {}

HIGHABSTRACTION

class NotesConfiguration implements GadgetConfiguration {}

class NotesGadget implements Gadget<NotesConfiguration> {}

HIGHABSTRACTION

class NotesConfiguration implements GadgetConfiguration {}

class NotesGadget implements Gadget<NotesConfiguration> {}

class NotesConfigurationDialog implements ConfigurationDialog<NotesConfiguration> {}

HIGHABSTRACTION

class NotesConfiguration implements GadgetConfiguration {}

@Componentclass NotesGadget implements Gadget<NotesConfiguration> {}

@Componentclass NotesConfigurationDialog implements ConfigurationDialog<NotesConfiguration> {}

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

LOOSECOUPLING interface MainMenu { }

• Define abstraction

LOOSECOUPLING interface MainMenu { }

@Componentclass DefaultMainMenu implements MainMenu {}• Define abstraction

• Define Implementations

LOOSECOUPLING interface MainMenu { }

@Componentclass DefaultMainMenu implements MainMenu {}

@Componentclass ResponsiveMainMenu implements MainMenu {}

• Define abstraction

• Define Implementations

DEPENDENCYINVERSION

@Autowiredprivate MainMenu mainMenu;

• Define abstraction

• Define Implementations

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

@Componentpublic class DefaultMainMenu implements MainMenu { … }

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

@Component@UIScopepublic class DefaultMainMenu implements MainMenu { … }

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

@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

@Bean @Responsive

@UIScope public MainMenu provideResponsiveMenu {

return new ResponsiveMainMenu(); }}

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

Automatic discoveryand lookup

UI AS BEAN@SpringUIpublic class VaadinUI extends UI {

path attribute forURL binding

UI AS BEAN

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

@SpringUIpublic class VaadinUI extends UI {

localhost:8080/context

UI AS BEAN

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

@SpringUIpublic class VaadinUI 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 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

COMPONENTSAS

BEANS

@Autowiredprivate Grid<Customer> grid;

DEMO

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

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

WITH SCOPES

@ 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

public interface MainMenu { … }

@Autowiredprivate MainMenu mainMenu;

@Component@UIScopepublic class DefaultMainMenu implements MainMenu { … }

@ U I S c o p e

@ 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

@Component@ViewScopepublic class NotesGadget {

@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@ 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

public interface HttpRequestStopWatch { … }

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

@SessionScope

@SessionScope@VaadinSessionScope

@SessionScope@VaadinSessionScope

@UIScope

@SessionScope@VaadinSessionScope

@UIScope @ViewScope

@SessionScope

@ApplicationScoped@SessionScope

@Vaadin SessionScope

@Vaadin SessionScope

@Vaadin SessionScope

@SessionScope

@Vaadin SessionScope

@Vaadin SessionScope

@Vaadin SessionScope

@UI Scope

@UI Scope

@UI Scope

@UI Scope

@UI Scope

@UI Scope

@ 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

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

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

}

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

@Autowiredprivate EventBus.ViewEventBus eventBus;

…}

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

}…

}

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

@Autowiredprivate EventBus.ViewEventBus eventBus;

}

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

@Autowiredprivate EventBus.ViewEventBus eventBus;

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

}

}

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

}}

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

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

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

Lessons learned

Lessons learned• DI is a powerful mechanism to decouple code

Lessons learned• DI is a powerful mechanism to decouple code

• Following DI almost certainly guarantees that best practices are followed

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

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

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

@peter_lehto

T H A N K Y O U !

top related