CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-micronaut

Modern, JVM-based framework for building modular, easily testable microservice and serverless applications with compile-time DI and fast startup.

Pending
Overview
Eval results
Files

functions.mddocs/

Function as a Service

Micronaut provides comprehensive support for serverless functions with integration for AWS Lambda, Google Cloud Functions, Azure Functions, and local function execution.

Capabilities

Function Beans

Define functions using the standard Java Function interface.

/**
 * Simple function bean
 */
@FunctionBean("hello")
public class HelloFunction implements Function<String, String> {
    
    @Override
    public String apply(String input) {
        return "Hello " + input;
    }
}

/**
 * Function with dependency injection
 */
@FunctionBean("userProcessor")
public class UserProcessorFunction implements Function<UserRequest, UserResponse> {
    
    private final UserService userService;
    
    public UserProcessorFunction(UserService userService) {
        this.userService = userService;
    }
    
    @Override
    public UserResponse apply(UserRequest request) {
        User user = userService.processUser(request);
        return new UserResponse(user.getId(), user.getName());
    }
}

Reactive Functions

Create functions that return reactive types for asynchronous processing.

/**
 * Reactive function implementations
 */
@FunctionBean("asyncProcessor")
public class AsyncProcessorFunction implements Function<ProcessRequest, Single<ProcessResponse>> {
    
    private final ProcessingService processingService;
    
    public AsyncProcessorFunction(ProcessingService processingService) {
        this.processingService = processingService;
    }
    
    @Override
    public Single<ProcessResponse> apply(ProcessRequest request) {
        return processingService.processAsync(request)
            .map(result -> new ProcessResponse(result.getId(), result.getStatus()));
    }
}

/**
 * Streaming function
 */
@FunctionBean("dataStream")
public class DataStreamFunction implements Function<Publisher<DataInput>, Publisher<DataOutput>> {
    
    @Override
    public Publisher<DataOutput> apply(Publisher<DataInput> input) {
        return Flowable.fromPublisher(input)
            .map(this::transform)
            .filter(Objects::nonNull);
    }
    
    private DataOutput transform(DataInput input) {
        // Transform input to output
        return new DataOutput(input.getValue().toUpperCase());
    }
}

HTTP Functions

Create functions that handle HTTP requests and responses.

/**
 * HTTP function handling
 */
@FunctionBean("httpHandler")
public class HttpHandlerFunction implements Function<HttpRequest<?>, HttpResponse<?>> {
    
    @Override
    public HttpResponse<?> apply(HttpRequest<?> request) {
        String method = request.getMethod().toString();
        String path = request.getPath();
        
        Map<String, Object> response = Map.of(
            "method", method,
            "path", path,
            "timestamp", Instant.now().toString()
        );
        
        return HttpResponse.ok(response);
    }
}

/**
 * Typed HTTP function
 */
@FunctionBean("apiEndpoint")
public class ApiEndpointFunction implements Function<ApiRequest, Single<ApiResponse>> {
    
    private final ApiService apiService;
    
    public ApiEndpointFunction(ApiService apiService) {
        this.apiService = apiService;
    }
    
    @Override
    public Single<ApiResponse> apply(ApiRequest request) {
        return apiService.handleRequest(request)
            .map(result -> new ApiResponse(result, "success"));
    }
}

AWS Lambda Integration

Deploy functions as AWS Lambda functions with event handling.

/**
 * AWS Lambda event handling
 */
@FunctionBean("s3Handler")
public class S3EventHandler implements Function<S3Event, String> {
    
    private final S3Service s3Service;
    
    public S3EventHandler(S3Service s3Service) {
        this.s3Service = s3Service;
    }
    
    @Override
    public String apply(S3Event event) {
        for (S3EventNotification.S3EventNotificationRecord record : event.getRecords()) {
            String bucketName = record.getS3().getBucket().getName();
            String objectKey = record.getS3().getObject().getKey();
            
            s3Service.processObject(bucketName, objectKey);
        }
        
        return "Processed " + event.getRecords().size() + " records";
    }
}

/**
 * API Gateway Lambda function
 */
