Spring Cloud Function - Quick Reference

SkillCloud & infra

Spring Cloud Function for serverless and FaaS deployments. Covers function beans, AWS Lambda, Azure Functions, and GCP adapters.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Spring Cloud Function - Quick Reference skill

What this skill tells your AI

The instructions your AI receives, as published by claude-dev-suite/claude-dev-suite in skills/backend-frameworks/spring-cloud-function/SKILL.md and read by ahel’s review.

Deep Knowledge: Use mcp__documentation__fetch_docs with technology: spring-cloud-function for comprehensive documentation.

Dependencies

<!-- Core -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-function-web</artifactId>
</dependency>

<!-- AWS Lambda adapter -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-function-adapter-aws</artifactId>
</dependency>

<!-- Azure Functions adapter -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-function-adapter-azure</artifactId>
</dependency>

<!-- GCP Cloud Functions adapter -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-function-adapter-gcp</artifactId>
</dependency>

Function Types

┌─────────────────────────────────────────────────────────────┐
│                   Function Types                            │
│                                                             │
│  Function<I, O>     Input → Processing → Output            │
│  Consumer<I>        Input → Processing (no output)         │
│  Supplier<O>        (no input) → Generate Output           │
│                                                             │
│  ┌───────┐    ┌──────────┐    ┌────────┐                   │
│  │ Input │───▶│ Function │───▶│ Output │                   │
│  └───────┘    └──────────┘    └────────┘                   │
└─────────────────────────────────────────────────────────────┘

Basic Functions

Function (Input → Output)

@Configuration
public class FunctionConfig {

    @Bean
    public Function<String, String> uppercase() {
        return value -> value.toUpperCase();
    }

    @Bean
    public Function<Person, Greeting> greet() {
        return person -> new Greeting("Hello, " + person.getName() + "!");
    }

    @Bean
    public Function<Flux<String>, Flux<String>> reactiveUppercase() {
        return flux -> flux.map(String::toUpperCase);
    }
}

public record Person(String name, int age) {}
public record Greeting(String message) {}

Consumer (Input → void)

@Bean
public Consumer<Order> processOrder() {
    return order -> {
        log.info("Processing order: {}", order.getId());
        orderService.process(order);
    };
}

@Bean
public Consumer<Flux<Event>> eventProcessor() {
    return events -> events
        .doOnNext(event -> log.info("Received event: {}", event))
        .subscribe(eventService::handle);
}

Supplier (void → Output)

@Bean
public Supplier<String> hello() {
    return () -> "Hello, World!";
}

@Bean
public Supplier<Flux<Long>> counter() {
    return () -> Flux.interval(Duration.ofSeconds(1));
}

@Bean
public Supplier<List<Product>> getProducts() {
    return () -> productRepository.findAll();
}

Configuration

application.yml

spring:
  cloud:
    function:
      # Default function to invoke
      definition: uppercase

      # For multiple functions
      # definition: validate|process|notify

      # Routing based on header
      routing-expression: "headers['function-name']"

# Function-specific config
uppercase:
  prefix: "RESULT: "

Function Composition

// Compose functions
@Bean
public Function<String, String> validate() {
    return input -> {
        if (input == null || input.isEmpty()) {
            throw new IllegalArgumentException("Input cannot be empty");
        }
        return input;
    };
}

@Bean
public Function<String, String> sanitize() {
    return input -> input.trim().toLowerCase();
}

@Bean
public Function<String, String> process() {
    return input -> "Processed: " + input;
}

// Configuration to compose: validate|sanitize|process
// spring.cloud.function.definition=validate|sanitize|process

Programmatic Composition

@Bean
public Function<String, String> composedFunction(
        Function<String, String> validate,
        Function<String, String> sanitize,
        Function<String, String> process) {

    return validate.andThen(sanitize).andThen(process);
}

HTTP Endpoints

// Automatic HTTP endpoints when using spring-cloud-starter-function-web
// POST /uppercase   → invokes uppercase function
// POST /greet       → invokes greet function
// GET  /hello       → invokes hello supplier

// Example requests:
// curl -X POST localhost:8080/uppercase -d "hello" -H "Content-Type: text/plain"
// curl -X POST localhost:8080/greet -d '{"name":"John"}' -H "Content-Type: application/json"
// curl localhost:8080/hello

AWS Lambda

Handler Configuration

# AWS Lambda handler
spring:
  cloud:
    function:
      definition: processEvent

Lambda Handler Class

public class LambdaHandler extends FunctionInvoker<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
}

@Bean
public Function<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> processEvent() {
    return request -> {
        String body = request.getBody();
        // Process request
        return APIGatewayProxyResponseEvent.builder()
            .statusCode(200)
            .body("Processed: " + body)
            .build();
    };
}

SAM Template

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31

Resources:
  MyFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: org.springframework.cloud.function.adapter.aws.FunctionInvoker::handleRequest
      Runtime: java17
      CodeUri: target/my-function.jar
      MemorySize: 512
      Timeout: 30
      Environment:
        Variables:
          SPRING_CLOUD_FUNCTION_DEFINITION: processEvent
      Events:
        Api:
          Type: Api
          Properties:
            Path: /process
            Method: POST

Azure Functions

Host Configuration

public class AzureHandler extends FunctionInvoker<HttpRequestMessage<String>, HttpResponseMessage> {
}

