Class JavaFXSafeProxyCreator

java.lang.Object
it.tidalwave.ui.javafx.JavaFXSafeProxyCreator

public class JavaFXSafeProxyCreator extends Object
This facility class create a thread-safe proxy for the JavaFX delegate (controller). Thread-safe means that it can be called by any thread and the JavaFX UI related stuff will be safely invoked in the JavaFX UI Thread. It is usually used in this way:
 // This is a Spring bean
 public class JavaFxFooBarPresentation implements FooBarPresentation
   {
     private static final String FXML_URL = "/my/package/javafx/FooBar.fxml";

     @Inject
     private FlowController flowController;

     private final NodeAndDelegate nad = createNodeAndDelegate(getClass(), FXML_URL);

     private final FooBarPresentation delegate = nad.getDelegate();

     public void showUp()
       {
         flowController.doSomething(nad.getNode());
       }

     public void showData (final String data)
       {
         delegate.showData(data);
       }
   }
 
The method createNodeAndDelegate(java.lang.Class, java.lang.String) safely invokes the FXMLLoader and returns a NodeAndDelegate that contains both the visual Node and its delegate (controller). The latter is wrapped by a safe proxy that makes sure that any method invocation (such as showData() in the example is again executed in the JavaFX UI Thread. This means that the Presentation object methods can be invoked in any thread. For method returning void, the method invocation is asynchronous; that is, the caller is not blocked waiting for the method execution completion. If a return value is provided, the invocation is synchronous, and the caller will correctly wait the completion of the execution in order to get the result value. A typical JavaFX delegate (controller) looks like:
 // This is not a Spring bean - created by the FXMLLoader
 public class JavaFxFooBarPresentationDelegate implements FooBarPresentation
   {
     @FXML
     private Label label;

     @FXML
     private Button button;

     @Inject // the only thing that can be injected, by means of JavaFXSafeProxyCreator
     private JavaFxBinder binder;

     @Override
     public void bind (final UserAction action)
       {
         binder.bind(button, action);
       }

     @Override
     public void showData (final String data)
       {
         label.setText(data);
       }
  }
 
Not only all the methods invoked on the delegate are guaranteed to run in the JavaFX UI thread, but also its constructor, as per JavaFX requirements. A Presentation Delegate must not try to have dependency injection from Spring (for instance, by means of AOP), otherwise a deadlock could be triggered. Injection in constructors is safe.
Author:
Fabrizio Giudici
  • Field Details

  • Method Details

    • createNodeAndDelegate

      @Nonnull public static <T> NodeAndDelegate<T> createNodeAndDelegate(@Nonnull Class<T> presentationClass)
      Creates a NodeAndDelegate for the given presentation class. The FXML resource name is inferred by default, For instance, is the class is named JavaFXFooBarPresentation, the resource name is FooBar.fxml and searched in the same packages as the class.
      Parameters:
      presentationClass - the class of the presentation for which the resources must be created.
      Since:
      1.0-ALPHA-13
      See Also:
    • createNodeAndDelegate

      @Nonnull public static <T> NodeAndDelegate<T> createNodeAndDelegate(@Nonnull Class<T> presentationClass, @Nonnull String fxmlResourcePath)
      Creates a NodeAndDelegate for the given presentation class.
      Parameters:
      presentationClass - the class of the presentation for which the resources must be created.
      fxmlResourcePath - the path of the FXML resource
    • createSafeProxy

      @Nonnull public static <T> T createSafeProxy(@Nonnull T target, Class<?>[] interfaces)