---
title:  Function Execution
---

<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements.  See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License.  You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

A client can invoke a server-resident function, with parameters, and can collect and operate on the returned results.

## <a id="server_side_requirements"></a>Server-side Requirements

To be callable from your client, a function must be 

- resident on the server, and
- registered as available for client access.

See [Executing a Function in <%=vars.product_name_long%>](serverman/developing/function_exec/function_execution.html) 
in the <%=vars.product_name%> User Guide for details on how to write and register server-resident functions.

## <a id="client_side_requirements"></a>Client-side Requirements

The client must connect to the server through a connection pool in order to invoke a server-side function.

## <a id="how_functions_execute"></a>How Functions Execute

1.  The calling client application runs the `execute` method on the `Execution` object. The function must already be registered on the servers.
2.  The function is invoked on the servers where it needs to run. The servers are determined by the `FunctionService on*` 
method calls, region configuration, and any filters.
3.  If the function has results, the result is returned in a `ResultCollector` object.
4.  The client collects results using the `ResultCollector.getResult()` method.

In every client where you want to execute the function and process the results:

- Use one of the `FunctionService on*` methods to create an `Execution` object. The `on*` methods,
`onRegion`, `onServer` and `onServers`, define the highest level where the function is run.
- If you use `onRegion` you can further narrow your run scope by setting key filters.
- A function run using `onRegion` is a *data dependent* function – others are *data-independent* functions.
- You can run a data dependent function against partitioned and colocated partitioned regions. From the client, provide the appropriate key
 sets to the function call.

-  The `Execution` object allows you to customize the invocation by:
    -   Providing a set of data keys to `withFilter` to narrow the execution scope. This works only for `onRegion` Execution objects (data-dependent functions).
    -   Providing function arguments to `withArgs`.
    -   Defining a custom `ResultCollector` for `withCollector`.

-  Call the `Execution.execute()` method to run the function.

## <a id="processing_function_results"></a>Processing Function Results

To get the results from the function in the client app, use the result collector returned from the function execution.
The `getResult` methods of the default result collector block until all results are received, then return the full result set.

The client can use the default result collector. If the client needs special results handling, code a custom `ResultsCollector` implementation to replace the default.
Use the `Execution::withCollector` method to specify the custom collector.
To handle the results in a custom manner:

1.  Write a class that implements the `ResultCollector` interface to handle the results in a custom manner. The methods are of two types: one handles data and information from <%=vars.product_name%> and populates the results set, while the other returns the compiled results to the calling application:
    -  `addResult` is called when results arrive from the `Function` methods. Use `addResult` to add a single result to the ResultCollector.
    -  `endResults` is called to signal the end of all results from the function execution.
    -  `getResult` is available to your executing application (the one that calls `Execution.execute`) to retrieve the results. This may block until all results are available.
    -  `clearResults` is called to clear partial results from the results collector. This is used only for highly available `onRegion` functions where the calling application waits for the results. If the call fails, before <%=vars.product_name%> retries the execution, it calls `clearResults` to ready the instance for a clean set of results.
2.  Use the `Execution` object in your executing member to call `withCollector`, passing your custom collector.

# <a id="examples"></a>Examples

The native client release contains examples of function execution written for .NET and
C++. The examples are located in `../examples/dotnet/functionexecution` and
`../examples/cpp/function-execution`, respectively.

The two examples share some common elements:

- They begin with a server-side script that runs `gfsh` commands to create a region, simply called "partition_region".
- The function is preloaded with a JAR file containing the server-side Java function code. 
- The function, called "ExampleMultiGetFunction", is defined in the
`examples/utilities` directory of your distribution. As its input parameter, the function takes an array of keys,
then performs a `get` on each key and returns an array containing the results.
- The function does not load values into the data store. That is a separate operation, performed in these examples by
the client, and does not involve the server-side function.

As prerequisites, the client code must be aware of the connection to the server, the name of the function, and the expected type/format 
of the input parameter and return value.

The client:

- creates an execution object
- provides the execution object with a populated input parameter array
- invokes the object's execute method to invoke the server-side function

If the client expects results, it must create a result object.
The .NET example uses a built-in result collector (`IResultCollector.getResults()`) to retrieve the function results.

The C++ example creates a result variable to hold the results from the collector.

## <a id="dotnet_example"></a>.NET Example
This section contains code snippets showing highlights of the .NET function execution example. They are not intended for cut-and-paste execution.
For the complete source, see the example source directory.

The .NET example creates a cache, then uses it to create a connection pool.

```csharp
   var cacheFactory = new CacheFactory()
       .Set("log-level", "none");
   var cache = cacheFactory.Create();

   var poolFactory = cache.GetPoolFactory()
       .AddLocator("localhost", 10334);
   var pool = poolFactory.Create("pool");
```

The example uses the connection pool to create a region, with the same characteristics and name as the server-side region (`partition_region`).

```csharp
   var regionFactory = cache.CreateRegionFactory(RegionShortcut.PROXY)
       .SetPoolName("pool");
   var region = regionFactory.Create<object, object>("partition_region");
```

