0

I just generated a WAR packaging app with spring boot initializer and here are the generated sources.

Main application class

@SpringBootApplication
public class ChargingListenerApplication {

  public static void main(String[] args) {
    SpringApplication.run(ChargingListenerApplication.class, args);
  }

}

the servlet initializer class.

public class ServletInitializer extends SpringBootServletInitializer {

  @Override
  protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
    return application.sources(ChargingListenerApplication.class);
  }

}

How does Spring realize this class and run configure()? Is this just because of the type? If so isn't this a bit weird to handle like this, instead of a proper annotation? Plus, in Spring documentation they extend SpringBootServletInitializer in the main class.

João Dias
  • 16,277
  • 6
  • 33
  • 45
Olgun Kaya
  • 2,519
  • 4
  • 32
  • 46

2 Answers2

1

Yes, it is because you are extending SpringBootServletInitializer. It makes use of Spring Framework’s servlet 3.0 support and lets you configure your application when it is launched by the servlet container, which means your custom ServletInitializer.configure() will actually be called.

And yes, in Spring documentation they extend SpringBootServletInitializer in the main class, but that does not mean that you can't also place it someplace else. The only weird thing is that they do recommend one thing (extending it in the main class) but the initializer does another (creating a separate class), but maybe it is on purpose for clarity reasons.

João Dias
  • 16,277
  • 6
  • 33
  • 45
  • Thanks for the explanation. I would still expect from spring guys invent a new annotation. Considering how they manage all other auto configuration stuff. – Olgun Kaya Nov 10 '21 at 12:44
  • It might be that the Servlet 3.0 API does not make it possible to rely on annotations. `SpringBootServletInitializer` implements `WebApplicationInitializer` (which you can find in https://github.com/spring-projects/spring-framework/blob/main/spring-web/src/main/java/org/springframework/web/WebApplicationInitializer.java or https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/WebApplicationInitializer.html). Right at the top it reads "Interface to be implemented in Servlet 3.0+ environments in order to configure the ServletContext programmatically". – João Dias Nov 10 '21 at 12:51
  • Yeah I saw that too, still trying to find where exactly spring starts to manipulate the ServletContext. I mean how does it recognize this class (a full package scan or something else) ? I would be fully ok if at some point these spring classes extends jee classes. – Olgun Kaya Nov 10 '21 at 13:09
  • Although I accept Joao Dias's answer as correct, below one can see the whole flow that spring servlet support implements. – Olgun Kaya Nov 10 '21 at 13:27
1

So first of all, Spring-web module has a class SpringServletContainerInitializer which has the definition as below.

@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {...}

For the Annotation HandlesTypes,

The classes in which a ServletContainerInitializer has expressed interest. If an implementation of ServletContainerInitializer specifies this annotation, the Servlet container must pass the Set of application classes that extend, implement, or have been annotated with the class types listed by this annotation to the ServletContainerInitializer.onStartup(java.util.Set>, javax.servlet.ServletContext) method of the ServletContainerInitializer (if no matching classes are found, null must be passed instead)

@Target(value=TYPE)
@Retention(value=RUNTIME)
public @interface HandlesTypes {..}

ServletContainerInitializer is servlet interface that a container runs all of it's implementations during the startup (ofc implementations must be registered via META-INF/services/javax.servlet.ServletContainerInitializer )

So, spring checks in registered SpringServletContainerInitializer class for types passed to the it via container and runs their onStartup methods respectively.

Olgun Kaya
  • 2,519
  • 4
  • 32
  • 46