Be careful when using @Configuration classes with @EnableWebMvc in Spring Boot
Tags: springboot, spring
Published: 2023-04-26 08:21:43

### Situation

Recently, we have been faced with a strange issue after adding a configuration class to our Spring Boot application. Unfortunately, the logs didn't provide any valuable information, becuause we didn't use the bean in our new configuration class which mention in logs:

```log
Parameter 1 of constructor in com.xyz.spring.starter.web.filter.FilterAutoConfiguration required a bean of type 'org.springframework.web.filter.RequestContextFilter' that could not be found.
Action:
Consider defining a bean of type 'org.springframework.web.filter.RequestContextFilter' in your configuration
```

And our new configuration class looked like this: 

```java
@Configuration
@EnableWebMvc
public class WebConfiguration implements WebMvcConfigurer {
    // some simple logic
}
```

After playing with the configuration, we found out that using the **@EnableWebMvc** annotation breaks our project. So, let's go deeper into the Spring configuration to understand why this is happening.


### What is the @Configuration annotation?

The Spring Framework documentation says: the **@Configuration** annotation allows us to use annotations for dependency injection. This annotation tels Spring that a class has some methods which create beans that can be used in the application. When the Spring container detects this annotation, it process this class and create these beans.

Just an example of using the @Configuration annotation:

```java
@Configuration
public class AppConfig {

    @Bean
    public MyBean myBean() {
        // instantiate, configure and return bean ...
    }
}
```

### What is the @EnableWebMvc annotation?

The official documentation says:
Adding this annotation to an **@Configuration** class imports the Spring MVC configuration from **WebMvcConfigurationSupport**

```java
@Configuration
@EnableWebMvc
@ComponentScan(basePackageClasses = MyConfiguration.class)
public class MyConfiguration {
}
```

To customize the imported configuration, implement the interface **WebMvcConfigurer** and override individual methods, e.g.:

```java
@Configuration
@EnableWebMvc
@ComponentScan(basePackageClasses = MyConfiguration.class)
public class MyConfiguration implements WebMvcConfigurer {

    @Override
    public void addFormatters(FormatterRegistry formatterRegistry) {
        formatterRegistry.addConverter(new MyConverter());
    }

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(new MyHttpMessageConverter());
    }

}
```
And there is some very interresting point:

**Note:** only one **@Configuration** class may have the **@EnableWebMvc** annotation to import the Spring Web MVC configuration. There can however be multiple **@Configuration** classes implementing WebMvcConfigurer in order to customize the provided configuration.

#### In a nutshell

1. We can have **ONLY ONE @Configuration** class which annotated with the **@EnableWebMvc** annotation!

2. If we need more - we have to implement **WebMvcConfigurer**.

Keep in mind that this from the Spring Framework Documentation, not from Spring Boot!


### What is Spring MVC Auto-configuration?

The Spring Boot Documentation says: 

Spring Boot provides auto-configuration for Spring MVC that works well with **most applications**.

The auto-configuration adds the following features on top of Spring’s defaults:

- Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans.

- Support for serving static resources, including support for WebJars.

- Automatic registration of Converter, GenericConverter, and Formatter beans.

- Support for HttpMessageConverters.

- Automatic registration of MessageCodesResolver.

- Static index.html support.

- Automatic use of a ConfigurableWebBindingInitializer bean.

If you want to keep those Spring Boot MVC customizations and make more MVC customizations (interceptors, formatters, view controllers, and other features), you can add your own **@Configuration** class of type **WebMvcConfigurer** but **without @EnableWebMvc.**

If you want to take complete control of Spring MVC, you can add your own **@Configuration** annotated with **@EnableWebMvc**, or alternatively add your own **@Configuration**-annotated **DelegatingWebMvcConfiguration** as described in the Javadoc of **@EnableWebMvc**.

#### In a nutshell

1. You can create your own **@Configuration** which should implement **WebMvcConfigurer**. But, **do not include the @EnableWebMvc** annotation in this class.

2. You can use @Configuration class with the @EnableWebMvc annotation but you have to take complete control of Spring MVC and customize every aspect of its configuration and be aware that it can cause conflicts with Spring Boot's auto-configuration and make it harder to configure your application correctly.


### What does the Internet say?

Baeldung mention in the section [Migrate a Spring Web Application](https://www.baeldung.com/spring-boot-migration#migrate-a-spring-web-application) that:

- When we use `spring-boot-starter-web` dependency, Spring Boot automatically sets up a DispatcherServlet bean and adds the **@EnableWebMvc** annotation to the main Application class.

- If we use the **@EnableWebMvc** annotation in a **@Configuration** class, it will **disable** Spring Boot's auto-configuration for MVC.


Some guy from [Quora](https://www.quora.com/What-is-the-use-of-EnableWebMvc-in-Spring):

*Spring Boot doesn’t mix well with the standard Spring MVC @EnableWebMvc. What happens when you add the annotation is that spring boot auto-configuration is disabled.*

*Don’t use @EnableWebMvc in spring boot, just include spring-web as a maven/gradle dependency and it will be auto-configured.*


Comments from [Stackoverflow](https://stackoverflow.com/questions/51008382/why-spring-boot-application-doesnt-require-enablewebmvc)

*Normally you would add @EnableWebMvc for a Spring MVC app, but Spring Boot adds it automatically when it sees spring-webmvc on the classpath. This flags the application as a web application and activates key behaviors such as setting up a DispatcherServlet.*

*It is important to remember that 3rd point. Do not annotate any @Configuration classes with @EnableWebMvc. Otherwise, Spring MVC will load and use its own serialization/deserialization configuration, ignoring your Spring Boot config.*


### What you can do?

Avoid using @EnableWebMvc in spring boot, just use `spring-boot-starter-web` dependency and it will be auto-configured. If you need to use **@EnableWebMvc** annotation in a **@Configuration** be aware of the consequences.


### References:

- [Annotation Interface EnableWebMvc](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/servlet/config/annotation/EnableWebMvc.html)

- [Annotation Interface Configuration](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/Configuration.html)

- [Spring MVC Auto-configuration](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#web.servlet.spring-mvc.auto-configuration)

- [Spring Configuration Annotation](https://www.digitalocean.com/community/tutorials/spring-configuration-annotation)

- [What is the use of EnableWebMvc in Spring?](https://www.quora.com/What-is-the-use-of-EnableWebMvc-in-Spring)

- [why spring-boot application doesn't require EnableWebMvc](https://stackoverflow.com/questions/51008382/why-spring-boot-application-doesnt-require-enablewebmvc)

- [SPRING BOOT, ENABLEWEBMVC AND COMMON USE-CASES](https://techblog.bozho.net/spring-boot-enablewebmvc-common-use-cases/)

- [Migrate a Spring Web Application](https://www.baeldung.com/spring-boot-migration#1-web-starter)

Follow my [telegram channel](https://t.me/enterprise_developer)