Skip to content

Refactor SpringBootServletInitializer.onStartup to initialize WebApplicationContext inside ServletContextListener #2070

@apogrebnyak

Description

@apogrebnyak

Currently, onStartup creates a web application, and only then registers a ServletContextListener (to react to contextDestroyed event).

If an application wants to register some other ServletContextListener before the SpringApplication is created it cannot reuse current onStartup method. I propose that onStartup be refactored to register a fully functioning ServletContextListener, that will be called by the Servlet container.

Here is a proposed refactoring:

@Override
public void onStartup (
        final ServletContext servletContext
    )
{
    servletContext.addListener(
        new ServletContextListener( ) {
            private ContextLoaderListener delegate = null;

            @Override
            public void contextInitialized ( final ServletContextEvent sce ) {
                final WebApplicationContext rootAppContext =
                    createRootApplicationContext(servletContext);

                if (rootAppContext != null) {
                    delegate = new ContextLoaderListener(rootAppContext);
                    // Do not call delegate.contextInitialized as we've 
                    // already initilized it
                }
                else {
                    this.logger.debug(
                        "No ContextLoaderListener registered, as "
                            + "createRootApplicationContext() did not "
                            + "return an application context");
                }
            }

            @Override
            public void contextDestroyed ( final ServletContextEvent sce ) {
                if ( delegate != null ) {
                    // Delegate call
                    delegate.contextDestroyed( sce );
                }
            }
        }
    );
}

With this change client application would be able to do the following:

public class ClientApp extends SpringBootServletInitializer {
  @Override
  public void onStartup (
        final ServletContext servletContext
    )
  {
    servletContext.addListener( new MyPreListener( ) );
    super.onStartup( servletContext );
    servletContext.addListener( new MyPostListener( ) );
  }
}

and ensure that listeners are called in order. Currently all listeners will be called only after SpringApplication has already been initialized (For some legacy applications this may not be desirable).

Metadata

Metadata

Assignees

No one assigned

    Labels

    status: declinedA suggestion or change that we don't feel we should currently apply

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions