Ten Man-Years of JavaFX: Real World Project Experiences

650 views

Published on

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
650
On SlideShare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
6
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide
  • From a user survey.Users have started to expect well thought-out GUIs. Blame the iPhone ;-)
  • *click *JavaFX 1 had a licensing model that prohibited redistribution of the JARs. We solved this by using Java Web Start, that fetched the JARs on the first startup.[Shorten these quotes further]
  • *3 clicks *...and guess what happened one month later?*click*
  • I asked people that’s been working with LoadUi over the years.Fun:Almost everybody says this! More modern than Swing and.Poor IDE support:Because of JavaFX Script.Hard to debug:Because of JavaFX Script + Not Open Source.License issues:Not allowed to redistribute the runtime.Missing basic controls:No table view, no modal windows, etc.
  • FXML:MVC in Swing is hard. In JavaFX it’s natural.Multi-platform issues:Major problems on Windows Server. Mac problems (runs in headless mode which kills all Swing integration). Major drag-n-drop bug in Linux. All these are reportedly fixed in JavaFX 8.Living in the future:A lot of bugs are being fixed... In JavaFX 8, which already been delayed once. No backports.Things are still changing a lot: In JavaFX 2, there are builder classes for everything. In JavaFX 8, those will be removed.
  • You’re not a UX designer:In JavaFX you can easily create new controls, with shadows, drag and drop and reflections.It’s easy to go overboard, break conventions, and create stuff with bad usability.
  • I’m going to show how we use a few JavaFX components in LoadUI. This is probably the most interesting if you’ve been using JavaFX.Webview, med custom starterpage som öppnar youtubevideoninline. Charts, with old test-run.Tabs CSS repeating background
  • [Explain what the LoadUI canvas is]
  • Ten Man-Years of JavaFX: Real World Project Experiences

    1. 1. Ten Man-Years of JavaFX: Real World Project Experiences JavaZone 2013 Henrik Olsson @imheols
    2. 2. Session Overview  Our experiences – Why we chose JavaFX – How we use JavaFX – The great migration – Pros, cons and tips  Examples of JavaFX usage  Our tools – GuavaFX – TestFX  Introduction
    3. 3. About me  Developer and Product Owner of LoadUI – SmartBear Software in Stockholm  Worked with JavaFX for ~3 years  Contact – henrik.olsson@smartbear.com – linkedin.com/in/heols  This is my first conference session
    4. 4. LoadUI  Open Source load testing tool.  Sister application of SoapUI.
    5. 5. Session Overview  Our experiences – Why we chose JavaFX – How we use JavaFX – The great migration – Pros, cons and tips  Examples of JavaFX usage  Our tools – GuavaFX – TestFX  Introduction
    6. 6. Illustratordesign JavaFXimplementation
    7. 7. GUI as a Competitive Advantage
    8. 8. THE GREAT MIGRATION
    9. 9. “JavaFX 1 will reach end of life (EOL) in December.” The JavaFX Blog, Spring 2012 “We can’t finish the migration of LoadUI until early next year. Will we be able to redistribute our existing LoadUI versions after the EOL date?” SmartBear Sweden CTO, February 2012 “No, sorry.” Oracle Representative in a phone call, February 2012
    10. 10. “Several software engineers have warned against total rewrites, especially under schedule constraints or competitive pressures.” From Rewrite (programming) at Wikipedia
    11. 11. The JavaFX Blog, May 2013 “We've decided to create a workaround that will allow anyone to redistribute the JavaFX 1 Runtime. This solution is available today…” “The EOL is postponed to March 2013. Redistribution of the JavaFX 1 Runtime is not an option, for a number of reasons.” Oracle Representative, Fall of 2012 “The deadline will be very hard to meet. Is it possible to delay the EOL, or let us redistribute the JavaFX 1 Runtime?” Me, Fall of 2012 “We are done with the migration!” Me, April 2013
    12. 12. Migrating  41k lines of JavaFX 1 (JavaFX Script) to 32k lines of JavaFX 2 (Java). – In 9 months  JavaFX 1 and JavaFX 2 cannot co-exist.  All code isolated in an OSGi module.  More of a rewrite than a migration.
    13. 13. Performance 0 5 10 15 20 25 Windows Linux Windows Linux JavaFX 1 JavaFX 2
    14. 14. JavaFX 1 Good stuff  Flexible  CSS  Fun! Pitfalls  Poor IDE support  Hard to debug  License issues  Missing basic controls
    15. 15. JavaFX 2 Good stuff  Flexible  CSS  Fun! Pitfalls  Poor IDE support  Hard to debug  License issues  Missing basic controls  FXML – MVC for real!  Multi-platform issues  Undocumented weak references – Bindings.bindContent() – Bindings.bindBidirectional()  ”Living in the future”
    16. 16. Tips for starting with JavaFX 2  Run tests early on all platforms that you will support.  Learn and use CSS and FXML.  Use IntelliJ IDEA or NetBeans.  Prepare mentally to move to JavaFX 8.  You’re not a UX designer.  Enjoy! – JavaFX is cool, fun and here to stay.
    17. 17. Session Overview  Introduction  Our experiences – Why we chose JavaFX – How we use JavaFX – The great migration – Pros, cons and tips  Examples of JavaFX usage  Our tools – GuavaFX – TestFX
    18. 18. EXAMPLES OF JAVAFX USAGE
    19. 19. Session Overview  Introduction  Our experiences – Why we chose JavaFX – How we use JavaFX – The great migration – Pros, cons and tips  Examples of JavaFX usage  Our tools – GuavaFX – TestFX
    20. 20. GUAVAFX
    21. 21. What is GuavaFX?  Functional extensions for the ObservableList, inspired by Google Guava. – transform – filter – concat (preserves ordering)  Game changer for us.  Cached.  Using weak listeners. 
    22. 22. THE LOADUI CANVAS GuavaFX Case Study:
    23. 23. ObservableList<ComponentNode> components = transform(canvas.getComponents(), componentToNode); bindContent(componentLayer.getChildren(), components);
    24. 24. ObservableList<WireNode> wires = transform(canvas.getWires(), wireToNode); bindContent(wireLayer.getChildren(), wires);
    25. 25. ObservableList<Template> scenarioTemplates = ofServices(ScenarioTemplate.class); ObservableList<Template> componentTemplates = ofServices(ComponentTemplate.class) .filter(notDeprecated); ObservableList<TemplateNode> toolboxItems = concat(scenarioTemplates, componentTemplates).transform(templateToNode); bindContent(toolbox.getItems(), toolboxItems);
    26. 26. Code in plain JavaFX final ObservableList<ComponentNode> components = observableArrayList(); components.addListener(new InvalidationListener() { @Override public void invalidated(Observable observable) { componentLayer.getChildren().clear(); for( Component component : components ) { componentLayer.getChildren().add(componentToView(component)); } } }); final ObservableList<WireNode> wires = observableArrayList(); wires.addListener(new InvalidationListener() { @Override public void invalidated(Observable observable) { wireLayer.getChildren().clear(); for( Wire wire : wires ) { wireLayer.getChildren().add( wireToView( wire ) ); } } }); ObservableList<Descriptor> scenarioDescriptors = ofServices(ScenarioDescriptor.class); ObservableList<Descriptor> componentDescriptorsUnfiltered = ofServices(ComponentDescriptor.class); final ObservableList<Descriptor> componentDescriptors = observableArrayList(); componentDescriptorsUnfiltered.addListener(new InvalidationListener() { @Override public void invalidated(Observable observable) { componentDescriptorsUnfiltered.getChildren().clear(); for( Descriptor descriptor : componentDescriptorsUnfiltered ) { if( descriptor.isDeprecated() ) { componentDescriptors.getChildren().add( descriptor ); } } } }); final ObservableList<ToolBoxItem> toolboxItems = observableArrayList(); InvalidationListener concatListener = new InvalidationListener() { @Override public void invalidated(Observable observable) { toolboxItems.getChildren().clear(); for( Descriptor descriptor : componentDescriptorsUnfiltered ) { toolboxItems.getChildren().add(descriptorToView(descriptor)); } for( Descriptor descriptor : scenarioDescriptors ) { toolboxItems.getChildren().add(descriptorToView(descriptor)); } } } componentDescriptors.addListener(concatListener); scenarioDescriptors.addListener(concatListener); • Also has to remove all InvalidationListeners when no longer needed. • Performance is worse (no caching).
    27. 27. JavaFX 8  Current state: – ObservableList.filtered – ObservableList.sorted – No ObservableList.transformed  Will hopefully make GuavaFX obsolete. myObservableList.filtered(tweet -> tweet.isRetweet())
    28. 28. TESTFX
    29. 29. Why TestFX?  We needed: – Tests that any tester could follow and modify.  Options: – JemmyFX was too complicated and verbose. – FEST-JavaFX was dead. – MarvinFX didn’t yet exist. – No GUI testing software existed for JavaFX. – Write our own!
    30. 30. What is TestFX?  A fluent and fixture-less API for interacting with JavaFX applications: – rightClick("#desktop").moveMouseTo("New") .click("Text Document") .type("myTextfile.txt") .press(ENTER) – drag(myNode).to("#trash-can") – press(CONTROL, A)
    31. 31. What is TestFX?  ...and verifying JavaFX applications’ behavior: – assertThat("My folder", contains(3, ".file")) – clickNodeThat(hasLabel(endsWith("FX"))) – waitUntil(continueButton, is(enabled())) 
    32. 32. Key principles  Fixture-less – Don’t have to create fixtures for custom controls – Clean code that most testers can read – Enables TDD – Dangerous? /** It is always dangerous to directly access objects within Java FX hierarchy. All the access should be done through event queue. If done otherwise results are unpredictable at the best. */ • Not in our experience.  60 tests running for more than a year.  Stress test to provoke JavaFX/TestFX. » Using Timeline, bindings and millisecond precision assertions.
    33. 33. Key principles  Hamcrest Matchers – Makes use of regular Hamcrest Matchers. – Provides a few JavaFX specific Matchers.  States – Optional
    34. 34. JemmyFX official example @Test public void hello() { SceneDock scene = new SceneDock(); ListViewDock list = new ListViewDock(scene.asParent()); final TextInputControlDock address = new TextInputControlDock(scene.asParent()); String location = address.getText(); address.asSelectionText().to(address.getText().length()); address.type("testdata"); address.keyboard().pushKey(ENTER); new ListItemDock(list.asList(), new LookupCriteria() { @Override public boolean check(Object cntrl) { return cntrl.toString().endsWith("folder1"); } }).mouse().click(2); new ComboBoxDock(scene.asParent()).asSelectable().selector().select(new File(location)); address.wrap().waitProperty(Wrap.TEXT_PROP_NAME, location); new LabeledDock(scene.asParent(), "back_btn").mouse().click(); new ListItemDock(list.asList(), "file.txt", SUBSTRING).mouse().click(1); }
    35. 35. Same example in TestFX @Test public void hello() { click("#address-field").type("testdata").press(ENTER); doubleClick("folder1"); click(".combo-box").click("Tests"); click("#back_btn").click("file.txt"); }
    36. 36. ...with some Hamcrest matchers @Test public void hello() { click("#address-field").type("testdata").press(ENTER); doubleClick("folder1"); click(".combo-box").click("Tests"); click("#back_btn").click("file.txt"); assertThat("#directory-listing", contains(1, ".file")); assertThat("#directory-listing .file", hasLabel("file.txt")); }
    37. 37. How we use TestFX  GUI unit tests class MyTest extends GuiTest { @BeforeClass public static void createStage() { showNodeInStage( nodeUnderTest ); } @Test public static void nodeUnderTest_should_behave() { // Test logic goes here. } }
    38. 38. How we use TestFX  System tests – With states (TestState.java). • First state starts LoadUI.
    39. 39. System Tests LoadUI Started Notification PanelTest System LogTest ProjectCreated AgentsCreated MonitorTest Project ManagementTest ProjectLoaded TableLog Test EventHandling Test Execution Test Result ViewTest LastResult Opened Statistic TabsTest WireTest Linked PlaybackTest SimpleScenario ChartCompare Test ChartsTest PlaybackTest
    40. 40. Last slide  Links – loadui.org – github.com/SmartBear/loadui – github.com/SmartBear/GuavaFX – github.com/SmartBear/TestFX – miglayout.com  Thanks to – Dain Nilsson – Ole Lensmar – Sofia Stråth – LoadUI contributors – SmartBear Stockholm smartbear.com/careers
    41. 41. Q & A

    ×