@FunctionBean("apiGateway")
public class ApiGatewayFunction 
    implements Function<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
    
    @Override
    public APIGatewayProxyResponseEvent apply(APIGatewayProxyRequestEvent request) {
        String httpMethod = request.getHttpMethod();
        String path = request.getPath();
        String body = request.getBody();
        
        // Process the request
        Map<String, Object> responseBody = Map.of(
            "message", "Request processed",
            "method", httpMethod,
            "path", path
        );
        
        return APIGatewayProxyResponseEvent.builder()
            .withStatusCode(200)
            .withHeaders(Map.of("Content-Type", "application/json"))
            .withBody(toJson(responseBody))
            .build();
    }
}

Function Configuration

Configure function deployment and runtime settings.

/**
 * Function configuration
 */
@ConfigurationProperties("function")
public class FunctionConfiguration {
    
    private String runtime = "java11";
    private int timeout = 30;
    private int memorySize = 512;
    private Map<String, String> environment = new HashMap<>();
    
    // getters and setters
}

/**
 * AWS-specific configuration
 */
@ConfigurationProperties("aws.lambda")
public class LambdaConfiguration {
    private String role;
    private String functionName;
    private String handler;
    private List<String> layers = new ArrayList<>();
    
    // getters and setters
}

Local Function Testing

Test functions locally during development.

/**
 * Local function testing
 */
@Singleton
public class FunctionTestRunner {
    
    private final ApplicationContext applicationContext;
    
    public FunctionTestRunner(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }
    
    public <T, R> R executeFunction(String functionName, T input, Class<R> returnType) {
        Function<T, R> function = applicationContext.getBean(Function.class, 
            Qualifiers.byName(functionName));
        return function.apply(input);
    }
    
    public <T> void executeVoidFunction(String functionName, T input) {
        Consumer<T> function = applicationContext.getBean(Consumer.class,
            Qualifiers.byName(functionName));
        function.accept(input);
    }
}

Cold Start Optimization

Optimize functions for minimal cold start times.

/**
 * Cold start optimization
 */
@Introspected
@Serdeable
public class OptimizedFunction implements Function<OptimizedRequest, OptimizedResponse> {
    
    // Use @Introspected for compile-time reflection
    // Use @Serdeable for compile-time serialization
    
    @Override
    public OptimizedResponse apply(OptimizedRequest request) {
        // Function logic optimized for fast startup
        return new OptimizedResponse(process(request.getData()));
    }
    
    private String process(String data) {
        // Minimal processing to reduce cold start impact
        return data.toUpperCase();
    }
}

Types

// Function annotations
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface FunctionBean {
    String value();
}

// Core function interfaces
public interface Function<T, R> {
    R apply(T t);
}

public interface Consumer<T> {
    void accept(T t);
}

public interface Supplier<T> {
    T get();
}

public interface BiFunction<T, U, R> {
    R apply(T t, U u);
}

// HTTP function types
public interface HttpRequest<B> extends HttpMessage<B> {
    HttpMethod getMethod();
    URI getUri();
    String getPath();
    HttpParameters getParameters();
    HttpHeaders getHeaders();
    Optional<B> getBody();
}

public interface HttpResponse<B> extends HttpMessage<B> {
    HttpStatus getStatus();
    int code();
    String reason();
    HttpHeaders getHeaders();
    Optional<B> getBody();
    
    static <T> MutableHttpResponse<T> ok(T body);
    static <T> MutableHttpResponse<T> created(T body);
    static MutableHttpResponse<String> badRequest(String error);
}

// AWS Lambda types (when using AWS integration)
public class S3Event {
    public List<S3EventNotificationRecord> getRecords();
}

public class APIGatewayProxyRequestEvent {
    public String getHttpMethod();
    public String getPath();
    public String getBody();
    public Map<String, String> getHeaders();
    public Map<String, String> getQueryStringParameters();
}

public class APIGatewayProxyResponseEvent {
    public static Builder builder();
    
    public static class Builder {
        public Builder withStatusCode(int statusCode);
        public Builder withHeaders(Map<String, String> headers);
        public Builder withBody(String body);
        public APIGatewayProxyResponseEvent build();
    }
}

// Function context for runtime information
public interface FunctionContext {
    String getFunctionName();
    String getFunctionVersion();
    int getRemainingTimeInMillis();
    int getMaxMemoryInMB();
    String getRequestId();
}

Install with Tessl CLI

npx tessl i tessl/maven-micronaut

docs

aop.md

configuration.md

dependency-injection.md

functions.md

http-client.md

http-server.md

index.md

management.md

messaging.md

reactive.md

retry.md

scheduling.md

websocket.md

tile.json