Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.

DataFX - JavaOne 2013

62.190 Aufrufe

Veröffentlicht am

The best way to get real-world data into your JavaFX application

Veröffentlicht in: Technologie

DataFX - JavaOne 2013

  1. 1. DataFXThe best way to get real-world data into your JavaFX application
  2. 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.
  3. 3. About us Hendrik Ebbers @hendrikEbbers www.guigarage.com. . Johan Vos @johanvos www.lodgon.com. .
  4. 4. Overview
  5. 5. Overview DataSources Websocket Cells Flow
  6. 6. Use DataFX
  7. 7. Use DataFX JSF View Browser Desktop Client Business Layer O r m aybe m obile... Server Persistence REST
  8. 8. Concurrency
  9. 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. 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. 11. DataFX Executor supports title, message and progress for each service supports Runnable, Callable, Service & Task cancel services on the gui
  12. 12. Let‘s wait void ConcurrentUtils.runAndWait(Runnable runnable) T ConcurrentUtils.runAndWait(Callable<T> callable) like SwingUtilities.invokeAndWait(...) we will collect all concurrent helper methods here
  13. 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. 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
  15. 15. DataSources
  16. 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
  17. 17. DataSources Data Observable / ObservableList DataFX DataProvider DataReader Converter
  18. 18. DataReader interface DataReader<T> { T get(); boolean next(); } Easy to implement! RestSource FileSource JDCBSource We provide this implementations - with builder API -
  19. 19. RestReader RestSource 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-
  20. 20. 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
  21. 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. 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
  23. 23. DataProvider API distinction between ObjectDataProvider and ListDataProvider Builders are provided: ObjectDataProviderBuilder ListDataProviderBuilder
  24. 24. Usage ObservableValue<T> dataProvider.getData(); Worker<T> dataProvider.retrieve().getValue(); DataProvider.setResultObjectProperty(o); different patterns for different developers How to populate Observable o with the retrieved value via DataProvider<T> dataProvider? or or
  25. 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. 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. 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. 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. 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. 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. 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. 32. Writeback support RestSource and JDBCSource already implement WritableDataReader Threading is dealt with by DataReader implementations Support of transient field by using @WriteTransient
  33. 33. Controller API
  34. 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. 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. 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. 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. 38. Controller API Provides a factory for view creation Inject all needed Nodes with @FXML Supports @PostConstruct
  39. 39. View Context Controller API support 2 contexts ApplicationContext View Context Inject context by using Annotation Register your model to the context
  40. 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. 41. Conclusion Create view with FXML Define your model as pojo Create a controller bind all this by using annotations
  42. 42. Flow API
  43. 43. Flow API Controller API is good for one view How to link different view?
  44. 44. Flow API open View View View View View View searc h details open diagram setting *
  45. 45. Master Detail two views: master and detail use FXML switch from one view to the other one delete data on user action decoupling all this stuff!!
  46. 46. Master Detail MasterView DetailsView back details delete
  47. 47. Master Detail MasterView DetailsView back details FXML Controller FXML Controller delete
  48. 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
  49. 49. Master Detail detailView.withChangeViewAction("back", masterView); direct link between the views action name MasterView DetailsView back details delete
  50. 50. Master Detail masterView.withRunAction("delete", DeleteAction.class); define a custom action action name delete MasterView DetailsView back details delete
  51. 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. 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. 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. 54. Flow API By using the flow API you don‘t have dependencies between the views Reuse views and actions Use annotations for configuration
  55. 55. more stuff Websocket API Cell API FileSource
  56. 56. www.javafxdata.org https://bitbucket.org/datafx/datafx https://bitbucket.org/datafx/javafxcommunity
  57. 57. QA