JacpFX Non Blocking UI


The JacpFX component lifecycle separates the tasks execution and state changes from each other. When a FXComponent receives a message, it first executes a handle method, which is running inside a worker thread. In this stage you can execute any long running task or create new JavaFX nodes without blocking the application. When the task execution is finished, the subsequent postHandle method will be executed inside the FX Application thread.

component-lifecycle

JacpFX FXComponent

@View(id = ComponentIds.COMPONENT__TWO,
        name = "SimpleView",
        active = true,
        resourceBundleLocation = "bundles.languageBundle",
        initialTargetLayoutId = PerspectiveIds.TARGET__CONTAINER_MAIN)
public class ComponentTwo implements FXComponent {
    private GridPane rootPane;
    @Override
    public Node handle(final Message message) {
        // runs in worker thread 
        ...
        return new GridPane();
    }
    
    @Override
    public Node postHandle(final Node node,
                           final Message message) {
        // runs in FX application thread 
        this.rootPane= node;
        node.getChildren().add(new Label("xyz"));
        return node
    }
 
}

JacpFX Callback-Components


A JacpFX CallbackComponent has no UI, and therefore no need to switch to the FX Application thread. CallbackComponents can be used to outsource long running tasks, or to coordinate a message flow.

component-lifecycle



A JacpFX CallbackComponent can be either stateful or stateless.

Stateful Callback-Component:

@Component(id = ComponentIds.STATEFUL_CALLBACK, name = "statefulCallback", active = true, resourceBundleLocation = "bundles.languageBundle", localeID = "en_US")
public class StatefulCallback implements CallbackComponent {
    private Logger log = Logger.getLogger(StatefulCallback.class.getName());
    @Override
    public Object handle(final Message message) {
        log.info(message.getMessageBody().toString());
        return "StatefulCallback - hello";
    }
 
}


Stateless Callback-Component:

@Component(id = ComponentIds.STATELESS_CALLBACK, name = "statelessCallback", active = true, resourceBundleLocation = "bundles.languageBundle", localeID = "en_US")
@Stateless
public class StatelessCallback implements CallbackComponent {
    private Logger log = Logger.getLogger(StatelessCallback.class.getName());
    @Override
    public Object handle(final Message message) {
        log.info(message.getMessageBody().toString());
        return "StatelessCallback - hello";
    }
 
}
shadow