[[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 <>, 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.