<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: liu tiger</title>
    <description>The latest articles on Forem by liu tiger (@liu_tiger_ef0f0505e13c8be).</description>
    <link>https://forem.com/liu_tiger_ef0f0505e13c8be</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3730887%2F186dc66e-4f3d-4f6e-bb2b-410efa4107d8.png</url>
      <title>Forem: liu tiger</title>
      <link>https://forem.com/liu_tiger_ef0f0505e13c8be</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/liu_tiger_ef0f0505e13c8be"/>
    <language>en</language>
    <item>
      <title>JavaFX UI Automation: Challenges, Existing Tools, and Real-World Event Handling Problems</title>
      <dc:creator>liu tiger</dc:creator>
      <pubDate>Wed, 11 Mar 2026 06:12:43 +0000</pubDate>
      <link>https://forem.com/liu_tiger_ef0f0505e13c8be/javafx-ui-automation-challenges-existing-tools-and-real-world-event-handling-problems-57k</link>
      <guid>https://forem.com/liu_tiger_ef0f0505e13c8be/javafx-ui-automation-challenges-existing-tools-and-real-world-event-handling-problems-57k</guid>
      <description>&lt;h1&gt;
  
  
  JavaFX UI Automation: Challenges, Existing Tools, and Real-World Event Handling Problems
&lt;/h1&gt;

&lt;p&gt;Automation testing has become a fundamental component of modern software engineering. In web development, automation ecosystems such as Selenium, Playwright, and Cypress are mature and widely adopted. However, the situation is very different for &lt;strong&gt;Java desktop applications&lt;/strong&gt;, particularly those built using &lt;strong&gt;JavaFX&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;While JavaFX provides a modern UI framework with rich rendering capabilities, its architecture introduces a number of challenges for automation testing. Many teams attempting to automate JavaFX applications quickly discover that existing automation tools struggle with object recognition, event propagation, popup windows, and internal control structures.&lt;/p&gt;

&lt;p&gt;This article summarizes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The current ecosystem of JavaFX automation tools
&lt;/li&gt;
&lt;li&gt;Their underlying technology stacks
&lt;/li&gt;
&lt;li&gt;Common issues encountered during real-world automation
&lt;/li&gt;
&lt;li&gt;Typical problems related to JavaFX event handling
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally, we briefly mention how newer automation platforms are addressing these problems in practice.&lt;/p&gt;




&lt;h1&gt;
  
  
  Why JavaFX Automation Is Difficult
&lt;/h1&gt;

&lt;p&gt;JavaFX differs significantly from earlier Java desktop UI frameworks such as Swing or AWT. Its architecture includes several design decisions that make UI automation more complicated.&lt;/p&gt;

&lt;p&gt;Key architectural elements include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Scene Graph–based UI structure&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CSS styling&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Control + Skin separation&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GPU rendering&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Complex event propagation model&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These features provide strong UI flexibility, but they also introduce complexity when attempting to automatically identify UI controls and simulate user interactions.&lt;/p&gt;

&lt;p&gt;For automation systems, several questions become non-trivial:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is the &lt;em&gt;actual UI control&lt;/em&gt; the user clicked?&lt;/li&gt;
&lt;li&gt;Which node in the Scene Graph corresponds to a business-level control?&lt;/li&gt;
&lt;li&gt;How do we handle popups and menus running in separate windows?&lt;/li&gt;
&lt;li&gt;How do we deal with event redirection and skin-level nodes?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Understanding the current tool ecosystem helps clarify where the difficulties originate.&lt;/p&gt;




&lt;h1&gt;
  
  
  Existing JavaFX Automation Tools
&lt;/h1&gt;

&lt;p&gt;Several tools and frameworks have attempted to support JavaFX automation. These typically come from three categories:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Java test frameworks extended for UI testing
&lt;/li&gt;
&lt;li&gt;UI automation libraries
&lt;/li&gt;
&lt;li&gt;Visual automation tools
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Below are some of the most commonly used solutions.&lt;/p&gt;




