Download - DataFX - JavaOne 2013

Transcript
Page 1: DataFX - JavaOne 2013

DataFXThe best way to get real-world data

into your JavaFX application

Page 2: DataFX - JavaOne 2013

The MissionIn this session, you'll learn how to develop Enterprise Applications in JavaFX with

Real-World Services and Data.

We will show how the DataFX framework facilitates the process of data retrieval and rendering, and how it allows you to focus

on your application-specific logic.

Page 4: DataFX - JavaOne 2013

Overview

Page 5: DataFX - JavaOne 2013

OverviewDataSources Websocket

Cells

Flow

Page 6: DataFX - JavaOne 2013

Use DataFX

Page 7: DataFX - JavaOne 2013

Use DataFX

JSF View

Browser Desktop Client

Business Layer

Or m

aybe

mobil

e...

Server

Persistence

REST

Page 8: DataFX - JavaOne 2013

Concurrency

Page 9: DataFX - JavaOne 2013

Concurrency API

JavaFX is a single threaded toolkit

You should not block the platform thread

Rest calls may take some time...

...and could freeze the application

Do not do this at home!

Page 10: DataFX - JavaOne 2013

DataFX Executor

Executor executor = new ObservableExecutor();ListView<Service<?>> list = new ListView<>();list.setCellFactory(new ServiceCellFactory());

list.itemsProperty().bind(executor.currentServicesProperty());

implementation of java.util.concurrent.Executor

bind your services to the view

Page 11: DataFX - JavaOne 2013

DataFX Executorsupports title, message and progress for each service

supports Runnable, Callable, Service & Task

cancel services on the gui

Page 12: DataFX - JavaOne 2013

Let‘s wait

void ConcurrentUtils.runAndWait(Runnable runnable)

T ConcurrentUtils.runAndWait(Callable<T> callable)

like SwingUtilities.invokeAndWait(...)

we will collect allconcurrent helper

methods here

Page 13: DataFX - JavaOne 2013

Lambda Support

JDK 8 has Lambda and the awesome Stream APIMap and reduce your collections in parallelBut how to turn into the JavaFX application thread?

Page 14: DataFX - JavaOne 2013

Lambda SupportStreamFX<T> streamFX = new StreamFX<>(myStream);

it is a wrapper

ObservableList<T> list = ...;streamFX.publish(list);

streamFX.forEachOrdered(final Consumer<ObjectProperty<? super T>> action)

this will happen in the application thread

Page 15: DataFX - JavaOne 2013

DataSources

Page 16: DataFX - JavaOne 2013

DataSources

Obtain data from a variety of sources, in a variety of formats and put the data in a JavaFX Observable or ObservableList Object.

Goal:

Variety of sources -> the DataReader abstracts this

Variety of formats -> the Converter abstracts this

**

1

11

*11

*1

Page 17: DataFX - JavaOne 2013

DataSourcesData

Observable /ObservableList

DataFX

DataProvider

DataReader

Converter

Page 18: DataFX - JavaOne 2013

DataReaderinterface DataReader<T> {

T get();

boolean next();

}

Easy to

implement!

RestSourceFileSourceJDCBSource We provide this implementations

- with builder API -

Page 19: DataFX - JavaOne 2013

RestReaderRestSource restSource = new RestSource();restSource.setHost(“myhost”);RestSource.setConverter(...);restSource.setPath("user/" + uid);restSource.setConsumerKey(“mykey”); restSource.setConsumerSecret(“mysecret”);

RestSourceBuilder.create().host(“myhost”).converter(...).path(“user”).path(uid).consumerKey(“myKey”).consumerSecret(“mysecret”).build()

-or-

Page 20: DataFX - JavaOne 2013

Data conversion

DataReader<T> has to provide data as an object of type T

Converter<U,T> consumes input as U, and provides data as T

Page 21: DataFX - JavaOne 2013

Converterinterface Converter<T,U> { public void initialize(T input); public U get(); public boolean next();}

create your custom one

