1. Introduction
Allows controller actions to ve invoked as promises. Relies on JDeferred as promise implementation.
Griffon version: 2.12.0
There are two ways to configure an action as a promise: implicit and explicit
Requires applying the @Promise annotation to the action method, making sure it returns a value.
For example:
package com.acme
import griffon.core.artifact.GriffonController
import griffon.inject.MVCMember
import griffon.metadata.ArtifactProviderFor
import griffon.plugins.jdeferred.Promise
import org.codehaus.griffon.runtime.core.artifact.AbstractGriffonController
import javax.annotation.Nonnull
@ArtifactProviderFor(GriffonController)
class SampleController extends AbstractGriffonController {
    @MVCMember @Nonnull SampleModel model
    @Promise
    int implicitMode() {
        model.count = model.count + 1
        model.count
    }
}The return value of the action will be set as the resolved value of the JDeferred Promise. Any exceptions that may occur
during the action’s execution will set as the Promises  rejected value.
This mode gives you further control on when a value may be resolved or rejected; it alos allows you to publish intermediate
results by calling notify. For example
package com.acme
import griffon.core.artifact.GriffonController
import griffon.core.controller.ControllerAction
import griffon.inject.MVCMember
import griffon.metadata.ArtifactProviderFor
import org.codehaus.griffon.runtime.core.artifact.AbstractGriffonController
import org.jdeferred.Deferred
import javax.annotation.Nonnull
@ArtifactProviderFor(GriffonController)
class SampleController extends AbstractGriffonController {
    @MVCMember @Nonnull SampleModel model
    @ControllerAction
    void explicitMode(@Nonnull Deferred deferred) {
        model.count = model.count + 1
        1.upto(3) { deferred.notify(it) }
        deferred.resolve(model.count)
    }
}Any exceptions that may occur during the action’s execution will be set as the Promises  rejected value if the
promise has not been resolved at that point.
1.1. Handling Results
Typically you’ll register callbacks on a Promise in order to handle results and errors delivered by the promise.
However promises are not available until the action is about to bhe executed, that’s too late to register a callback.
For this reason, the jdeferred plugin allows you to record callbacks ahead of time, using RecordingPromise in
combination with PromiseManager. Here’s how callbacks can be set on a view during it’s intialization
package com.acme;
import griffon.core.artifact.GriffonView;
import griffon.inject.MVCMember;
import griffon.metadata.ArtifactProviderFor;
import griffon.plugins.jdeferred.RecordingPromise;
import org.codehaus.griffon.runtime.javafx.artifact.AbstractJavaFXGriffonView;
import javax.annotation.Nonnull;
import javax.inject.Inject;
import java.util.Map;
@ArtifactProviderFor(GriffonView.class)
public class SampleView extends AbstractJavaFXGriffonView {
    @Inject private PromiseManager promiseManager;
    @MVCMember @Nonnull private SampleController controller;
    @Override
    public void mvcGroupInit(@Nonnull Map<String, Object> args) {
        RecordingPromise<String, Throwable, Void> promise = promiseManager.promiseFor(actionFor(controller, "click"));
        promise.done(r -> System.out.println("Result is " + r))
            .fail(Throwable::printStackTrace)
            .always((s, r, j) -> System.out.println("Finished!"));
    }
    @Override
    public void initUI() {
        // build the UI
    }
}Griffon version: 2.12.0
2. Build JDeferred
2.1. Gradle
You have two options for configuring this plugin: automatic and manual.
2.1.1. Automatic
As long as the project has the org.codehaus.griffon.griffon plugin applied to it you
may include the following snippet in build.gradle
dependencies {
    griffon 'org.codehaus.griffon.plugins:griffon-jdeferred-plugin:1.1.0'
}The griffon plugin will take care of the rest given its configuration.
2.1.2. Manual
You will need to configure any of the following blocks depending on your setup
dependencies {
    compile 'org.codehaus.griffon.plugins:griffon-jdeferred-core:1.1.0'
}dependencies {
    compile 'org.codehaus.griffon.plugins:griffon-jdeferred-javafx:1.1.0'
}dependencies {
    compile 'org.codehaus.griffon.plugins:griffon-jdeferred-lanterna:1.1.0'
}dependencies {
    compile 'org.codehaus.griffon.plugins:griffon-jdeferred-pivot:1.1.0'
}dependencies {
    compile 'org.codehaus.griffon.plugins:griffon-jdeferred-swing:1.1.0'
}2.2. Maven
First configure the griffon-jdeferred-plugin BOM in your POM file, by placing the following
snippet before the <build> element
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.codehaus.griffon.plugins</groupId>
            <artifactId>griffon-jdeferred-plugin</artifactId>
            <version>1.1.0</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>Next configure dependencies as required by your particular setup
<dependency>
    <groupId>org.codehaus.griffon.plugins</groupId>
    <artifactId>griffon-jdeferred-core</artifactId>
</dependency><dependency>
    <groupId>org.codehaus.griffon.plugins</groupId>
    <artifactId>griffon-jdeferred-javafx</artifactId>
</dependency><dependency>
    <groupId>org.codehaus.griffon.plugins</groupId>
    <artifactId>griffon-jdeferred-lanterna</artifactId>
</dependency><dependency>
    <groupId>org.codehaus.griffon.plugins</groupId>
    <artifactId>griffon-jdeferred-pivot</artifactId>
</dependency><dependency>
    <groupId>org.codehaus.griffon.plugins</groupId>
    <artifactId>griffon-jdeferred-swing</artifactId>
</dependency>3. Modules
The following sections display all bindings per module. Use this information to successfully override a binding on your own modules or to troubleshoot a module binding if the wrong type has been applied by the Griffon runtime.
3.1. JDeferred Core
Module name: jdeferred
bind(ActionManager.class)
    .to(JDeferredActionManager.class)
    .asSingleton();
bind(ActionHandler.class)
    .to(JDeferredActionHandler.class)
    .asSingleton();
bind(PromiseManager.class)
    .to(DefaultPromiseManager.class)
    .asSingleton();3.2. JDeferred JavaFX
Module name: jdeferred-javafx
Depends on: jdeferred
bind(ActionManager.class)
    .to(JDeferredJavaFXActionManager.class)
    .asSingleton();3.3. JDeferred Lanterna
Module name: jdeferred-lanterna
Depends on: jdeferred
bind(ActionManager.class)
    .to(JDeferredJavaLanternaManager.class)
    .asSingleton();