&lt;h1&gt;
  
  
  TestFX
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Technology Stack
&lt;/h2&gt;

&lt;p&gt;TestFX is one of the most well-known open-source frameworks designed for JavaFX UI testing.&lt;/p&gt;

&lt;p&gt;Its typical technology stack includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Java&lt;/li&gt;
&lt;li&gt;JUnit / TestNG&lt;/li&gt;
&lt;li&gt;JavaFX Robot&lt;/li&gt;
&lt;li&gt;Scene Graph queries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example usage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;clickOn&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"#loginButton"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"admin"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;clickOn&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"#submit"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="nc"&gt;TestFX&lt;/span&gt; &lt;span class="n"&gt;provides&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="no"&gt;DSL&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;style&lt;/span&gt; &lt;span class="no"&gt;API&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;simulate&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="n"&gt;interactions&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="nc"&gt;JavaFX&lt;/span&gt; &lt;span class="n"&gt;controls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;

&lt;span class="o"&gt;---&lt;/span&gt;

&lt;span class="err"&gt;##&lt;/span&gt; &lt;span class="nc"&gt;Limitations&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="nc"&gt;TestFX&lt;/span&gt;

&lt;span class="nc"&gt;Although&lt;/span&gt; &lt;span class="nc"&gt;TestFX&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="n"&gt;useful&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="n"&gt;simple&lt;/span&gt; &lt;span class="n"&gt;scenarios&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;real&lt;/span&gt; &lt;span class="n"&gt;enterprise&lt;/span&gt; &lt;span class="n"&gt;applications&lt;/span&gt; &lt;span class="n"&gt;often&lt;/span&gt; &lt;span class="n"&gt;reveal&lt;/span&gt; &lt;span class="n"&gt;several&lt;/span&gt; &lt;span class="n"&gt;limitations&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;

&lt;span class="err"&gt;###&lt;/span&gt; &lt;span class="nc"&gt;Dependency&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="no"&gt;CSS&lt;/span&gt; &lt;span class="nc"&gt;Selectors&lt;/span&gt;

&lt;span class="nc"&gt;TestFX&lt;/span&gt; &lt;span class="n"&gt;frequently&lt;/span&gt; &lt;span class="n"&gt;relies&lt;/span&gt; &lt;span class="nl"&gt;on:&lt;/span&gt;

&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="nl"&gt;fx:&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="no"&gt;CSS&lt;/span&gt; &lt;span class="n"&gt;selectors&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="n"&gt;lookup&lt;/span&gt; &lt;span class="n"&gt;queries&lt;/span&gt;

&lt;span class="nc"&gt;In&lt;/span&gt; &lt;span class="n"&gt;real&lt;/span&gt; &lt;span class="nl"&gt;systems:&lt;/span&gt;

&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;many&lt;/span&gt; &lt;span class="n"&gt;controls&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="n"&gt;not&lt;/span&gt; &lt;span class="n"&gt;have&lt;/span&gt; &lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="nl"&gt;fx:&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;dynamic&lt;/span&gt; &lt;span class="n"&gt;controls&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;created&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;runtime&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;complex&lt;/span&gt; &lt;span class="n"&gt;controls&lt;/span&gt; &lt;span class="n"&gt;generate&lt;/span&gt; &lt;span class="n"&gt;deeply&lt;/span&gt; &lt;span class="n"&gt;nested&lt;/span&gt; &lt;span class="n"&gt;structures&lt;/span&gt;

&lt;span class="nc"&gt;As&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="n"&gt;identification&lt;/span&gt; &lt;span class="n"&gt;can&lt;/span&gt; &lt;span class="n"&gt;become&lt;/span&gt; &lt;span class="n"&gt;unstable&lt;/span&gt; &lt;span class="n"&gt;or&lt;/span&gt; &lt;span class="n"&gt;difficult&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;maintain&lt;/span&gt; &lt;span class="n"&gt;across&lt;/span&gt; &lt;span class="n"&gt;application&lt;/span&gt; &lt;span class="n"&gt;versions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;

