Context module for the Micronaut Framework that extends the micronaut-inject module with additional bean container services such as job scheduling with @Scheduled, event listeners with @EventListener, and immutable configuration properties
—
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.
Core interface for embedded server implementations providing server metadata and lifecycle management.
/**
* Interface for embedded server implementations
* Extends EmbeddedApplication with server-specific functionality
*/
public interface EmbeddedServer extends EmbeddedApplication<EmbeddedServer> {
/**
* Get the port the server is listening on
* @return Server port number
*/
int getPort();
/**
* Get the host the server is bound to
* @return Server host address
*/
String getHost();
/**
* Get the URL scheme (protocol) used by the server
* @return URL scheme (typically "http" or "https")
*/
String getScheme();
/**
* Get the complete server URL
* @return Full server URL including scheme, host, and port
*/
URL getURL();
/**
* Get the server URI
* @return Server URI
*/
URI getURI();
/**
* Get the context path URI for the server
* @return URI including context path if configured
*/
URI getContextURI();
/**
* Check if the server should remain alive after startup
* @return true if server should keep the JVM alive
*/
boolean isKeepAlive();
}Usage Examples:
import io.micronaut.runtime.server.EmbeddedServer;
import io.micronaut.runtime.Micronaut;
public class ServerInfoExample {
public static void main(String[] args) {
ApplicationContext context = Micronaut.run(ServerInfoExample.class, args);
// Get embedded server information
EmbeddedServer server = context.getBean(EmbeddedServer.class);
System.out.println("Server Details:");
System.out.println(" URL: " + server.getURL());
System.out.println(" Host: " + server.getHost());
System.out.println(" Port: " + server.getPort());
System.out.println(" Scheme: " + server.getScheme());
System.out.println(" Context URI: " + server.getContextURI());
System.out.println(" Keep Alive: " + server.isKeepAlive());
System.out.println(" Running: " + server.isRunning());
}
}
// Service that uses server information
@Singleton
public class ServiceRegistrationService {
private final EmbeddedServer server;
public ServiceRegistrationService(EmbeddedServer server) {
this.server = server;
}
public void registerWithServiceDiscovery() {
String serviceUrl = server.getURL().toString();
// Register this service instance
ServiceRegistry.register(
"my-service",
serviceUrl,
Map.of(
"host", server.getHost(),
"port", String.valueOf(server.getPort()),
"scheme", server.getScheme()
)
);
}
}Events fired during embedded server startup and shutdown phases.
/**
* Event fired when EmbeddedServer completes startup
* Indicates server is ready to accept HTTP requests
*/
public class ServerStartupEvent extends ApplicationStartupEvent {
/**
* Create server startup event
* @param embeddedServer The server that completed startup
*/
public ServerStartupEvent(EmbeddedServer embeddedServer);
/**
* Get the embedded server that started
* @return EmbeddedServer instance
*/
@Override
public EmbeddedServer getSource();
}
/**
* Event fired when EmbeddedServer begins shutdown
* Server will no longer accept new requests after this event
*/
public class ServerShutdownEvent extends ApplicationEvent {
/**
* Create server shutdown event
* @param embeddedServer The server that is shutting down
*/
public ServerShutdownEvent(EmbeddedServer embeddedServer);
/**
* Get the embedded server that is shutting down
* @return EmbeddedServer instance
*/
@Override
public EmbeddedServer getSource();
}Usage Examples:
import io.micronaut.runtime.server.event.ServerStartupEvent;
import io.micronaut.runtime.server.event.ServerShutdownEvent;
import io.micronaut.runtime.event.annotation.EventListener;
@Singleton
public class ServerLifecycleManager {
private static final Logger logger = LoggerFactory.getLogger(ServerLifecycleManager.class);
@EventListener
public void onServerStartup(ServerStartupEvent event) {
EmbeddedServer server = event.getSource();
logger.info("🚀 Server started successfully!");
logger.info(" Server URL: {}", server.getURL());
logger.info(" Host: {}", server.getHost());
logger.info(" Port: {}", server.getPort());
logger.info(" Scheme: {}", server.getScheme());
// Perform startup tasks
initializeHealthChecks(server);
registerWithLoadBalancer(server);
enableTrafficRouting(server);
// Log startup time
long startupTime = getStartupTime();
logger.info("✅ Server ready in {}ms", startupTime);
}
@EventListener
public void onServerShutdown(ServerShutdownEvent event) {
EmbeddedServer server = event.getSource();
logger.info("🛑 Server shutdown initiated");
logger.info(" Server URL: {}", server.getURL());
// Perform graceful shutdown tasks
deregisterFromLoadBalancer(server);
disableTrafficRouting(server);
completeOngoingRequests();
closeConnections();
logger.info("✅ Server shutdown completed");
}
private void initializeHealthChecks(EmbeddedServer server) {
// Start health check endpoints
healthCheckService.start(server.getPort());
}
private void registerWithLoadBalancer(EmbeddedServer server) {
// Register with external load balancer
loadBalancerClient.register(
server.getHost(),
server.getPort(),
server.getScheme()
);
}
}Working with server configuration and customization.
/**
* Server configuration integration examples
* Accessing and using server configuration
*/
// Configuration-driven server behavior
@Singleton
public class ServerConfigurationService {
private final ServerConfiguration serverConfig;
private final EmbeddedServer embeddedServer;
public ServerConfigurationService(ServerConfiguration serverConfig,
EmbeddedServer embeddedServer) {
this.serverConfig = serverConfig;
this.embeddedServer = embeddedServer;
}
@EventListener
public void onServerStartup(ServerStartupEvent event) {
// Validate server configuration matches expectations
validateServerConfiguration();
// Configure server-specific features
configureServerFeatures();
}
private void validateServerConfiguration() {
int actualPort = embeddedServer.getPort();
int configuredPort = serverConfig.getPort();
if (actualPort != configuredPort) {
logger.warn("Server started on port {} but configured for port {}",
actualPort, configuredPort);
}
String actualHost = embeddedServer.getHost();
String configuredHost = serverConfig.getHost();
if (!Objects.equals(actualHost, configuredHost)) {
logger.info("Server host: actual={}, configured={}",
actualHost, configuredHost);
}
}
}
// Custom server startup logic
@Singleton
public class CustomServerStartup {
@EventListener
public void onServerStartup(ServerStartupEvent event) {
EmbeddedServer server = event.getSource();
// Custom initialization based on server properties
if ("https".equals(server.getScheme())) {
enableSecurityFeatures();
}
if (server.getPort() == 443 || server.getPort() == 80) {
enableProductionMode();
}
// Register custom endpoints
registerCustomEndpoints(server);
}
private void registerCustomEndpoints(EmbeddedServer server) {
String baseUrl = server.getURL().toString();
// Register metrics endpoint
endpointRegistry.register(baseUrl + "/metrics", metricsHandler);
// Register admin endpoint
if (isAdminEnabled()) {
endpointRegistry.register(baseUrl + "/admin", adminHandler);
}
}
}Integration with different server environments and deployment scenarios.
@Singleton
public class EnvironmentAwareServerManager {
private final Environment environment;
public EnvironmentAwareServerManager(Environment environment) {
this.environment = environment;
}
@EventListener
public void onServerStartup(ServerStartupEvent event) {
EmbeddedServer server = event.getSource();
// Environment-specific server configuration
if (environment.getActiveNames().contains("production")) {
configureProductionServer(server);
} else if (environment.getActiveNames().contains("development")) {
configureDevelopmentServer(server);
}
// Cloud environment detection
if (isRunningInCloud()) {
configureCloudServer(server);
}
// Container environment detection
if (isRunningInContainer()) {
configureContainerServer(server);
}
}
private void configureProductionServer(EmbeddedServer server) {
logger.info("Configuring server for production environment");
// Enable production features
enableRequestLogging();
enablePerformanceMonitoring();
configureSecurityHeaders();
// Validate production requirements
if (!"https".equals(server.getScheme())) {
logger.warn("Production server not using HTTPS: {}", server.getURL());
}
}
private void configureDevelopmentServer(EmbeddedServer server) {
logger.info("Configuring server for development environment");
// Enable development features
enableDebugEndpoints();
enableHotReload();
disableSecurityRestrictions();
logger.info("Development server ready at: {}", server.getURL());
}
private boolean isRunningInCloud() {
// Detect cloud environment (AWS, GCP, Azure, etc.)
return environment.getProperty("cloud.platform").isPresent() ||
System.getenv("AWS_REGION") != null ||
System.getenv("GOOGLE_CLOUD_PROJECT") != null;
}
private boolean isRunningInContainer() {
// Detect container environment (Docker, Kubernetes, etc.)
return Files.exists(Paths.get("/.dockerenv")) ||
System.getenv("KUBERNETES_SERVICE_HOST") != null;
}
}Integration with health checks and monitoring systems.
@Singleton
public class ServerHealthManager {
private final MeterRegistry meterRegistry;
private final HealthAggregator healthAggregator;
public ServerHealthManager(MeterRegistry meterRegistry,
HealthAggregator healthAggregator) {
this.meterRegistry = meterRegistry;
this.healthAggregator = healthAggregator;
}
@EventListener
public void onServerStartup(ServerStartupEvent event) {
EmbeddedServer server = event.getSource();
// Register server metrics
registerServerMetrics(server);
// Initialize health checks
initializeHealthChecks(server);
// Start monitoring
startServerMonitoring(server);
}
private void registerServerMetrics(EmbeddedServer server) {
// Server information gauges
Gauge.builder("server.port")
.description("Server port number")
.register(meterRegistry, server, s -> s.getPort());
Gauge.builder("server.running")
.description("Server running status")
.register(meterRegistry, server, s -> s.isRunning() ? 1 : 0);
// Server startup timer
Timer.Sample startupTimer = Timer.start(meterRegistry);
startupTimer.stop(Timer.builder("server.startup.time")
.description("Server startup time")
.register(meterRegistry));
}
private void initializeHealthChecks(EmbeddedServer server) {
// Register server-specific health indicators
healthAggregator.addHealthIndicator("server", () ->
server.isRunning() ?
HealthStatus.UP.describe("Server running on " + server.getURL()) :
HealthStatus.DOWN.describe("Server not running")
);
// Port availability check
healthAggregator.addHealthIndicator("server.port", () ->
isPortAccessible(server.getHost(), server.getPort()) ?
HealthStatus.UP.describe("Port " + server.getPort() + " accessible") :
HealthStatus.DOWN.describe("Port " + server.getPort() + " not accessible")
);
}
@EventListener
public void onServerShutdown(ServerShutdownEvent event) {
// Record shutdown metrics
meterRegistry.counter("server.shutdown.count").increment();
// Update health status
healthAggregator.updateHealthIndicator("server",
HealthStatus.DOWN.describe("Server shutting down"));
}
}Examples of integrating server lifecycle with external systems.
@Singleton
public class ExternalSystemIntegration {
private final ServiceDiscoveryClient serviceDiscovery;
private final LoadBalancerClient loadBalancer;
private final MetricsCollector metricsCollector;
@EventListener
@Async
public CompletableFuture<Void> onServerStartup(ServerStartupEvent event) {
return CompletableFuture.runAsync(() -> {
EmbeddedServer server = event.getSource();
try {
// Register with service discovery
registerWithServiceDiscovery(server);
// Add to load balancer pool
addToLoadBalancerPool(server);
// Start external monitoring
startExternalMonitoring(server);
logger.info("Server successfully registered with external systems");
} catch (Exception e) {
logger.error("Failed to register with external systems", e);
// Could trigger health check failure or retry logic
}
});
}
@EventListener
@Async
public CompletableFuture<Void> onServerShutdown(ServerShutdownEvent event) {
return CompletableFuture.runAsync(() -> {
EmbeddedServer server = event.getSource();
try {
// Graceful deregistration from external systems
removeFromLoadBalancerPool(server);
deregisterFromServiceDiscovery(server);
stopExternalMonitoring(server);
logger.info("Server successfully deregistered from external systems");
} catch (Exception e) {
logger.error("Error during external system deregistration", e);
}
});
}
private void registerWithServiceDiscovery(EmbeddedServer server) {
ServiceInstance instance = ServiceInstance.builder()
.instanceId(generateInstanceId())
.serviceName("my-service")
.host(server.getHost())
.port(server.getPort())
.secure("https".equals(server.getScheme()))
.metadata(Map.of(
"version", getApplicationVersion(),
"environment", getCurrentEnvironment(),
"contextPath", server.getContextURI().getPath()
))
.build();
serviceDiscovery.register(instance);
}
}Install with Tessl CLI
npx tessl i tessl/maven-io-micronaut--micronaut-context