0
# Fallback Strategies
1
2
Alternative execution paths when primary methods fail, including custom fallback handlers, fallback methods, and exception-based fallback logic.
3
4
## Capabilities
5
6
### Method-based Fallback
7
8
Fallback to alternative methods in the same class with matching signatures.
9
10
```java { .api }
11
@Fallback(
12
fallbackMethod = "alternativeMethod",
13
applyOn = {IOException.class, TimeoutException.class},
14
skipOn = {IllegalArgumentException.class}
15
)
16
public ReturnType methodWithFallback(ParameterType param);
17
18
// Fallback method must have matching signature
19
public ReturnType alternativeMethod(ParameterType param);
20
```
21
22
#### Parameters
23
24
- `fallbackMethod` - Name of fallback method in same class
25
- `applyOn` - Exception types that trigger fallback (default: Throwable.class)
26
- `skipOn` - Exception types that skip fallback (takes precedence)
27
28
#### Usage Example
29
30
```java
31
@ApplicationScoped
32
public class UserService {
33
34
@Inject
35
ExternalUserApi externalApi;
36
37
@Inject
38
UserCache cache;
39
40
// Primary method with cached fallback
41
@Fallback(
42
fallbackMethod = "getUserFromCache",
43
applyOn = {ConnectException.class, TimeoutException.class}
44
)
45
@Timeout(5000)
46
public User getUser(Long userId) throws UserNotFoundException {
47
return externalApi.fetchUser(userId);
48
}
49
50
public User getUserFromCache(Long userId) throws UserNotFoundException {
51
User cached = cache.get(userId);
52
if (cached != null) {
53
return cached;
54
}
55
throw new UserNotFoundException("User not found: " + userId);
56
}
57
58
// Order service with default fallback
59
@Fallback(fallbackMethod = "getDefaultOrderStatus")
60
public OrderStatus getOrderStatus(String orderId) throws ServiceException {
61
return orderServiceClient.getStatus(orderId);
62
}
63
64
public OrderStatus getDefaultOrderStatus(String orderId) {
65
return OrderStatus.PENDING; // Safe default
66
}
67
}
68
```
69
70
### Handler-based Fallback
71
72
Custom fallback handlers for complex fallback logic and cross-cutting concerns.
73
74
```java { .api }
75
@Fallback(
76
value = CustomFallbackHandler.class,
77
applyOn = {IOException.class},
78
skipOn = {SecurityException.class}
79
)
80
public ReturnType methodWithHandler(ParameterType param);
81
82
// Fallback handler implementation
83
class CustomFallbackHandler implements FallbackHandler<ReturnType> {
84
public ReturnType handle(ExecutionContext context);
85
}
86
```
87
88
#### Usage Example
89
90
```java
91
@ApplicationScoped
92
public class PaymentService {
93
94
// Payment with sophisticated fallback handler
95
@Fallback(value = PaymentFallbackHandler.class)
96
@CircuitBreaker(requestVolumeThreshold = 10, failureRatio = 0.4)
97
public PaymentResult processPayment(PaymentRequest request) throws PaymentException {
98
return primaryPaymentGateway.process(request);
99
}
100
}
101
102
// Sophisticated fallback handler
103
public class PaymentFallbackHandler implements FallbackHandler<PaymentResult> {
104
105
@Inject
106
SecondaryPaymentGateway secondaryGateway;
107
108
@Inject
109
PaymentQueue paymentQueue;
110
111
@Inject
112
NotificationService notifications;
113
114
@Override
115
public PaymentResult handle(ExecutionContext context) {
116
PaymentRequest request = (PaymentRequest) context.getParameters()[0];
117
Throwable failure = context.getFailure();
118
119
// Try secondary payment gateway first
120
try {
121
return secondaryGateway.process(request);
122
} catch (Exception e) {
123
// Queue for later processing
124
paymentQueue.enqueue(request);
125
126
// Notify customer
127
notifications.notifyPaymentDelayed(request.getCustomerId());
128
129
return PaymentResult.queued(request.getTransactionId());
130
}
131
}
132
}
133
```
134
135
### Conditional Fallback
136
137
Fallback logic based on specific exception types and conditions.
138
139
```java { .api }
140
@Fallback(
141
fallbackMethod = "specificFallback",
142
applyOn = {ServiceUnavailableException.class, TimeoutException.class},
143
skipOn = {ValidationException.class, SecurityException.class}
144
)
145
public ReturnType conditionalFallbackMethod();
146
```
147
148
#### Usage Example
149
150
```java
151
@ApplicationScoped
152
public class NotificationService {
153
154
@Inject
155
EmailService emailService;
156
157
@Inject
158
SmsService smsService;
159
160
@Inject
161
PushNotificationService pushService;
162
163
// Email with SMS fallback for delivery issues
164
@Fallback(
165
fallbackMethod = "sendViaSms",
166
applyOn = {MailServerException.class, DeliveryException.class},
167
skipOn = {InvalidEmailException.class}
168
)
169
public NotificationResult sendEmail(String recipient, String message) {
170
return emailService.send(recipient, message);
171
}
172
173
public NotificationResult sendViaSms(String recipient, String message) {
174
// Convert email recipient to phone number if possible
175
String phoneNumber = contactService.getPhoneNumber(recipient);
176
if (phoneNumber != null) {
177
return smsService.send(phoneNumber, message);
178
}
179
return NotificationResult.failed("No SMS fallback available");
180
}
181
182
// Push notification with multiple fallbacks
183
@Fallback(
184
fallbackMethod = "sendViaEmail",
185
applyOn = {PushServiceException.class}
186
)
187
public NotificationResult sendPushNotification(String userId, String message) {
188
return pushService.send(userId, message);
189
}
190
191
public NotificationResult sendViaEmail(String userId, String message) {
192
String email = userService.getEmail(userId);
193
try {
194
return sendEmail(email, message); // This has its own fallback
195
} catch (Exception e) {
196
return NotificationResult.failed("All notification methods failed");
197
}
198
}
199
}
200
```
201
202
### Fallback with Circuit Breaker
203
204
Combined fallback and circuit breaker patterns for comprehensive resilience.
205
206
```java { .api }
207
@CircuitBreaker(requestVolumeThreshold = 10, failureRatio = 0.5)
208
@Fallback(fallbackMethod = "circuitBreakerFallback")
209
@Timeout(5000)
210
public ReturnType resilientMethod();
211
```
212
213
#### Usage Example
214
215
```java
216
@ApplicationScoped
217
public class CatalogService {
218
219
@Inject
220
ExternalCatalogApi externalApi;
221
222
@Inject
223
CatalogCache cache;
224
225
@Inject
226
DefaultCatalogProvider defaultProvider;
227
228
// Product catalog with circuit breaker and cached fallback
229
@CircuitBreaker(
230
requestVolumeThreshold = 15,
231
failureRatio = 0.3,
232
delay = 30000
233
)
234
@Fallback(fallbackMethod = "getCachedCatalog")
235
@Timeout(8000)
236
public ProductCatalog getProductCatalog(String category) throws CatalogException {
237
return externalApi.getCatalog(category);
238
}
239
240
public ProductCatalog getCachedCatalog(String category) throws CatalogException {
241
// Try cache first
242
ProductCatalog cached = cache.get(category);
243
if (cached != null && !cached.isExpired()) {
244
return cached.withStaleIndicator();
245
}
246
247
// Fall back to default catalog
248
return defaultProvider.getDefaultCatalog(category);
249
}
250
}
251
```
252
253
## Types
254
255
### Fallback Core Types
256
257
```java { .api }
258
// Execution context for fallback handlers
259
interface ExecutionContext {
260
Method getMethod();
261
Object[] getParameters();
262
Object getTarget();
263
Throwable getFailure();
264
Map<String, Object> getContextData();
265
}
266
267
// Fallback handler interface
268
interface FallbackHandler<T> {
269
/**
270
* Handle fallback execution
271
* @param context Execution context with method and failure information
272
* @return Fallback result
273
*/
274
T handle(ExecutionContext context);
275
}
276
277
// Method information
278
interface Method {
279
String getName();
280
Class<?>[] getParameterTypes();
281
Class<?> getReturnType();
282
Class<?> getDeclaringClass();
283
}
284
```