&lt;span class="o"&gt;---&lt;/span&gt;

&lt;span class="err"&gt;###&lt;/span&gt; &lt;span class="nc"&gt;Popup&lt;/span&gt; &lt;span class="nc"&gt;Components&lt;/span&gt; &lt;span class="nc"&gt;Are&lt;/span&gt; &lt;span class="nc"&gt;Difficult&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="nc"&gt;Detect&lt;/span&gt;

&lt;span class="nc"&gt;Several&lt;/span&gt; &lt;span class="nc"&gt;JavaFX&lt;/span&gt; &lt;span class="no"&gt;UI&lt;/span&gt; &lt;span class="n"&gt;components&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;implemented&lt;/span&gt; &lt;span class="n"&gt;as&lt;/span&gt; &lt;span class="n"&gt;popup&lt;/span&gt; &lt;span class="n"&gt;windows&lt;/span&gt; &lt;span class="n"&gt;rather&lt;/span&gt; &lt;span class="n"&gt;than&lt;/span&gt; &lt;span class="n"&gt;part&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt; &lt;span class="nc"&gt;Scene&lt;/span&gt; &lt;span class="nc"&gt;Graph&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nc"&gt;Examples&lt;/span&gt; &lt;span class="nl"&gt;include:&lt;/span&gt;

&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="nc"&gt;ComboBox&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt; &lt;span class="n"&gt;dropdown&lt;/span&gt; &lt;span class="n"&gt;menus&lt;/span&gt;  
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="nc"&gt;ContextMenu&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;  
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="nc"&gt;Tooltip&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;

&lt;span class="nc"&gt;Internally&lt;/span&gt; &lt;span class="n"&gt;these&lt;/span&gt; &lt;span class="n"&gt;components&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;implemented&lt;/span&gt; &lt;span class="n"&gt;using&lt;/span&gt; &lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="nc"&gt;PopupWindow&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;meaning&lt;/span&gt; &lt;span class="n"&gt;they&lt;/span&gt; &lt;span class="n"&gt;exist&lt;/span&gt; &lt;span class="n"&gt;outside&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;primary&lt;/span&gt; &lt;span class="n"&gt;scene&lt;/span&gt; &lt;span class="n"&gt;hierarchy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;

&lt;span class="nc"&gt;Automation&lt;/span&gt; &lt;span class="n"&gt;frameworks&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt; &lt;span class="n"&gt;only&lt;/span&gt; &lt;span class="n"&gt;inspect&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt; &lt;span class="nc"&gt;Scene&lt;/span&gt; &lt;span class="nc"&gt;Graph&lt;/span&gt; &lt;span class="n"&gt;often&lt;/span&gt; &lt;span class="n"&gt;fail&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;detect&lt;/span&gt; &lt;span class="n"&gt;these&lt;/span&gt; &lt;span class="no"&gt;UI&lt;/span&gt; &lt;span class="n"&gt;elements&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;

&lt;span class="o"&gt;---&lt;/span&gt;

&lt;span class="err"&gt;###&lt;/span&gt; &lt;span class="nc"&gt;Event&lt;/span&gt; &lt;span class="nc"&gt;Target&lt;/span&gt; &lt;span class="nc"&gt;Inconsistency&lt;/span&gt;

&lt;span class="nc"&gt;In&lt;/span&gt; &lt;span class="nc"&gt;JavaFX&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="nl"&gt;of:&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
java&lt;br&gt;
event.getTarget()&lt;/p&gt;

&lt;p&gt;does not always correspond to the actual business control.&lt;/p&gt;

&lt;p&gt;For example, clicking a CheckBox may produce event targets such as:&lt;/p&gt;

&lt;p&gt;LabeledText&lt;br&gt;
StackPane&lt;br&gt;
TabPane&lt;/p&gt;

