Fading Coder

One Final Commit for the Last Sprint

Home > Notes > Content

Lifecycle Management and Configuration Initialization in Spring and Spring MVC Integration

Notes May 15 1

When a Java web container boots, the initialization sequence of framework configuration files is tight coupled with the ServletContext lifecycle. Proper hooking into this startup phase ensures that application contexts, data sources, and environment properties are loaded at the correct time.

Native Servlet Context Listeners

The most direct approach involves attaching a listener to the ServletContext lifecycle. The container triggers initialization callbacks before dispatching any requests, making it an ideal place for foundational setup.

package com.example.web.config;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class WebBootstrapListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent event) {
        logInitializationPhase("ServletContext is now active");
        setupLegacyResources(event.getServletContext());
    }

    @Override
    public void contextDestroyed(ServletContextEvent event) {
        cleanupResources();
    }

    private void logInitializationPhase(String message) {
        System.out.println("[BOOTSTRAP] " + message);
    }

    private void setupLegacyResources(Object context) {
        // Placeholder for legacy setup logic
    }

    private void cleanupResources() {
        System.out.println("[SHUTDOWN] Cleaning up native resources");
    }
}

Spring Framework Event Listeners

Within the Spring ecosystem, component-driven event listening provides a more integrated mechanism. By implementing ApplicationListener, beans can react to framework-level events once the ApplicationContext begins to populate.

package com.example.core.listener;

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Service;

@Service
public class FrameworkEventObserver implements ApplicationListener<ApplicationEvent> {

    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        recordEventMetadata(event);
    }

    private void recordEventMetadata(ApplicationEvent evt) {
        System.out.println("Event Type: " + evt.getClass().getSimpleName());
        System.out.println("Timestamp: " + evt.getTimestamp());
    }
}

Execution Order Considerations

It is crucial to understand the precedence of these listeners. The native ServletContextListener executes first, as the servlet container must establish the web context before Spring can instantiate its ApplicationContext. Consequently, framework-level listeners will only trigger after the foundational servlet infrastructure is ready.

Spring Boot Startup Phase Hooks

For applications leveraging Spring Boot, fine-grained control over the entire bootstrap process is achieved through SpringApplicationRunListener. This interface exposes distinct phases, allowing developers to inject logic before enviroment preparation, context creation, and actual application execution.

package com.example.boot.hook;

import org.springframework.boot.ConfigurableBootstrapContext;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringApplicationRunListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import java.util.Map;

public class DetailedBootstrapMonitor implements SpringApplicationRunListener {
    private final SpringApplication appInstance;
    private final String[] startupParameters;

    public DetailedBootstrapMonitor(SpringApplication application, String[] arguments) {
        this.appInstance = application;
        this.startupParameters = arguments;
    }

    @Override
    public void starting(ConfigurableBootstrapContext ctx) {
        System.out.println("Phase: Application bootstrap initiated");
    }

    @Override
    public void environmentPrepared(ConfigurableBootstrapContext ctx, ConfigurableEnvironment env) {
        System.out.println("Phase: Environment configuration resolved");
        Map<String, Object> osProps = env.getSystemProperties();
        Map<String, Object> envVars = env.getSystemEnvironment();
        System.out.println("Active System Properties: " + osProps.size());
        System.out.println("Loaded Environment Variables: " + envVars.size());
    }

    @Override
    public void contextPrepared(ConfigurableApplicationContext ctx) {
        System.out.println("Phase: ApplicationContext initialized and prepared");
    }

    @Override
    public void contextLoaded(ConfigurableApplicationContext ctx) {
        System.out.println("Phase: Bean definitions loaded into context");
    }

    @Override
    public void started(ConfigurableApplicationContext ctx) {
        System.out.println("Phase: Application context fully refreshed and started");
    }

    @Override
    public void running(ConfigurableApplicationContext ctx) {
        System.out.println("Phase: Application is now running and accepting requests");
    }

    @Override
    public void failed(ConfigurableApplicationContext ctx, Throwable error) {
        System.out.println("Phase: Bootstrap failed - " + error.getMessage());
    }
}

To activate this custom listener in a Spring Boot environment, it must be registered via the service provider interface. In traditional setups, this is accomplished by creating a spring.factories file under META-INF/ with the following mapping:

org.springframework.boot.SpringApplicationRunListener=com.example.boot.hook.DetailedBootstrapMonitor

Modern Spring Boot versions may utilize META-INF/spring/org.springframework.boot.SpringApplicationRunListener.imports for the same purpose.

Tags: spring

Related Articles

Designing Alertmanager Templates for Prometheus Notifications

How to craft Alertmanager templates to format alert messages, improving clarity and presentation. Alertmanager uses Go’s text/template engine with additional helper functions. Alerting rules referenc...

Deploying a Maven Web Application to Tomcat 9 Using the Tomcat Manager

Tomcat 9 does not provide a dedicated Maven plugin. The Tomcat Manager interface, however, is backward-compatible, so the Tomcat 7 Maven Plugin can be used to deploy to Tomcat 9. This guide shows two...

Skipping Errors in MySQL Asynchronous Replication

When a replica halts because the SQL thread encounters an error, you can resume replication by skipping the problematic event(s). Two common approaches are available. Methods to Skip Errors 1) Skip a...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.