Skip to content

Document how to rely on ServletContext with an embedded container setup #24561

@zaynetro

Description

@zaynetro

If Configuration class implements both ServletContextAware and DestructionAwareBeanPostProcessor then setServletContext will not be called.

Steps to reproduce:

  1. Init a project https://start.spring.io/
  2. Maven project, Spring boot 2.4.1, Java 8
  3. Add spring-boot-starter-web dependency
  4. Add two configuration classes
DemoConfig
package com.example.demo;

import javax.annotation.PostConstruct;
import javax.servlet.ServletContext;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.ServletContextAware;

@Configuration
public class DemoConfig implements DestructionAwareBeanPostProcessor, ServletContextAware {
    private static final Logger LOG = LoggerFactory.getLogger( DemoConfig.class );

    private ServletContext servletContext;

    @PostConstruct
    public void init() {
        LOG.warn( "init() {}", servletContext );
    }

    @Override
    public void postProcessBeforeDestruction( Object bean, String beanName ) throws BeansException {
    }

    @Override
    public void setServletContext( ServletContext servletContext ) {
        LOG.warn( "setServletContext() {}", servletContext );
        this.servletContext = servletContext;
    }

}
AnotherConfig
package com.example.demo;

import javax.annotation.PostConstruct;
import javax.servlet.ServletContext;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.ServletContextAware;

@Configuration
public class AnotherConfig implements ServletContextAware {
    private static final Logger LOG = LoggerFactory.getLogger( AnotherConfig.class );

    private ServletContext servletContext;

    @PostConstruct
    public void init() {
        LOG.warn( "init() {}", servletContext );
    }

    @Override
    public void setServletContext( ServletContext servletContext ) {
        LOG.warn( "setServletContext() {}", servletContext );
        this.servletContext = servletContext;
    }

}

Logs:

2020-12-18 22:17:01.742  INFO 331634 --- [           main] com.example.demo.DemoApplication         : Starting DemoApplication using Java 1.8.0_265 on zaynetro-thinkpad with PID 331634 (/home/zaynetro/Code/trial/demo-spring-boot/target/classes started by zaynetro in /home/zaynetro/Code/trial/demo-spring-boot)
2020-12-18 22:17:01.745 DEBUG 331634 --- [           main] com.example.demo.DemoApplication         : Running with Spring Boot v2.4.1, Spring v5.3.2
2020-12-18 22:17:01.746  INFO 331634 --- [           main] com.example.demo.DemoApplication         : No active profile set, falling back to default profiles: default
2020-12-18 22:17:02.367  WARN 331634 --- [           main] com.example.demo.DemoConfig              : init() null
2020-12-18 22:17:02.614  INFO 331634 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2020-12-18 22:17:02.623  INFO 331634 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2020-12-18 22:17:02.623  INFO 331634 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.41]
2020-12-18 22:17:02.668  INFO 331634 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2020-12-18 22:17:02.668  INFO 331634 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 873 ms
2020-12-18 22:17:02.713  WARN 331634 --- [           main] com.example.demo.AnotherConfig           : setServletContext() org.apache.catalina.core.ApplicationContextFacade@299266e2
2020-12-18 22:17:02.713  WARN 331634 --- [           main] com.example.demo.AnotherConfig           : init() org.apache.catalina.core.ApplicationContextFacade@299266e2
2020-12-18 22:17:02.842  INFO 331634 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2020-12-18 22:17:02.985  INFO 331634 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''

setServletContext is called correctly for AnotherConfig but never called for DemoConfig.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions