View Source

{section}
{column:width=50%}
h3. The Functor Pattern
This is an {color:green}*example implementation*{color} of [Function Objects (Wikipedia)|http://en.wikipedia.org/wiki/Function_object] or as it is also known, the Functor Pattern, built with Coherence.

The Functor Pattern is an extension to the [Command Pattern]. In fact the semantics are identical with the exception that the Functor Pattern additionally provides a mechanism to return values (or re-throw exceptions) to the _Submitter_ (using Java 5+ [Futures|http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/Future.html]) where as the [Command Pattern] does not provide such capabilities. Consequently in order to use Functor Pattern it is highly recommended that you understand the [Command Pattern].

h3. Dependencies
This project (like other Coherence Incubator projects) uses [Apache Ivy|http://ant.apache.org/ivy/] for dependency specification and management. While a standard {{ivy.xml}} definition file ships with the source and documentation distribution, the following diagram visually indicates the current dependencies.

{center}
!Incubator-Dependencies-Functor.png!
{center}
{column}

{column:width=50%}
h3. Outline
|| *Release Name:* | *{color:red}Version 1.3.1: March 12th, 2010{color}* |
|| *Target Platforms:* | Java Standard Edition 5+ |
|| *Requires Coherence:* | 3.5.3+ |
|| *Dependencies:* | [Coherence Common 1.6.1 | Coherence Common 1.6.0]\\ [Command Pattern 2.6.1 | Command Pattern 2.6.0] |
|| *Download:* | [^coherence-functorpattern-1.3.1.14471.jar] \\ MD5: 35e714a8422cc05314c27a1798639842 |
|| *Source Code and \\Documentation:* | [^coherence-functorpattern-1.3.1.14471-src.zip] \\ MD5: b582f4b7f9c991dad690277291ca7a59 |
|| *Previous Releases:* | [Functor Pattern 1.2.0] \\ [Functor Pattern 1.1.0] \\ [Functor Pattern 1.0.0] |

h3. Rationale
The Functor Pattern provides a useful alternative to Oracle Coherence _EntryProcessors_ with the advantage that _Functors_ are executed asynchronously, instead of synchronously as is the case with _EntryProcessors_.
{column}
{section}

h3. What's New?
The following changes have been made since the Functor Pattern 1.3.0 release.

* Upgraded to use [Coherence Common 1.6.1|Coherence Common 1.6.0] and [Command Pattern 2.6.1|Command Pattern 2.6.0]

The following changes have been made since the [Functor Pattern 1.2.0] release.

* Upgraded to use [Coherence Common 1.6.0] and [Command Pattern 2.6.0]

h3. Example

Let's start with a simple example where we use the Functor Pattern to asynchronously increment and return the value of a {{Counter}}

First, we'll start by writing a simple {{Counter}}:
{code:java|title=Counter.java|borderStyle=solid}
import java.io.Serializable;
import com.oracle.coherence.patterns.command.Context;

public class Counter implements Context, Serializable {
private long next;
public Counter(long initialValue) {
this.next = initialValue;
}

public long next() {
return next++;
}

public String toString() {
return String.format("Counter{next=%d}", next);
}
}
{code}

Second, let's write a Functor that will increment the value of a {{Counter}}
{code:java|title=NextValueFunctor.java|borderStyle=solid}
import java.io.Serializable;
import com.oracle.coherence.patterns.command.ExecutionEnvironment;
import com.oracle.coherence.patterns.functor.Functor;

public class NextValueFunctor implements Functor<Counter, Long>, Serializable {
private static final long serialVersionUID = 4841498972676821911L;

public Long execute(ExecutionEnvironment<Counter> executionEnvironment) {
Counter counter = executionEnvironment.getContext();
long next = counter.next();
executionEnvironment.setContext(counter);
return next;
}
}
{code}

Lastly, let's write a simple example to test our Functor.
{code:java|title= FunctorPatternExample.java|borderStyle=solid}
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import com.oracle.coherence.common.identifiers.Identifier;
import com.oracle.coherence.patterns.command.ContextsManager;
import com.oracle.coherence.patterns.command.DefaultContextsManager;
import com.oracle.coherence.patterns.functor.DefaultFunctorSubmitter;
import com.oracle.coherence.patterns.functor.FunctorSubmitter;
import com.tangosol.net.CacheFactory;

public class FunctorPatternExample {
public static void main(String[] args) throws InterruptedException, ExecutionException {

ContextsManager contextsManager = DefaultContextsManager.getInstance();
Identifier contextIdentifier = contextsManager.registerContext("myCounter", new Counter(0));

FunctorSubmitter functorSubmitter = DefaultFunctorSubmitter.getInstance();
functorSubmitter.submitCommand(contextIdentifier, new LoggingCommand("Commenced", 0));

for (int i = 0; i < 50; i++) {
Future<Long> future = functorSubmitter.submitFunctor(contextIdentifier, new NextValueFunctor());
System.out.println(future.get());
}

functorSubmitter.submitCommand(contextIdentifier, new LoggingCommand("Completed", 0));

Thread.sleep(2000);

Counter counter = (Counter)contextsManager.getContext(contextIdentifier);
System.out.println(counter);
}
}
{code}

h3. Frequently Asked Questions

(*b) *What is the relationship between the Functor Pattern, Command Pattern, Entry Processors and the Invocation Service for performing work in a cluster?*

The following table outlines the main differences.

|| || Functor Pattern || Command Pattern || EntryProcessors || InvocationService ||
| Processing Target | A Context | A Context | A Cache Entry | A Cluster Member |
| Submission Behavior | Non-Blocking | Non-Blocking | Blocking | Blocking and Non-Blocking |
| Execution Order | Order of Submission | Order of Submission | Order of Submission (unless using PriorityTasks) | Order of Submission |
| Supports Return Values?\\(and re-throwing Exceptions) | Yes | No | Yes | Yes |
| Guaranteed to Execute?\\(if Submitter terminates after submission) | Yes | Yes | Yes (submitter blocks) | Yes (for blocking), No (for non-blocking) |
| Guaranteed to Execute?\\(if Target JVM terminates during execution) | Yes | Yes | Yes (submitter automatically retries) | No (retry up to developer) |
| Submitted requests recoverable from disk? | Yes (when using Cache Store) | Yes (when using Cache Store) | No | No |
| Request may be cancelled? | Yes | Yes | No | Yes (for non-blocking) |

(*b) *Can {{Functors}} and {{Commands}} be submitted to the same {{Context}}?*
Yes. {{Functors}} and {{Commands}} may be submitted for execution against the same {{Context}}. They will be executed in the order of submission from the {{Submitter}}. Further, {{FunctorSubmitters}} may be used instead of {{CommandSubmitters}} (as the {{FunctorSubmitter}} interface is a sub-interface of the {{CommandSubmitter}} interface)

(*b) *How do I monitor the execution of {{Functors}} ?*

As the Functor Pattern uses the [Command Pattern] for the internal implementation (and that is JMX enabled), all you need to do is simply enable JMX.

h3. References and Additional Information

* Wikipedia - [Function Objects and the Functor Pattern (Wikipedia)|http://en.wikipedia.org/wiki/Function_object]