---
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 paramaters, 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 object must already be registered on the servers.
2.  The function is invoked on all servers where it needs to run. The locations 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 result collector `getResult`.

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. The function run
using `onRegion` is a data dependent function – the others are data-independent functions.

You can run a data dependent function against custom partitioned and colocated partitioned regions. From the client, provide the appropriate key
 sets to the function call.

-  Use the `Execution` object as needed for additional function configuration. You can:
    -   Provide a set of data keys to `withFilter` to narrow the execution scope. This works only for `onRegion` Execution objects.
    -   Provide function arguments to `withArgs`.
    -   Define a custom `ResultCollector` to `withCollector`.

-  Call the `Execution` object execute method to run the function.

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

The client may 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 define the custom collector.

For example, to program your client to get the results from a function, use the result collector returned from the function execution, like this:

```cpp
ResultCollectorPtr rc = FunctionService::onRegion(region)
                    ->withArgs(args)
                    ->withFilter(keySet)
                    ->withCollector(new MyCustomResultCollector())
                    .execute(Function);
CacheableVectorPtr functionResult = rc.getResult();
```

The `getResult` methods of the default result collector block until all results are received, then return the full result set.

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, as shown in the example above.

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

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

Both examples begin with a server-side script that runs `gfsh` commands to create
a region, simply called "partition_region", which 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
- populates the execution object with input parameters
- invokes the object's execute method to invoke the server-side function.

If the client expects results, it must create a result
object. Optionally, the client can use a provided result collector which offers some predefined
methods for iterating over and processing return values.

## <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 Client.IResultCollector.

```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 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;
  }
```