&lt;p&gt;This occurs because JavaFX controls are rendered through Skin implementations, which contain multiple internal layout nodes.&lt;/p&gt;

&lt;p&gt;Automation frameworks must therefore reconstruct the true UI control context by traversing the parent hierarchy.&lt;/p&gt;

&lt;h1&gt;
  
  
  JemmyFX
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Technical Stack
&lt;/h2&gt;

&lt;p&gt;JemmyFX originated from the NetBeans ecosystem and extended the Jemmy framework to support JavaFX automation testing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Its architecture typically includes:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Java Robot interaction&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scene Graph traversal&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;operator-based control abstraction&lt;br&gt;
The overall design is conceptually similar to Swing’s Jemmy testing framework.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Limitations
&lt;/h2&gt;

&lt;p&gt;Although JemmyFX was promising in earlier JavaFX versions, several challenges remain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limited Maintenance
&lt;/h2&gt;

&lt;p&gt;As JavaFX evolved, JemmyFX development slowed, leaving compatibility gaps with newer JavaFX releases.&lt;/p&gt;




&lt;p&gt;Automation frameworks built on JemmyFX may therefore encounter issues when used with modern JavaFX environments.&lt;/p&gt;

&lt;p&gt;Internal Node Exposure&lt;/p&gt;

&lt;p&gt;JavaFX controls are usually composed of multiple internal nodes.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;CheckBox&lt;br&gt;
 └── StackPane&lt;br&gt;
     └── LabeledText&lt;/p&gt;

&lt;p&gt;If the user clicks the text region, the event target becomes LabeledText rather than the CheckBox.&lt;/p&gt;

&lt;p&gt;Automation frameworks that rely directly on event targets may therefore misinterpret the user interaction.&lt;/p&gt;

&lt;p&gt;Skin Structure Changes&lt;/p&gt;

&lt;p&gt;JavaFX relies heavily on the Skin architecture:&lt;/p&gt;

&lt;p&gt;Control&lt;br&gt;
 └── Skin&lt;br&gt;
     └── internal nodes&lt;/p&gt;

&lt;p&gt;The internal node hierarchy may change between JavaFX versions, causing automation scripts that rely on internal structure to become fragile.&lt;/p&gt;

&lt;h1&gt;
  
  
  Image-Based Automation Tools
&lt;/h1&gt;

&lt;p&gt;Some teams avoid JavaFX structural complexity by using image recognition tools such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sikuli&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;OpenCV-based UI automation frameworks&lt;/p&gt;

&lt;p&gt;These tools interact with applications by matching screenshots rather than inspecting UI structure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limitations
&lt;/h2&gt;

&lt;p&gt;While image-based automation bypasses Scene Graph complexity, it introduces different limitations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resolution Dependency
&lt;/h2&gt;

&lt;p&gt;Even small UI layout changes or display scaling differences may cause image recognition to fail.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance Overhead
&lt;/h2&gt;

&lt;p&gt;Pixel-based comparison operations are computationally expensive, which can slow down automated test execution.&lt;/p&gt;

&lt;p&gt;Lack of Semantic Understanding&lt;/p&gt;

&lt;p&gt;Image recognition tools cannot interpret:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;UI control types&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;application logic&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;application state&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They operate purely on visual patterns rather than UI semantics.&lt;/p&gt;

&lt;p&gt;Event Handling Problems in JavaFX Automation&lt;/p&gt;

&lt;p&gt;One of the most complex aspects of JavaFX automation testing is the event system.&lt;/p&gt;

&lt;p&gt;Event Target Does Not Represent the Actual Control&lt;/p&gt;

&lt;p&gt;The value returned by:&lt;/p&gt;

&lt;p&gt;event.getTarget()&lt;/p&gt;

&lt;p&gt;may not correspond to the control the user intended to interact with.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;User clicks CheckBox&lt;br&gt;
event.getTarget() == TabPane&lt;/p&gt;