JSONConverter<T> implements Converter<InputStream, T>RestSource reads an InputStream, and will ask Converter to deliver instance(s) of T

Page 22: DataFX - JavaOne 2013

DataProviderDataProviders populate JavaFX Observable and ObservableList instances

Data is added/changed on the JavaFX Application Thread only

Retrieval is done in a background thread, managable via an ExecutorPool

Page 23: DataFX - JavaOne 2013

DataProvider

API distinction between ObjectDataProvider and ListDataProvider

Builders are provided: ObjectDataProviderBuilder

ListDataProviderBuilder

Page 24: DataFX - JavaOne 2013

Usage

ObservableValue<T> dataProvider.getData();

Worker<T> dataProvider.retrieve().getValue();

DataProvider.setResultObjectProperty(o);

different

patterns f

or

different

developer

s

How to populate Observable o with the retrieved value via DataProvider<T> dataProvider?

or

or

Page 25: DataFX - JavaOne 2013

DataProvider

DataProviders leverage the Observable capabilities: content is added when it is available

ListDataProvider will add entities to the resulting ObservableList as long as input can be read from the DataReader

Page 26: DataFX - JavaOne 2013

DataProvider

Binding the ObservableList in a ListView will cause the ListView to be populated gradually

This can be leveraged in your application logic, i.e. First retrieve the most recent or important items

Page 27: DataFX - JavaOne 2013

Writeback support

Starting in DataFX 2.0, it is possible to make changes to retrieved data, and send those changes back to the original datasource

UI

Obs

erva

ble

external Data DataFX

Page 28: DataFX - JavaOne 2013

Challenges

We don't want to write-back all changes

In many cases, write-back is more complex than read, and not symmetrical

i.e. Authentication needed, different granularity

Page 29: DataFX - JavaOne 2013

Writeback supportonly one additional class that handles the writeback...

ObjectDataProvider.setWriteBackHandler(WriteBackHandler h);

ListDataDataProvider.setAddEntryHandler(WriteBackHandler h);

...and you only need to implement one

method

Page 30: DataFX - JavaOne 2013

ExampleDataReader<Person> dr = new JdbcSource(....);ListDataProvider<Person> lodp = new ListDataProvider(dr);

ObservableList<Person> myList = ...;lodp.setResultObservableList(myList);

lodp.setWriteBackHandler(new WriteBackHandler<Person>() {...});

ok, this is the part

we already know

adding writeback support

Page 31: DataFX - JavaOne 2013

Examplelodp.setWriteBackHandler(new WriteBackHandler<Person>() {

@Override public WritableDataReader createDataSource(Person me) {

String statement = "UPDATE PERSON SET lastName=\'" + me.getLastName() + "\' WHERE firstName=\'" + me.getFirstName() + "\'";

JdbcSource<Person> dr = new JdbcSource(dbURL, statement, null);

dr.setUpdateQuery(true);return dr;

}}); simple implementation of jdbc

writeback support

Page 32: DataFX - JavaOne 2013

Writeback supportRestSource and JDBCSource already implement WritableDataReader

Threading is dealt with by DataReader implementations

Support of transient field by using @WriteTransient

Page 33: DataFX - JavaOne 2013

Controller API

Page 34: DataFX - JavaOne 2013

JAVAFX APIIn JavaFX you should use FXML to define your viewsYou can define a controller for the view

Link from (FXML-) view to the controller

<HBox fx:controller="com.guigarage.MyController">    <TextField fx:id="myTextfield"/>    <Button fx:id="backButton" text="back"/></HBox>

Page 35: DataFX - JavaOne 2013

Controller APISome kind of inversion of control

Define the FXML in your controller class

Create a view by using the controller class

Supports more annotations for the view livecycle

convention over configuration

Page 36: DataFX - JavaOne 2013

Controller API@FXMLController("Details.fxml")public class DetailViewController {          @FXML        private TextField myTextfield;          @FXML        private Button backButton;            @PostConstruct        public void init() {            myTextfield.setText("Hello!");        }}

define the FXML file

