The document provides an overview of the DataFX framework, which facilitates data retrieval and rendering in JavaFX applications. It discusses how DataFX allows developers to focus on application logic by abstracting away things like data sources, conversion, and threading. Key aspects covered include DataSources and Readers for retrieving data from various sources; Converters for transforming data formats; DataProviders for populating Observable data in JavaFX; controller APIs for building views; and Flow APIs for linking views and handling user actions. The goal of DataFX is to simplify common tasks in building enterprise JavaFX applications that interact with real-world services and data.
2. The Mission
In 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.
9. 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!
10. DataFX Executor
Executor executor = new ObservableExecutor();
ListView<Service<?>> list = new ListView<>();
list.setCellFactory(new ServiceCellFactory());
list.itemsProperty().
bind(executor.currentServicesProperty());
implementation ofjava.util.concurrent.Executor
bind your services to the view
11. DataFX Executor
supports title, message and progress for
each service
supports Runnable, Callable, Service &
Task
cancel services on the gui
13. Lambda Support
JDK 8 has Lambda and the awesome
Stream API
Map and reduce your collections in
parallel
But how to turn into the JavaFX
application thread?
14. Lambda Support
StreamFX<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
16. 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
18. DataReader
interface DataReader<T> {
T get();
boolean next();
}
Easy to
implement!
RestSource
FileSource
JDCBSource We provide this implementations
- with builder API -
21. Converter
interface 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
22. DataProvider
DataProviders 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
25. 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
26. 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
27. 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
Observable
external Data DataFX
28. 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
29. Writeback support
only one additional
class that handles
the writeback...
ObjectDataProvider.setWriteBackHandler(WriteBackHandler h);
ListDataDataProvider.setAddEntryHandler(WriteBackHandler h);
...and you only need
to implement one
method
30. Example
DataReader<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
31. Example
lodp.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
32. Writeback support
RestSource and JDBCSource already
implement WritableDataReader
Threading is dealt with by DataReader
implementations
Support of transient field by using
@WriteTransient
34. JAVAFX API
In JavaFX you should use FXML to
define your views
You 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>
35. Controller API
Some 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
36. 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
37. 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
38. Controller API
Provides a factory for view creation
Inject all needed Nodes with @FXML
Supports @PostConstruct
39. View Context
Controller API support 2 contexts
ApplicationContext
View Context
Inject context by using Annotation
Register your model to the context
40. View Context
public class DetailViewController {
@FXML
private TextField myTextfield;
@FXMLViewContext
private ViewContext<DetailViewController> context;
@PostConstruct
public void init() {
DataModel model = context.getViewFlowContext().
getRegisteredObject(DataModel.class);
myTextfield.textProperty().
bindBidirectional(model.getSelected());
}
}
injection
access
registered
objects
41. Conclusion
Create view with FXML
Define your model as pojo
Create a controller
bind all this by using annotations
48. 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 DetailsView
back
details
delete
51. Master Detail
Use 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?
52. 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
53. Flow API
share your data model by using contexts
ViewFlowContext added
@FXMLViewFlowContext
private ViewFlowContext context;
You can inject contexts in your
action classes, too
@PostConstruct and @PreDestroy are
covered by the view livecycle
54. Flow API
By using the flow API you don‘t have
dependencies between the views
Reuse views and actions
Use annotations for configuration