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 Promise
s 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 Promise
s 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();