0
# Server Lifecycle
1
2
Embedded server abstraction and lifecycle management for web applications. Provides unified interface for different server implementations with comprehensive startup/shutdown coordination and server information access.
3
4
## Capabilities
5
6
### EmbeddedServer Interface
7
8
Core interface for embedded server implementations providing server metadata and lifecycle management.
9
10
```java { .api }
11
/**
12
* Interface for embedded server implementations
13
* Extends EmbeddedApplication with server-specific functionality
14
*/
15
public interface EmbeddedServer extends EmbeddedApplication<EmbeddedServer> {
16
17
/**
18
* Get the port the server is listening on
19
* @return Server port number
20
*/
21
int getPort();
22
23
/**
24
* Get the host the server is bound to
25
* @return Server host address
26
*/
27
String getHost();
28
29
/**
30
* Get the URL scheme (protocol) used by the server
31
* @return URL scheme (typically "http" or "https")
32
*/
33
String getScheme();
34
35
/**
36
* Get the complete server URL
37
* @return Full server URL including scheme, host, and port
38
*/
39
URL getURL();
40
41
/**
42
* Get the server URI
43
* @return Server URI
44
*/
45
URI getURI();
46
47
/**
48
* Get the context path URI for the server
49
* @return URI including context path if configured
50
*/
51
URI getContextURI();
52
53
/**
54
* Check if the server should remain alive after startup
55
* @return true if server should keep the JVM alive
56
*/
57
boolean isKeepAlive();
58
}
59
```
60
61
**Usage Examples:**
62
63
```java
64
import io.micronaut.runtime.server.EmbeddedServer;
65
import io.micronaut.runtime.Micronaut;
66
67
public class ServerInfoExample {
68
69
public static void main(String[] args) {
70
ApplicationContext context = Micronaut.run(ServerInfoExample.class, args);
71
72
// Get embedded server information
73
EmbeddedServer server = context.getBean(EmbeddedServer.class);
74
75
System.out.println("Server Details:");
76
System.out.println(" URL: " + server.getURL());
77
System.out.println(" Host: " + server.getHost());
78
System.out.println(" Port: " + server.getPort());
79
System.out.println(" Scheme: " + server.getScheme());
80
System.out.println(" Context URI: " + server.getContextURI());
81
System.out.println(" Keep Alive: " + server.isKeepAlive());
82
System.out.println(" Running: " + server.isRunning());
83
}
84
}
85
86
// Service that uses server information
87
@Singleton
88
public class ServiceRegistrationService {
89
90
private final EmbeddedServer server;
91
92
public ServiceRegistrationService(EmbeddedServer server) {
93
this.server = server;
94
}
95
96
public void registerWithServiceDiscovery() {
97
String serviceUrl = server.getURL().toString();
98
99
// Register this service instance
100
ServiceRegistry.register(
101
"my-service",
102
serviceUrl,
103
Map.of(
104
"host", server.getHost(),
105
"port", String.valueOf(server.getPort()),
106
"scheme", server.getScheme()
107
)
108
);
109
}
110
}
111
```
112
113
### Server Lifecycle Events
114
115
Events fired during embedded server startup and shutdown phases.
116
117
```java { .api }
118
/**
119
* Event fired when EmbeddedServer completes startup
120
* Indicates server is ready to accept HTTP requests
121
*/
122
public class ServerStartupEvent extends ApplicationStartupEvent {
123
124
/**
125
* Create server startup event
126
* @param embeddedServer The server that completed startup
127
*/
128
public ServerStartupEvent(EmbeddedServer embeddedServer);
129
130
/**
131
* Get the embedded server that started
132
* @return EmbeddedServer instance
133
*/
134
@Override
135
public EmbeddedServer getSource();
136
}
137
138
/**
139
* Event fired when EmbeddedServer begins shutdown
140
* Server will no longer accept new requests after this event
141
*/
142
public class ServerShutdownEvent extends ApplicationEvent {
143
144
/**
145
* Create server shutdown event
146
* @param embeddedServer The server that is shutting down
147
*/
148
public ServerShutdownEvent(EmbeddedServer embeddedServer);
149
150
/**
151
* Get the embedded server that is shutting down
152
* @return EmbeddedServer instance
153
*/
154
@Override
155
public EmbeddedServer getSource();
156
}
157
```
158
159
**Usage Examples:**
160
161
```java
162
import io.micronaut.runtime.server.event.ServerStartupEvent;
163
import io.micronaut.runtime.server.event.ServerShutdownEvent;
164
import io.micronaut.runtime.event.annotation.EventListener;
165
166
@Singleton
167
public class ServerLifecycleManager {
168
169
private static final Logger logger = LoggerFactory.getLogger(ServerLifecycleManager.class);
170
171
@EventListener
172
public void onServerStartup(ServerStartupEvent event) {
173
EmbeddedServer server = event.getSource();
174
175
logger.info("π Server started successfully!");
176
logger.info(" Server URL: {}", server.getURL());
177
logger.info(" Host: {}", server.getHost());
178
logger.info(" Port: {}", server.getPort());
179
logger.info(" Scheme: {}", server.getScheme());
180
181
// Perform startup tasks
182
initializeHealthChecks(server);
183
registerWithLoadBalancer(server);
184
enableTrafficRouting(server);
185
186
// Log startup time
187
long startupTime = getStartupTime();
188
logger.info("β Server ready in {}ms", startupTime);
189
}
190
191
@EventListener
192
public void onServerShutdown(ServerShutdownEvent event) {
193
EmbeddedServer server = event.getSource();
194
195
logger.info("π Server shutdown initiated");
196
logger.info(" Server URL: {}", server.getURL());
197
198
// Perform graceful shutdown tasks
199
deregisterFromLoadBalancer(server);
200
disableTrafficRouting(server);
201
completeOngoingRequests();
202
closeConnections();
203
204
logger.info("β Server shutdown completed");
205
}
206
207
private void initializeHealthChecks(EmbeddedServer server) {
208
// Start health check endpoints
209
healthCheckService.start(server.getPort());
210
}
211
212
private void registerWithLoadBalancer(EmbeddedServer server) {
213
// Register with external load balancer
214
loadBalancerClient.register(
215
server.getHost(),
216
server.getPort(),
217
server.getScheme()
218
);
219
}
220
}
221
```
222
223
### Server Configuration Integration
224
225
Working with server configuration and customization.
226
227
```java { .api }
228
/**
229
* Server configuration integration examples
230
* Accessing and using server configuration
231
*/
232
233
// Configuration-driven server behavior
234
@Singleton
235
public class ServerConfigurationService {
236
237
private final ServerConfiguration serverConfig;
238
private final EmbeddedServer embeddedServer;
239
240
public ServerConfigurationService(ServerConfiguration serverConfig,
241
EmbeddedServer embeddedServer) {
242
this.serverConfig = serverConfig;
243
this.embeddedServer = embeddedServer;
244
}
245
246
@EventListener
247
public void onServerStartup(ServerStartupEvent event) {
248
// Validate server configuration matches expectations
249
validateServerConfiguration();
250
251
// Configure server-specific features
252
configureServerFeatures();
253
}
254
255
private void validateServerConfiguration() {
256
int actualPort = embeddedServer.getPort();
257
int configuredPort = serverConfig.getPort();
258
259
if (actualPort != configuredPort) {
260
logger.warn("Server started on port {} but configured for port {}",
261
actualPort, configuredPort);
262
}
263
264
String actualHost = embeddedServer.getHost();
265
String configuredHost = serverConfig.getHost();
266
267
if (!Objects.equals(actualHost, configuredHost)) {
268
logger.info("Server host: actual={}, configured={}",
269
actualHost, configuredHost);
270
}
271
}
272
}
273
274
// Custom server startup logic
275
@Singleton
276
public class CustomServerStartup {
277
278
@EventListener
279
public void onServerStartup(ServerStartupEvent event) {
280
EmbeddedServer server = event.getSource();
281
282
// Custom initialization based on server properties
283
if ("https".equals(server.getScheme())) {
284
enableSecurityFeatures();
285
}
286
287
if (server.getPort() == 443 || server.getPort() == 80) {
288
enableProductionMode();
289
}
290
291
// Register custom endpoints
292
registerCustomEndpoints(server);
293
}
294
295
private void registerCustomEndpoints(EmbeddedServer server) {
296
String baseUrl = server.getURL().toString();
297
298
// Register metrics endpoint
299
endpointRegistry.register(baseUrl + "/metrics", metricsHandler);
300
301
// Register admin endpoint
302
if (isAdminEnabled()) {
303
endpointRegistry.register(baseUrl + "/admin", adminHandler);
304
}
305
}
306
}
307
```
308
309
### Server Environment Integration
310
311
Integration with different server environments and deployment scenarios.
312
313
```java { .api }
314
@Singleton
315
public class EnvironmentAwareServerManager {
316
317
private final Environment environment;
318
319
public EnvironmentAwareServerManager(Environment environment) {
320
this.environment = environment;
321
}
322
323
@EventListener
324
public void onServerStartup(ServerStartupEvent event) {
325
EmbeddedServer server = event.getSource();
326
327
// Environment-specific server configuration
328
if (environment.getActiveNames().contains("production")) {
329
configureProductionServer(server);
330
} else if (environment.getActiveNames().contains("development")) {
331
configureDevelopmentServer(server);
332
}
333
334
// Cloud environment detection
335
if (isRunningInCloud()) {
336
configureCloudServer(server);
337
}
338
339
// Container environment detection
340
if (isRunningInContainer()) {
341
configureContainerServer(server);
342
}
343
}
344
345
private void configureProductionServer(EmbeddedServer server) {
346
logger.info("Configuring server for production environment");
347
348
// Enable production features
349
enableRequestLogging();
350
enablePerformanceMonitoring();
351
configureSecurityHeaders();
352
353
// Validate production requirements
354
if (!"https".equals(server.getScheme())) {
355
logger.warn("Production server not using HTTPS: {}", server.getURL());
356
}
357
}
358
359
private void configureDevelopmentServer(EmbeddedServer server) {
360
logger.info("Configuring server for development environment");
361
362
// Enable development features
363
enableDebugEndpoints();
364
enableHotReload();
365
disableSecurityRestrictions();
366
367
logger.info("Development server ready at: {}", server.getURL());
368
}
369
370
private boolean isRunningInCloud() {
371
// Detect cloud environment (AWS, GCP, Azure, etc.)
372
return environment.getProperty("cloud.platform").isPresent() ||
373
System.getenv("AWS_REGION") != null ||
374
System.getenv("GOOGLE_CLOUD_PROJECT") != null;
375
}
376
377
private boolean isRunningInContainer() {
378
// Detect container environment (Docker, Kubernetes, etc.)
379
return Files.exists(Paths.get("/.dockerenv")) ||
380
System.getenv("KUBERNETES_SERVICE_HOST") != null;
381
}
382
}
383
```
384
385
### Server Health and Monitoring
386
387
Integration with health checks and monitoring systems.
388
389
```java { .api }
390
@Singleton
391
public class ServerHealthManager {
392
393
private final MeterRegistry meterRegistry;
394
private final HealthAggregator healthAggregator;
395
396
public ServerHealthManager(MeterRegistry meterRegistry,
397
HealthAggregator healthAggregator) {
398
this.meterRegistry = meterRegistry;
399
this.healthAggregator = healthAggregator;
400
}
401
402
@EventListener
403
public void onServerStartup(ServerStartupEvent event) {
404
EmbeddedServer server = event.getSource();
405
406
// Register server metrics
407
registerServerMetrics(server);
408
409
// Initialize health checks
410
initializeHealthChecks(server);
411
412
// Start monitoring
413
startServerMonitoring(server);
414
}
415
416
private void registerServerMetrics(EmbeddedServer server) {
417
// Server information gauges
418
Gauge.builder("server.port")
419
.description("Server port number")
420
.register(meterRegistry, server, s -> s.getPort());
421
422
Gauge.builder("server.running")
423
.description("Server running status")
424
.register(meterRegistry, server, s -> s.isRunning() ? 1 : 0);
425
426
// Server startup timer
427
Timer.Sample startupTimer = Timer.start(meterRegistry);
428
startupTimer.stop(Timer.builder("server.startup.time")
429
.description("Server startup time")
430
.register(meterRegistry));
431
}
432
433
private void initializeHealthChecks(EmbeddedServer server) {
434
// Register server-specific health indicators
435
healthAggregator.addHealthIndicator("server", () ->
436
server.isRunning() ?
437
HealthStatus.UP.describe("Server running on " + server.getURL()) :
438
HealthStatus.DOWN.describe("Server not running")
439
);
440
441
// Port availability check
442
healthAggregator.addHealthIndicator("server.port", () ->
443
isPortAccessible(server.getHost(), server.getPort()) ?
444
HealthStatus.UP.describe("Port " + server.getPort() + " accessible") :
445
HealthStatus.DOWN.describe("Port " + server.getPort() + " not accessible")
446
);
447
}
448
449
@EventListener
450
public void onServerShutdown(ServerShutdownEvent event) {
451
// Record shutdown metrics
452
meterRegistry.counter("server.shutdown.count").increment();
453
454
// Update health status
455
healthAggregator.updateHealthIndicator("server",
456
HealthStatus.DOWN.describe("Server shutting down"));
457
}
458
}
459
```
460
461
### Integration with External Systems
462
463
Examples of integrating server lifecycle with external systems.
464
465
```java { .api }
466
@Singleton
467
public class ExternalSystemIntegration {
468
469
private final ServiceDiscoveryClient serviceDiscovery;
470
private final LoadBalancerClient loadBalancer;
471
private final MetricsCollector metricsCollector;
472
473
@EventListener
474
@Async
475
public CompletableFuture<Void> onServerStartup(ServerStartupEvent event) {
476
return CompletableFuture.runAsync(() -> {
477
EmbeddedServer server = event.getSource();
478
479
try {
480
// Register with service discovery
481
registerWithServiceDiscovery(server);
482
483
// Add to load balancer pool
484
addToLoadBalancerPool(server);
485
486
// Start external monitoring
487
startExternalMonitoring(server);
488
489
logger.info("Server successfully registered with external systems");
490
} catch (Exception e) {
491
logger.error("Failed to register with external systems", e);
492
// Could trigger health check failure or retry logic
493
}
494
});
495
}
496
497
@EventListener
498
@Async
499
public CompletableFuture<Void> onServerShutdown(ServerShutdownEvent event) {
500
return CompletableFuture.runAsync(() -> {
501
EmbeddedServer server = event.getSource();
502
503
try {
504
// Graceful deregistration from external systems
505
removeFromLoadBalancerPool(server);
506
deregisterFromServiceDiscovery(server);
507
stopExternalMonitoring(server);
508
509
logger.info("Server successfully deregistered from external systems");
510
} catch (Exception e) {
511
logger.error("Error during external system deregistration", e);
512
}
513
});
514
}
515
516
private void registerWithServiceDiscovery(EmbeddedServer server) {
517
ServiceInstance instance = ServiceInstance.builder()
518
.instanceId(generateInstanceId())
519
.serviceName("my-service")
520
.host(server.getHost())
521
.port(server.getPort())
522
.secure("https".equals(server.getScheme()))
523
.metadata(Map.of(
524
"version", getApplicationVersion(),
525
"environment", getCurrentEnvironment(),
526
"contextPath", server.getContextURI().getPath()
527
))
528
.build();
529
530
serviceDiscovery.register(instance);
531
}
532
}
533
```