&lt;p&gt;or&lt;/p&gt;

&lt;p&gt;event.getTarget() == LabeledText&lt;/p&gt;

&lt;p&gt;This happens because the click occurs on an internal node inside the control’s Skin.&lt;/p&gt;

&lt;p&gt;Automation frameworks must therefore determine the actual control by analyzing the parent node hierarchy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Popup Components Use Separate Windows
&lt;/h2&gt;

&lt;p&gt;Many JavaFX components operate in independent popup windows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;ContextMenu&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ComboBox dropdown&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tooltip&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These elements are created using PopupWindow rather than being part of the primary Scene Graph.&lt;/p&gt;

&lt;p&gt;Automation frameworks that only monitor the main Scene will miss interactions occurring within popup components.&lt;/p&gt;

&lt;h1&gt;
  
  
  Skin-Based Rendering Alters Event Paths
&lt;/h1&gt;

&lt;p&gt;A typical JavaFX control hierarchy might appear as:&lt;/p&gt;

&lt;p&gt;CheckBox&lt;br&gt;
 └── CheckBoxSkin&lt;br&gt;
     └── StackPane&lt;br&gt;
         └── Text&lt;/p&gt;

&lt;p&gt;If the user clicks the Text node, the event target becomes Text.&lt;/p&gt;

&lt;p&gt;Automation frameworks must therefore traverse upward in the node hierarchy to identify the real control.&lt;/p&gt;

&lt;h2&gt;
  
  
  TabPane Event Propagation
&lt;/h2&gt;

&lt;p&gt;Within a TabPane, UI elements are wrapped inside several container layers.&lt;/p&gt;

&lt;p&gt;An event propagation path may appear as:&lt;/p&gt;

&lt;p&gt;Text&lt;br&gt;
 → StackPane&lt;br&gt;
 → TabContentRegion&lt;br&gt;
 → TabPane&lt;/p&gt;

&lt;p&gt;Automation frameworks that rely solely on event.getTarget() may incorrectly assume that the interaction belongs to the container.&lt;/p&gt;

&lt;h2&gt;
  
  
  Event Redirection
&lt;/h2&gt;

&lt;p&gt;Some JavaFX controls internally consume or re-dispatch events.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;Event.fireEvent(...)&lt;/p&gt;

&lt;p&gt;When this occurs, the final event target may differ from the original node that received the click.&lt;/p&gt;

&lt;p&gt;Structural Challenges for Automation Frameworks&lt;/p&gt;

&lt;p&gt;Overall, JavaFX introduces several structural challenges for automation testing:&lt;/p&gt;

&lt;h2&gt;
  
  
  complex Scene Graph hierarchies
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Skin-based UI implementation
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;multiple window layers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;unstable event targets&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;internal node structures that may change between versions&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Traditional automation frameworks often struggle to handle these characteristics reliably.&lt;/p&gt;

&lt;h1&gt;
  
  
  Enterprise JavaFX Automation Requirements
&lt;/h1&gt;

&lt;p&gt;In enterprise environments, JavaFX applications are often used for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;financial trading platforms&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;risk management systems&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;data analysis clients&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;enterprise management dashboards&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Such systems require automation frameworks capable of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;reliable UI control identification&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;full Scene Graph traversal&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;multi-window event monitoring&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;accurate interpretation of user interactions&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Emerging Developer Tooling
&lt;/h1&gt;

&lt;p&gt;With the rise of AI-assisted development environments, new approaches are emerging for automation tooling.&lt;/p&gt;

&lt;p&gt;A Java Desktop automation extension for developer environments such as VS Code and Cursor is currently under development.&lt;/p&gt;

&lt;p&gt;The extension will provide capabilities including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;JavaFX UI object inspection&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;record &amp;amp; replay automation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;UI test step generation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;integration with MCP (Model Context Protocol)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The extension version supporting Code and Cursor is planned for release in the near future.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;JavaFX enables the development of modern, high-performance Java desktop applications, but its architecture introduces several challenges for automation testing.&lt;/p&gt;

