[[geode-functions]]
== Function Implementations & Executions
:geode-name: {apache-geode-name}


This chapter is about using {geode-name} in a Spring context for distributed computing use cases.

=== Background

Distributed computing, particularly in conjunction with data access and mutation operations, is a very effective
and efficient use of clustered computing resources. This is similar to {wikipedia-docs}/MapReduce[MapReduce].

A naively conceived query returning potentially hundreds of thousands (or even millions) of rows of data in a result set
to the application that queried and requested the data can be very costly, especially under load. Therefore, it is
typically more efficient to move the processing and computations on the predicated data set to where the data resides,
perform the required computations, summarize the results, and then send the reduced data set back to the client.

Additionally, when the computations are handled in parallel, across the cluster of computing resources, the operation
can be performed much more quickly. This typically involves intelligently organizing the data using various partitioning
(a.k.a. sharding) strategies to uniformly balance the data set across the cluster.

{geode-name} addresses this very important application concern in its
{apache-geode-docs}/developing/function_exec/chapter_overview.html[Function execution] framework.

Spring Data for {geode-name} {spring-data-geode-docs-html}/#function-annotations[builds] on this Function execution
framework by letting developers {spring-data-geode-docs-html}/#function-implementation[implement]
and {spring-data-geode-docs-html}/#function-execution[execute] {geode-name} functions with a simple POJO-based
annotation configuration model.

TIP: See {spring-data-geode-docs-html}/#_implementation_vs_execution[the section about implementation versus execution]
for the difference between Function implementation and execution.

Taking this a step further, Spring Boot for {geode-name} auto-configures and enables both Function implementation
and execution out-of-the-box. Therefore, you can immediately begin writing Functions and invoking them without having to
worry about all the necessary plumbing to begin with. You can rest assured that it works as expected.

=== Applying Functions

Earlier, when we talked about <<geode-caching-provider,caching>>, we described a `FinancialLoanApplicationService` class
that could process eligibility when someone (represented by a `Person` object) applied for a financial loan.

This can be a very resource intensive and expensive operation, since it might involve collecting credit and employment
history, gathering information on outstanding loans, and so on. We applied caching in order to not have to recompute
or redetermine eligibility every time a loan office may want to review the decision with the customer.

But, what about the process of computing eligibility in the first place?

Currently, the application's `FinancialLoanApplicationService` class seems to be designed to fetch the data and perform
the eligibility determination in place. However, it might be far better to distribute the processing and even determine
eligibility for a larger group of people all at once, especially when multiple, related people are involved in a single
decision, as is typically the case.

We can implement an `EligibilityDeterminationFunction` class by using SDG:

.Function implementation
====
[source,java]
----
@Component
class EligibilityDeterminationFunction {

    @GemfireFunction(HA = true, hasResult = true, optimizeForWrite=true)
    public EligibilityDecision determineEligibility(FunctionContext functionContext, Person person, Timespan timespan) {
        // ...
    }
}
----
====

By using the SDG {spring-data-geode-javadoc}/org/springframework/data/gemfire/function/annotation/GemfireFunction.html[`@GemfireFunction`]
annotation, we can implement our Function as a POJO method. SDG appropriately handles registering this POJO method
as a proper Function with {geode-name}.

If we now want to call this function from our Spring Boot `ClientCache` application, we can define
a function execution interface with a method name that matches the function name and that targets the execution
on the `EligibilityDecisions` Region:

.Function execution
====
[source,java]
----
@OnRegion("EligibilityDecisions")
interface EligibilityDeterminationExecution {

  EligibilityDecision determineEligibility(Person person, Timespan timespan);

}
----
====

We can then inject an instance of the `EligibilityDeterminationExecution` interface into our
`FinancialLoanApplicationService`, as we would any other object or Spring bean:

.Function use
====
[source,java]
----
@Service
class FinancialLoanApplicationService {

    private final EligibilityDeterminationExecution execution;

    public LoanApplicationService(EligibilityDeterminationExecution execution) {
        this.execution = execution;
    }

    @Cacheable("EligibilityDecisions")
    EligibilityDecision processEligibility(Person person, Timespan timespan) {
        return this.execution.determineEligibility(person, timespan);
    }
}
----
====

As with caching, no additional configuration is required to enable and find your application Function implementations
and executions. You can simply build and run. Spring Boot for {geode-name} handles the rest.

TIP: It is common to "implement" and register your application Functions on the server and "execute" them from
the client.