The sample client populates the server's datastore with values, using the API and some sample key-value pairs.

```csharp
   string rtimmonsKey = "rtimmons";
   string rtimmonsValue = "Robert Timmons";
   string scharlesKey = "scharles";
   string scharlesValue = "Sylvia Charles";
   region.Put(rtimmonsKey, rtimmonsValue, null);
   region.Put(scharlesKey, scharlesValue, null);
```

To confirm that the data has been stored, the client uses the API to retrieve the values and write them to the console.
This is done without reference to the server-side example function.

```csharp
   var user1 = region.Get(rtimmonsKey, null);
   var user2 = region.Get(scharlesKey, null);

   Console.WriteLine(rtimmonsKey + " = " + user1);
   Console.WriteLine(scharlesKey + " = " + user2);
```

Next, the client retrieves those same values using the server-side example function.
The client code creates the input parameter, an array of keys whose values are to be retrieved.

```csharp
   ArrayList keyArgs = new ArrayList();
   keyArgs.Add(rtimmonsKey);
   keyArgs.Add(scharlesKey);
```

The client creates an execution object using `Client.FunctionService.OnRegion` and specifying the region.

```csharp
   var exc = Client.FunctionService<object>.OnRegion<object, object>(region);
```

The client then calls the server side function with its input arguments and stores the results in a Client.IResultCollector.

```csharp
   Client.IResultCollector<object> rc = exc.WithArgs<object>(keyArgs).Execute("ExampleMultiGetFunction");
```

It then loops through the results and prints the retrieved values.

```csharp
   ICollection<object> res = rc.GetResult();

   Console.WriteLine("Function Execution Results:");
   Console.WriteLine("   Count = {0}", res.Count);

   foreach (List<object> item in res)
   {
     foreach (object item2 in item)
     {
       Console.WriteLine("   value = {0}", item2.ToString());
     }
   }
```

## <a id="cpp_example"></a>C++ Example
This section contains code snippets showing highlights of the C++ function execution example. They are not intended for cut-and-paste execution.
For the complete source, see the example source directory.

The C++ example creates a cache.

```cpp
Cache setupCache() {
  return CacheFactory()
      .set("log-level", "none")
      .create();
}
```

The example client uses the cache to create a connection pool, 

```cpp
void createPool(const Cache& cache) {
  auto pool = cache.getPoolManager()
      .createFactory()
      .addServer("localhost", EXAMPLE_SERVER_PORT)
      .create("pool");
}
```

Then, using that pool, the client creates a region with the same characteristics and name as the server-side region (`partition_region`).

```cpp
std::shared_ptr<Region> createRegion(Cache& cache) {
  auto regionFactory = cache.createRegionFactory(RegionShortcut::PROXY);
  auto region = regionFactory.setPoolName("pool").create("partition_region");

  return region;
}
```

The sample client populates the server's datastore with values, using the API and some sample key-value pairs.

```cpp
void populateRegion(const std::shared_ptr<Region>& region) {
  for (int i = 0; i < keys.size(); i++) {
    region->put(keys[i], values[i]);
  }
}
```

As confirmation that the data has been stored, the sample client uses the API to retrieve the values and write them to the console.
This is done without reference to the server-side example function.

```cpp
std::shared_ptr<CacheableVector> populateArguments() {
  auto arguments = CacheableVector::create();
  for (int i = 0; i < keys.size(); i++) {
    arguments->push_back(CacheableKey::create(keys[i]));
  }
  return arguments;
}
```

Next, the client retrieves those same values using the server-side example function.
The client code creates the input parameter, an array of keys whose values are to be retrieved.

```cpp
std::vector<std::string> executeFunctionOnServer(const std::shared_ptr<Region> region,
    const std::shared_ptr<CacheableVector> arguments) {
  std::vector<std::string> resultList;
```

The client creates an execution object using `Client.FunctionService.OnRegion` and specifying the region.

```cpp
  auto functionService = FunctionService::onServer(region->getRegionService());
```

The client then calls the server side function with its input arguments and stores the results in a vector.

```cpp
  if(auto executeFunctionResult = functionService.withArgs(arguments).execute(getFuncIName)->getResult()) {
    for (auto &arrayList: *executeFunctionResult) {
      for (auto &cachedString: *std::dynamic_pointer_cast<CacheableArrayList>(arrayList)) {
        resultList.push_back(std::dynamic_pointer_cast<CacheableString>(cachedString)->value());
      }
    }
  } else {
    std::cout << "get executeFunctionResult is NULL\n";
  }

  return resultList;
}
```

It then loops through the results vector and prints the retrieved values.

```cpp
void printResults(const std::vector<std::string>& resultList) {
  std::cout << "Result count = " << resultList.size() << std::endl << std::endl;
  int i = 0;
  for (auto &cachedString: resultList) {
    std::cout << "\tResult[" << i << "]=" << cachedString << std::endl;
    ++i;
  }
```