@FunctionName("process")
public HttpResponseMessage run(
        @HttpTrigger(
            name = "req",
            methods = {HttpMethod.POST},
            authLevel = AuthorizationLevel.ANONYMOUS
        ) HttpRequestMessage<String> request,
        ExecutionContext context) {

    return handleRequest(request, context);
}

GCP Cloud Functions

public class GcpHandler extends FunctionInvoker<String, String> {
}

// Deployment
// gcloud functions deploy myFunction \
//   --entry-point org.springframework.cloud.function.adapter.gcp.FunctionInvoker \
//   --runtime java17 \
//   --trigger-http \
//   --memory 512MB

Message-Driven Functions

With Spring Cloud Stream

@Bean
public Function<Flux<Order>, Flux<OrderResult>> processOrders() {
    return orders -> orders
        .map(order -> {
            // Process order
            return new OrderResult(order.getId(), "PROCESSED");
        });
}
spring:
  cloud:
    stream:
      bindings:
        processOrders-in-0:
          destination: orders
        processOrders-out-0:
          destination: order-results
    function:
      definition: processOrders

Function Catalog

@Autowired
private FunctionCatalog functionCatalog;

public void invokeDynamically(String functionName, Object input) {
    Function<Object, Object> function = functionCatalog.lookup(functionName);
    if (function != null) {
        Object result = function.apply(input);
        log.info("Result: {}", result);
    }
}

Error Handling

@Bean
public Function<Order, OrderResult> processOrder() {
    return order -> {
        try {
            validateOrder(order);
            return new OrderResult(order.getId(), "SUCCESS");
        } catch (ValidationException e) {
            return new OrderResult(order.getId(), "VALIDATION_ERROR: " + e.getMessage());
        } catch (Exception e) {
            log.error("Error processing order", e);
            throw new RuntimeException("Processing failed", e);
        }
    };
}

// Global error handler
@Bean
public Consumer<ErrorMessage> errorHandler() {
    return error -> {
        log.error("Function error: {}", error.getPayload().getMessage());
        alertService.sendAlert(error);
    };
}

Testing

@SpringBootTest
class FunctionTests {

    @Autowired
    private Function<String, String> uppercase;

    @Autowired
    private FunctionCatalog catalog;

    @Test
    void shouldUppercase() {
        String result = uppercase.apply("hello");
        assertThat(result).isEqualTo("HELLO");
    }

    @Test
    void shouldLookupFunction() {
        Function<String, String> fn = catalog.lookup("uppercase");
        assertThat(fn.apply("test")).isEqualTo("TEST");
    }

    @Test
    void shouldComposeFunction() {
        Function<String, String> composed = catalog.lookup("validate|sanitize|process");
        String result = composed.apply("  HELLO  ");
        assertThat(result).isEqualTo("Processed: hello");
    }
}

// Integration test with WebTestClient
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class FunctionHttpTests {

    @Autowired
    private WebTestClient webTestClient;

    @Test
    void shouldInvokeViaHttp() {
        webTestClient.post()
            .uri("/uppercase")
            .contentType(MediaType.TEXT_PLAIN)
            .bodyValue("hello")
            .exchange()
            .expectStatus().isOk()
            .expectBody(String.class)
            .isEqualTo("HELLO");
    }
}

Native Image (GraalVM)

<dependency>
    <groupId>org.springframework.experimental</groupId>
    <artifactId>spring-native</artifactId>
</dependency>

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <image>
            <builder>paketobuildpacks/builder:tiny</builder>
            <env>
                <BP_NATIVE_IMAGE>true</BP_NATIVE_IMAGE>
            </env>
        </image>
    </configuration>
</plugin>

Best Practices

DoDon't
Keep functions focused/smallCreate monolithic functions
Use reactive types for streamingBlock on large datasets
Handle errors gracefullyLet exceptions propagate unhandled
Test functions in isolationSkip unit tests
Configure appropriate timeoutsIgnore cold start impact

Production Checklist

  • Function definition configured
  • Error handling implemented
  • Timeouts appropriate for platform
  • Memory limits set
  • Cold start optimized
  • Logging configured
  • Monitoring/tracing enabled
  • Secrets management (not env vars)
  • Native image if needed
  • CI/CD pipeline for deployment

When NOT to Use This Skill

  • REST APIs - Use standard Spring MVC controllers
  • Complex workflows - Use AWS Step Functions, Temporal
  • Long-running processes - Not suitable for functions
  • Traditional deployment - May not provide benefits

Anti-Patterns

Anti-PatternProblemSolution
Large function payloadCold start, timeoutKeep functions small
State in functionFunctions should be statelessUse external storage
Hardcoded cloud configNot portableUse Spring Cloud abstractions
No timeout handlingLambda timeout = errorHandle gracefully
Secrets in env varsSecurity riskUse secrets manager

Quick Troubleshooting

ProblemDiagnosticFix
Function not foundCheck function nameVerify spring.cloud.function.definition
Cold start slowCheck dependenciesReduce classpath, use native
TimeoutCheck execution timeOptimize or increase timeout
Memory errorCheck Lambda configIncrease memory allocation
Routing not workingCheck function catalogVerify function names

Reference Documentation

Signals

GitHub stars
33
Forks
6
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
spring-cloud-function
Source
github.com/claude-dev-suite/claude-dev-suite