&lt;p&gt;Existing tools such as:&lt;/p&gt;

&lt;p&gt;TestFX&lt;/p&gt;

&lt;p&gt;JemmyFX&lt;/p&gt;

&lt;p&gt;image-based frameworks&lt;/p&gt;

&lt;p&gt;each attempt to address part of the problem but often encounter difficulties related to Scene Graph traversal, popup windows, and event handling.&lt;/p&gt;

&lt;p&gt;Understanding these structural issues is essential when designing automation frameworks for JavaFX applications.&lt;/p&gt;

&lt;p&gt;Among existing solutions, the MARS automation testing platform focuses on addressing these complex scenarios. By analyzing UI structures and event propagation behaviors more deeply, MARS is able to reliably identify the actual UI control involved in user interactions, even within complex JavaFX environments.&lt;/p&gt;

</description>
      <category>automation</category>
      <category>java</category>
      <category>testing</category>
      <category>ui</category>
    </item>
    <item>
      <title>We’re Building a Protocol to Turn Real-World Actions into On-Chain Truth — Looking for Feedback</title>
      <dc:creator>liu tiger</dc:creator>
      <pubDate>Sun, 25 Jan 2026 03:12:09 +0000</pubDate>
      <link>https://forem.com/liu_tiger_ef0f0505e13c8be/were-building-a-protocol-to-turn-real-world-actions-into-on-chain-truth-looking-for-feedback-4ob2</link>
      <guid>https://forem.com/liu_tiger_ef0f0505e13c8be/were-building-a-protocol-to-turn-real-world-actions-into-on-chain-truth-looking-for-feedback-4ob2</guid>
      <description>&lt;h1&gt;
  
  
  TrustFlow: Turning Real-World Actions into On-Chain Truth
&lt;/h1&gt;

&lt;p&gt;Hi dev.to community 👋  &lt;/p&gt;

&lt;p&gt;I’m building &lt;strong&gt;TrustFlow&lt;/strong&gt;, an open protocol that aims to solve a gap many of us keep re-implementing in different ways:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Smart contracts are deterministic, but real-world execution is not.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;TrustFlow models real-world, multi-party processes as &lt;strong&gt;verifiable state machines&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
Execution happens off-chain, evidence is collected and verified, and only &lt;strong&gt;finalized state commitments&lt;/strong&gt; are anchored on-chain for settlement and dispute resolution.&lt;/p&gt;

&lt;p&gt;Key ideas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Protocol-first (not a vertical app, not SaaS)&lt;/li&gt;
&lt;li&gt;Clear separation: execution → verification → settlement&lt;/li&gt;
&lt;li&gt;Minimal on-chain footprint, dispute-aware by design&lt;/li&gt;
&lt;li&gt;Designed to generalize beyond any single use case&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The current repo includes a &lt;strong&gt;car rental workflow&lt;/strong&gt; as a reference implementation — not because rental is the goal, but because it’s a good example of a dispute-prone, real-world process.&lt;/p&gt;

&lt;p&gt;I’d really appreciate feedback on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The protocol abstraction itself&lt;/li&gt;
&lt;li&gt;Missing edge cases or failure modes&lt;/li&gt;
&lt;li&gt;Similar problems you’ve faced in Web3 or hybrid systems&lt;/li&gt;
&lt;li&gt;Whether this feels like a useful primitive or over-engineering
Repo &amp;amp; docs: &lt;a href="https://trustflow.live" rel="noopener noreferrer"&gt;https://trustflow.live&lt;/a&gt;
Thanks in advance for any thoughts or criticism.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Repo &amp;amp; docs: &lt;a href="https://trustflow.live" rel="noopener noreferrer"&gt;https://trustflow.live&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Thanks in advance for any thoughts or criticism.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>ai</category>
      <category>webdev</category>
      <category>software</category>
    </item>
  </channel>
</rss>
