Search code examples
spring-bootspring-boot-starter

Is it possible to configure the spring boot server explicitly?


I've a Spring Boot application where one of the dependencies is using spring and a embedded jetty to start an ad-hoc web server. This causes my spring boot app to start in a jetty instead of a tomcat.

My spring-boot-starter-web:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
  <exclusions>
    <exclusion>
      <groupId>org.apache.tomcat.embed</groupId>
      <artifactId>tomcat-embed-websocket</artifactId>
    </exclusion>
  </exclusions>
</dependency>

The dependencies pom:

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-web</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.integration</groupId>
  <artifactId>spring-integration-http</artifactId>
</dependency>

<dependency>
  <groupId>org.apache.httpcomponents</groupId>
  <artifactId>httpclient</artifactId>
</dependency>

<dependency>
  <groupId>org.eclipse.jetty</groupId>
  <artifactId>jetty-server</artifactId>
</dependency>

<dependency>
  <groupId>org.eclipse.jetty</groupId>
  <artifactId>jetty-servlet</artifactId>
</dependency>

Is there a possibility to configure the server to use by spring boot explicitly instead of being inferred by the dependency tree?

EDIT

I investigated the issue a little bit further and created a repo to reproduce the issue: github.com/svettwer/spring-server-test
org.eclipse.jetty.websocket:javax-websocket-server-impl causes spring to start with jetty without any other config required.

EDIT 2

The issue is not present anymore in Spring Boot 2.x

EDIT 3 I'll deleted the repo mentioned earlier, but here is the dependency setup that caused the issue:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <version>1.5.7.RELEASE</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <version>1.5.7.RELEASE</version>
        <scope>test</scope>
    </dependency>

    <!-- Comment that in to start spring with jetty-->
    <dependency>
        <groupId>org.eclipse.jetty.websocket</groupId>
        <artifactId>javax-websocket-server-impl</artifactId>
        <version>9.4.8.v20171121</version>
    </dependency>

</dependencies>

Solution

  • Normally, if you have the spring-boot-starter-tomcat on your classpath (through spring-boot-starter-web), it should always select Tomcat since it has priority over other servlet containers. Even if you have the following dependencies, Spring boot will start with Tomcat:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>jetty-server</artifactId>
    </dependency>
    <dependency>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>jetty-webapp</artifactId>
    </dependency>
    <dependency>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>jetty-servlet</artifactId>
    </dependency>
    

    You can programmatically override the chosen servlet container by registering your own ServletWebServerFactory, for example:

    @Bean
    public ServletWebServerFactory factory() {
        return new TomcatServletWebServerFactory();
    }
    

    You can choose the predefined TomcatServletWebServerFactory, JettyServletWebServerFactory or the UndertowServletWebServerFactory.