0
# Component Lifecycle
1
2
Robust component lifecycle management with container support, event notifications, and graceful shutdown capabilities. The lifecycle system provides consistent state management for all Jetty components.
3
4
## Capabilities
5
6
### LifeCycle Interface
7
8
Core component lifecycle management interface with well-defined state transitions.
9
10
```java { .api }
11
/**
12
* Component lifecycle interface
13
*/
14
public interface LifeCycle {
15
/** Start the component */
16
void start() throws Exception;
17
18
/** Stop the component */
19
void stop() throws Exception;
20
21
/** Check if component is running */
22
boolean isRunning();
23
24
/** Check if component is started */
25
boolean isStarted();
26
27
/** Check if component is stopped */
28
boolean isStopped();
29
30
/** Check if component is failed */
31
boolean isFailed();
32
33
/** Check if component is starting */
34
boolean isStarting();
35
36
/** Check if component is stopping */
37
boolean isStopping();
38
39
/** Add lifecycle listener */
40
void addLifeCycleListener(LifeCycle.Listener listener);
41
42
/** Remove lifecycle listener */
43
void removeLifeCycleListener(LifeCycle.Listener listener);
44
45
/** Lifecycle event listener interface */
46
interface Listener {
47
default void lifeCycleStarting(LifeCycle event) {}
48
default void lifeCycleStarted(LifeCycle event) {}
49
default void lifeCycleFailure(LifeCycle event, Throwable cause) {}
50
default void lifeCycleStopping(LifeCycle event) {}
51
default void lifeCycleStopped(LifeCycle event) {}
52
}
53
}
54
```
55
56
**Usage Examples:**
57
58
```java
59
import org.eclipse.jetty.util.component.LifeCycle;
60
61
// Basic lifecycle usage
62
LifeCycle component = new MyComponent();
63
64
// Add listener for lifecycle events
65
component.addLifeCycleListener(new LifeCycle.Listener() {
66
@Override
67
public void lifeCycleStarted(LifeCycle event) {
68
System.out.println("Component started: " + event);
69
}
70
71
@Override
72
public void lifeCycleFailure(LifeCycle event, Throwable cause) {
73
System.err.println("Component failed: " + cause.getMessage());
74
}
75
});
76
77
// Start and stop
78
try {
79
component.start();
80
// ... use component
81
} finally {
82
component.stop();
83
}
84
```
85
86
### AbstractLifeCycle
87
88
Base implementation providing common lifecycle functionality.
89
90
```java { .api }
91
/**
92
* Abstract base class for lifecycle components
93
*/
94
public abstract class AbstractLifeCycle implements LifeCycle {
95
/** Get current lifecycle state */
96
public State getState();
97
98
/** Template method for start implementation */
99
protected abstract void doStart() throws Exception;
100
101
/** Template method for stop implementation */
102
protected abstract void doStop() throws Exception;
103
104
/** Set state to failed */
105
protected void setFailed(Throwable th);
106
107
/** Lifecycle states */
108
public enum State {
109
STOPPED, STARTING, STARTED, STOPPING, FAILED
110
}
111
}
112
```
113
114
**Usage Examples:**
115
116
```java
117
import org.eclipse.jetty.util.component.AbstractLifeCycle;
118
119
public class MyService extends AbstractLifeCycle {
120
private ServerSocket serverSocket;
121
122
@Override
123
protected void doStart() throws Exception {
124
serverSocket = new ServerSocket(8080);
125
System.out.println("Service started on port 8080");
126
}
127
128
@Override
129
protected void doStop() throws Exception {
130
if (serverSocket != null) {
131
serverSocket.close();
132
serverSocket = null;
133
}
134
System.out.println("Service stopped");
135
}
136
137
public void handleClient() {
138
if (!isStarted()) {
139
throw new IllegalStateException("Service not started");
140
}
141
// Handle client request
142
}
143
}
144
```
145
146
### Container Interface
147
148
Component containment and relationship management.
149
150
```java { .api }
151
/**
152
* Container interface for managing child components
153
*/
154
public interface Container {
155
/** Add a bean to the container */
156
void addBean(Object bean);
157
158
/** Add a bean with managed lifecycle */
159
void addBean(Object bean, boolean managed);
160
161
/** Remove a bean from the container */
162
boolean removeBean(Object bean);
163
164
/** Get all beans of specified type */
165
<T> Collection<T> getBeans(Class<T> clazz);
166
167
/** Get single bean of specified type */
168
<T> T getBean(Class<T> clazz);
169
170
/** Check if bean is managed */
171
boolean isManaged(Object bean);
172
173
/** Container event listener */
174
interface Listener {
175
void beanAdded(Container parent, Object child);
176
void beanRemoved(Container parent, Object child);
177
}
178
179
/** Inherited listener that propagates to children */
180
interface InheritedListener extends Listener {
181
// Marker interface for listeners that should be inherited by child containers
182
}
183
}
184
```
185
186
### ContainerLifeCycle
187
188
Combined lifecycle and container implementation.
189
190
```java { .api }
191
/**
192
* Lifecycle implementation with container capabilities
193
*/
194
public class ContainerLifeCycle extends AbstractLifeCycle implements Container, Dumpable {
195
/** Add managed bean */
196
public void addManaged(LifeCycle bean);
197
198
/** Install bean (add and start if container is started) */
199
public void installBean(Object bean);
200
201
/** Install bean with management flag */
202
public void installBean(Object bean, boolean managed);
203
204
/** Uninstall bean (stop and remove if managed) */
205
public void uninstallBean(Object bean);
206
207
/** Update bean (replace existing) */
208
public void updateBean(Object oldBean, Object newBean);
209
210
/** Get contained beans */
211
public Collection<Object> getBeans();
212
213
/** Auto start/stop child components */
214
public void setAutoStart(boolean auto);
215
216
/** Check if auto start is enabled */
217
public boolean isAutoStart();
218
}
219
```
220
221
**Usage Examples:**
222
223
```java
224
import org.eclipse.jetty.util.component.ContainerLifeCycle;
225
226
public class Server extends ContainerLifeCycle {
227
private final List<Handler> handlers = new ArrayList<>();
228
229
public void addHandler(Handler handler) {
230
addBean(handler, true); // Managed lifecycle
231
handlers.add(handler);
232
}
233
234
public void removeHandler(Handler handler) {
235
removeBean(handler);
236
handlers.remove(handler);
237
}
238
239
@Override
240
protected void doStart() throws Exception {
241
// Start all managed beans automatically
242
super.doStart();
243
System.out.println("Server started with " + getBeans(Handler.class).size() + " handlers");
244
}
245
246
@Override
247
protected void doStop() throws Exception {
248
System.out.println("Stopping server");
249
// Stop all managed beans automatically
250
super.doStop();
251
}
252
}
253
```
254
255
### Graceful Shutdown
256
257
Graceful shutdown interface for components that need time to complete operations.
258
259
```java { .api }
260
/**
261
* Interface for components supporting graceful shutdown
262
*/
263
public interface Graceful {
264
/** Initiate graceful shutdown */
265
CompletableFuture<Void> shutdown();
266
267
/** Check if shutdown is in progress */
268
boolean isShutdown();
269
270
/** Graceful shutdown utility */
271
static CompletableFuture<Void> shutdown(Object... objects) {
272
// Utility method to shutdown multiple objects
273
}
274
}
275
```
276
277
**Usage Examples:**
278
279
```java
280
import org.eclipse.jetty.util.component.Graceful;
281
import java.util.concurrent.CompletableFuture;
282
import java.util.concurrent.TimeUnit;
283
284
public class GracefulService extends ContainerLifeCycle implements Graceful {
285
private volatile boolean shuttingDown = false;
286
private final AtomicInteger activeRequests = new AtomicInteger();
287
288
@Override
289
public CompletableFuture<Void> shutdown() {
290
shuttingDown = true;
291
292
return CompletableFuture.runAsync(() -> {
293
// Wait for active requests to complete
294
while (activeRequests.get() > 0) {
295
try {
296
Thread.sleep(100);
297
} catch (InterruptedException e) {
298
Thread.currentThread().interrupt();
299
break;
300
}
301
}
302
});
303
}
304
305
@Override
306
public boolean isShutdown() {
307
return shuttingDown;
308
}
309
310
public void handleRequest() {
311
if (shuttingDown) {
312
throw new IllegalStateException("Service is shutting down");
313
}
314
315
activeRequests.incrementAndGet();
316
try {
317
// Process request
318
} finally {
319
activeRequests.decrementAndGet();
320
}
321
}
322
}
323
324
// Usage
325
GracefulService service = new GracefulService();
326
service.start();
327
328
// Later, shutdown gracefully
329
CompletableFuture<Void> shutdown = service.shutdown();
330
try {
331
shutdown.get(30, TimeUnit.SECONDS); // Wait up to 30 seconds
332
service.stop();
333
} catch (TimeoutException e) {
334
// Force stop if graceful shutdown times out
335
service.stop();
336
}
337
```
338
339
### Utility Classes
340
341
Additional lifecycle utilities and helpers.
342
343
```java { .api }
344
/**
345
* Lifecycle utilities
346
*/
347
public class LifeCycleCallbackCollection<T> implements LifeCycle.Listener {
348
/** Add callback for specific event */
349
public void addCallback(T callback);
350
351
/** Remove callback */
352
public void removeCallback(T callback);
353
}
354
355
/**
356
* File-based lifecycle notifications
357
*/
358
public class FileNoticeLifeCycleListener implements LifeCycle.Listener {
359
/** Create listener that writes to file on events */
360
public FileNoticeLifeCycleListener(Path noticeFile, String startedMessage, String stoppedMessage);
361
}
362
363
/**
364
* JVM halt on lifecycle failure
365
*/
366
public class HaltLifeCycleListener implements LifeCycle.Listener {
367
/** Create listener that halts JVM on failure */
368
public HaltLifeCycleListener();
369
370
/** Create listener with custom exit code */
371
public HaltLifeCycleListener(int exitCode);
372
}
373
```
374
375
**Usage Examples:**
376
377
```java
378
import org.eclipse.jetty.util.component.*;
379
import java.nio.file.Paths;
380
381
// File-based notifications
382
FileNoticeLifeCycleListener fileListener = new FileNoticeLifeCycleListener(
383
Paths.get("/var/run/myapp.status"),
384
"STARTED",
385
"STOPPED"
386
);
387
component.addLifeCycleListener(fileListener);
388
389
// JVM halt on failure (for critical services)
390
HaltLifeCycleListener haltListener = new HaltLifeCycleListener(1);
391
criticalService.addLifeCycleListener(haltListener);
392
```
393
394
## Lifecycle Patterns
395
396
### Template Method Pattern
397
398
```java
399
// Extend AbstractLifeCycle for consistent behavior
400
public class MyComponent extends AbstractLifeCycle {
401
@Override
402
protected void doStart() throws Exception {
403
// Initialize resources
404
// Will be called exactly once during start transition
405
}
406
407
@Override
408
protected void doStop() throws Exception {
409
// Cleanup resources
410
// Will be called exactly once during stop transition
411
}
412
}
413
```
414
415
### Container Pattern
416
417
```java
418
// Use ContainerLifeCycle for components with children
419
public class CompositeService extends ContainerLifeCycle {
420
public CompositeService() {
421
addBean(new DatabaseService(), true); // Managed
422
addBean(new CacheService(), true); // Managed
423
addBean(new Logger(), false); // Unmanaged
424
}
425
426
// Child components automatically started/stopped
427
}
428
```
429
430
### Error Handling
431
432
Lifecycle operations handle errors through:
433
434
- State transitions to FAILED on exceptions during start/stop
435
- Listener notifications for failure events
436
- Automatic cleanup of partially started components
437
- Exception propagation to callers
438
439
## Best Practices
440
441
1. **Always extend AbstractLifeCycle** for consistent behavior
442
2. **Use ContainerLifeCycle** for components with dependencies
443
3. **Implement Graceful** for services that handle requests
444
4. **Add lifecycle listeners** for monitoring and diagnostics
445
5. **Handle exceptions** in doStart/doStop methods appropriately
446
6. **Use managed beans** for automatic lifecycle propagation
447
7. **Test state transitions** thoroughly in component tests