29

I'm writing a Spring Boot application that uses one of several @Configuration classes depending on which @Profile is set in the application.propertiesfile.

One of those Configuration classes uses a REST interface, and therefore I'm including spring-boot-starter-web as a dependency.

This starts up an embedded Tomcat instance, which is fine.

The problem is, the other profiles don't need an embedded server (e.g. I'm using JMS to handle incoming messages instead of REST).

Is there any way to stop the @SpringBootApplication from starting up Tomcat by default, and only using it for the REST Configuration class? E.g., by annotating that class with @EnableWebMVC

Here's an example of my @Configurationclasses:

REST:

@Profile({"REST"})
@Configuration
@EnableWebMvc
public class HttpConfiguration{
 .
 .
 .
}

JMS:

@Profile({"JMS"})
@Configuration
@EnableJms
public class JMSConfiguration{
 .
 .
 .
}

Thanks

barcom
  • 559
  • 1
  • 4
  • 15
  • 3
    Try `@SpringBootApplication(exclude={EmbeddedServletContainerFactory.class})` for the JMS profile. This should exclude auto configuration of Embedded Servlet container – Ori Dar Aug 18 '15 at 16:59

3 Answers3

40

Use

@SpringBootApplication(exclude = {EmbeddedServletContainerAutoConfiguration.class, 
                                  WebMvcAutoConfiguration.class})

to exclude Spring Boot's auto-configuration for embedded servlet containers. Additionally, you need to set the following property for the non-REST cases, so that Spring Boot won't try to start a WebApplicationContext (which needs a servlet container):

spring.main.web-environment=false

Then enable the embedded Tomcat in your REST profile by importing EmbeddedServletContainerAutoConfiguration.class (this delays the autoconfiguration until after the REST profile has been loaded:

@Profile({"REST"})
@Configuration
@Import(EmbeddedServletContainerAutoConfiguration.class)
public class HttpConfiguration {
    // ...
}

If you are using any EmbeddedServletContainerCustomizers, you also need to import EmbeddedServletContainerCustomizerBeanPostProcessorRegistrar.class.

barcom
  • 559
  • 1
  • 4
  • 15
hzpz
  • 7,536
  • 1
  • 38
  • 44
  • Thanks, this definitely looks like the right track. Seeing this exception now: Exception in thread "main" `org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean. at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:133) at org.springframework.context.support.AbstractApplicationContext.refresh` – barcom Aug 19 '15 at 10:38
  • One other issue I had was that when using `@Import(EmbeddedTomcat.class)` the server.port property was ignored, and I was stuck on port 8080. I managed to overcome that by swapping the import to `@Import(EmbeddedServletContainerAutoConfiguration.class)` at that point, so it didn't attempt the autoconfiguration until after the relevant `@Configuration` class was loaded. – barcom Aug 20 '15 at 09:17
  • Fore reference I preferred to use this annotation to exclude auto configurations : `@EnableAutoConfiguration(exclude = { ... })` – bric3 Aug 11 '17 at 13:29
  • 1
    spring.main.web-environment , deprecated in springBoot 2.1.8.RELEASE – Hamedz Sep 30 '19 at 16:44
33

As of Spring Boot 2.0 only spring.main.web-application-type=none in the relevant profile do the trick.

If you use a multi-document application.yml with Spring Boot 2.0, adding this block and replacing no-web-profile-name with the profile that shouldn't have an embedded web server should work:

---
spring:
  profiles: no-web-profile-name
  main:
    web-application-type: none
chipwilson
  • 160
  • 2
  • 9
frno
  • 2,641
  • 2
  • 18
  • 19
21

The answers from @hzpz and @orid set me on the right track.

I needed to add

@SpringBootApplication(exclude = {EmbeddedServletContainerAutoConfiguration.class, 
WebMvcAutoConfiguration.class})

and set:

spring.main.web-environment=false

in my application.properties file for the non-Rest cases.

barcom
  • 559
  • 1
  • 4
  • 15
  • 3
    Glad I could help and thanks for the credit! However, your answer would have been better as an edit to my answer, since my answer was obviously missing some crucial parts. I did the edit myself to make it a proper answer to your problem. – hzpz Aug 19 '15 at 13:30
  • @hzpz Sorry, didn't realise I could edit someone else's comment. Thanks for the help. – barcom Aug 20 '15 at 09:20