Modern, JVM-based framework for building modular, easily testable microservice and serverless applications with compile-time DI and fast startup.
—
Micronaut provides comprehensive resilience patterns including retry logic, circuit breakers, and bulkhead isolation to handle failures and improve application reliability.
Automatically retry failed operations with configurable strategies.
/**
* Retry configuration and usage
*/
@Singleton
public class ExternalService {
@Retryable(attempts = "3", delay = "1s")
public String callExternal() {
// Method will be retried up to 3 times with 1 second delay
return restClient.getData();
}
@Retryable(attempts = "5", delay = "2s", multiplier = "2")
public String callWithBackoff() {
// Exponential backoff: 2s, 4s, 8s, 16s
return restClient.getData();
}
@Retryable(
attempts = "3",
includes = {ConnectException.class, SocketTimeoutException.class},
excludes = {IllegalArgumentException.class}
)
public String callWithSpecificExceptions() {
// Only retry on specific exceptions
return restClient.getData();
}
@Retryable(attempts = "3", delay = "1s")
Single<String> reactiveRetry() {
// Reactive retry support
return Single.fromCallable(() -> restClient.getData());
}
}Protect against cascading failures with circuit breaker patterns.
/**
* Circuit breaker configuration
*/
@Singleton
public class ReliableService {
@CircuitBreaker
public String reliableCall() {
// Default circuit breaker configuration
return externalService.call();
}
@CircuitBreaker(
attempts = "5",
openTimeout = "30s",
resetTimeout = "60s"
)
public String configuredCircuitBreaker() {
// Custom circuit breaker settings
return externalService.call();
}
@CircuitBreaker(includes = {ConnectException.class})
@Fallback
public String circuitBreakerWithFallback() {
// Circuit breaker with fallback method
return externalService.call();
}
// Fallback method for circuitBreakerWithFallback
public String circuitBreakerWithFallback(CircuitOpenException ex) {
return "Service temporarily unavailable";
}
}Isolate different parts of the application to prevent resource exhaustion.
/**
* Bulkhead isolation
*/
@Singleton
public class IsolatedService {
@Bulkhead(value = "critical-operations", maxConcurrency = 10)
public String criticalOperation() {
// Limited to 10 concurrent executions
return performCriticalWork();
}
@Bulkhead(value = "background-tasks", maxConcurrency = 5, maxWaitDuration = "5s")
public CompletableFuture<String> backgroundTask() {
// Background tasks with wait timeout
return CompletableFuture.supplyAsync(this::performBackgroundWork);
}
}Add timeout protection to prevent operations from hanging indefinitely.
/**
* Timeout configuration
*/
@Singleton
public class TimedService {
@TimedOut("5s")
public String timedOperation() {
// Operation will timeout after 5 seconds
return longRunningOperation();
}
@TimedOut("10s")
@Fallback
public String timedOperationWithFallback() {
// Timeout with fallback
return longRunningOperation();
}
// Fallback method for timeout
public String timedOperationWithFallback(TimeoutException ex) {
return "Operation timed out, using cached result";
}
@TimedOut("3s")
Single<String> reactiveTimeout() {
// Reactive timeout support
return Single.fromCallable(this::longRunningOperation);
}
}Combine multiple resilience patterns for comprehensive protection.
/**
* Combined resilience patterns
*/
@Singleton
public class ResilientService {
@Retryable(attempts = "3", delay = "1s")
@CircuitBreaker(attempts = "5", openTimeout = "30s")
@TimedOut("10s")
@Fallback
public String resilientOperation() {
// Combined retry, circuit breaker, timeout, and fallback
return externalService.call();
}
// Fallback for resilientOperation
public String resilientOperation(Exception ex) {
if (ex instanceof CircuitOpenException) {
return "Circuit breaker is open";
} else if (ex instanceof TimeoutException) {
return "Operation timed out";
} else {
return "Operation failed after retries";
}
}
@Bulkhead("api-calls")
@Retryable(attempts = "2")
@CircuitBreaker
Publisher<String> resilientReactiveOperation() {
// Reactive resilience patterns
return Flowable.fromCallable(() -> externalService.call());
}
}Configure resilience patterns through application properties.
/**
* Resilience configuration properties
*/
@ConfigurationProperties("resilience")
public class ResilienceConfiguration {
@ConfigurationProperties("retry")
public static class RetryConfiguration {
private int attempts = 3;
private Duration delay = Duration.ofSeconds(1);
private double multiplier = 1.0;
// getters and setters
}
@ConfigurationProperties("circuit-breaker")
public static class CircuitBreakerConfiguration {
private int attempts = 5;
private Duration openTimeout = Duration.ofSeconds(30);
private Duration resetTimeout = Duration.ofMinutes(1);
// getters and setters
}
@ConfigurationProperties("bulkhead")
public static class BulkheadConfiguration {
private int maxConcurrency = 10;
private Duration maxWaitDuration = Duration.ofSeconds(5);
// getters and setters
}
}// Resilience annotations
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Retryable {
String attempts() default "3";
String delay() default "1s";
String multiplier() default "1.0";
Class<? extends Throwable>[] includes() default {};
Class<? extends Throwable>[] excludes() default {};
}
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface CircuitBreaker {
String attempts() default "20";
String openTimeout() default "20s";
String resetTimeout() default "20s";
Class<? extends Throwable>[] includes() default {};
Class<? extends Throwable>[] excludes() default {};
double failureThreshold() default 0.5;
}
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Bulkhead {
String value() default "";
int maxConcurrency() default 10;
String maxWaitDuration() default "0s";
}
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface TimedOut {
String value();
}
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Fallback {
}
// Exception types
public class CircuitOpenException extends RuntimeException {
public CircuitOpenException(String message);
public CircuitOpenException(String message, Throwable cause);
}
public class BulkheadRejectionException extends RuntimeException {
public BulkheadRejectionException(String message);
public BulkheadRejectionException(String message, Throwable cause);
}
// Circuit breaker states
public enum CircuitState {
CLOSED, OPEN, HALF_OPEN
}
// Retry context
public interface RetryContext {
int getCurrentAttempt();
int getMaxAttempts();
Duration getDelay();
Throwable getLastException();
}Install with Tessl CLI
npx tessl i tessl/maven-micronaut