default Java annotation

Page 37: DataFX - JavaOne 2013

Controller API<?xml version="1.0" encoding="UTF-8"?>  <?import javafx.scene.control.*?><?import javafx.scene.layout.*?>  <HBox spacing="10" alignment="bottom_right">    <TextField fx:id="myTextfield"/>    <Button fx:id="backButton" text="back"/></HBox>

use JavaFX Scene Builder!

no controller class is set in

FXML

Page 38: DataFX - JavaOne 2013

Controller API

Provides a factory for view creation

Inject all needed Nodes with @FXML

Supports @PostConstruct

Page 39: DataFX - JavaOne 2013

View Context

Controller API support 2 contextsApplicationContextView Context

Inject context by using Annotation

Register your model to the context

Page 40: DataFX - JavaOne 2013

View Contextpublic class DetailViewController {    @FXML  private TextField myTextfield;  @FXMLViewContextprivate ViewContext<DetailViewController> context;

    @PostConstruct  public void init() { DataModel model = context.getViewFlowContext(). getRegisteredObject(DataModel.class);

myTextfield.textProperty(). bindBidirectional(model.getSelected());  }}

injection

access registered objects

Page 41: DataFX - JavaOne 2013

ConclusionCreate view with FXML

Define your model as pojo

Create a controller

bind all this by using annotations

Page 42: DataFX - JavaOne 2013

Flow API

Page 43: DataFX - JavaOne 2013

Flow APIController API is good for one view

How to link different view?

Page 44: DataFX - JavaOne 2013

Flow APIopenView View

View

View

View

View

search

details

open

diagram

setting*

Page 45: DataFX - JavaOne 2013

Master Detailtwo views: master and detail

use FXML

switch from one view to the other one

delete data on user action

decoupling all this stuff!!

Page 46: DataFX - JavaOne 2013

Master Detail

MasterView DetailsViewback

detailsdelete

Page 47: DataFX - JavaOne 2013

Master Detail

MasterView DetailsViewback

details

FXML Controller FXML Controller

delete

Page 48: DataFX - JavaOne 2013

Master Detail

FXMLFlowView masterView = FXMLFlowView.create(MasterViewController.class);

FXMLFlowView detailView = FXMLFlowView.create(DetailViewController.class);

create one FLowView for each view

use controller API internally

MasterView DetailsViewback

detailsdelete

Page 49: DataFX - JavaOne 2013

Master Detail

detailView.withChangeViewAction("back", masterView);

direct link between the views

action name

MasterView DetailsViewback

detailsdelete

Page 50: DataFX - JavaOne 2013

Master Detail

masterView.withRunAction("delete", DeleteAction.class);

define a custom action

action name

delete

MasterView DetailsViewback

detailsdelete

Page 51: DataFX - JavaOne 2013

Master DetailUse controller API for all views

Define a FlowView for each view

link with by adding an action

add custom actions to your flow

but how can I use them?

Page 52: DataFX - JavaOne 2013

Master Detail@FXMLController("Details.fxml")public class DetailViewController {

@FXML @FlowAction("back") private Button backButton; @PostConstruct public void init() { //... } @PreDestroy public void destroy() { //... }}

controller API

defined in FXML

bind your flow actions by annotation

listen to the

flow

Page 53: DataFX - JavaOne 2013

Flow APIshare your data model by using contexts

ViewFlowContext added@FXMLViewFlowContextprivate ViewFlowContext context;

You can inject contexts in your

action classes, too

@PostConstruct and @PreDestroy are covered by the view livecycle

Page 54: DataFX - JavaOne 2013

Flow APIBy using the flow API you don‘t have dependencies between the viewsReuse views and actions Use annotations for configuration

Page 55: DataFX - JavaOne 2013

more stuff

Websocket APICell API

FileSource

Page 56: DataFX - JavaOne 2013

www.javafxdata.org

https://bitbucket.org/datafx/datafx

https://bitbucket.org/datafx/javafxcommunity

Page 57: DataFX - JavaOne 2013

QA