0

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>

2 Answers2

0

This guide may help you: https://docs.spring.io/spring-boot/docs/current/reference/html/howto-embedded-web-servers.html

If you run an mvn dependency:tree and search for jetty you might find that you need to exclude it, e.g:

spring-boot-starter-jetty

excluded like in the example:

    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <!-- Exclude the Tomcat dependency -->
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<!-- Use Jetty instead -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jetty</artifactId>
</dependency>

which is favouring jetty over tomcat - but you get the idea hopefully...

Hope this helps.

David
  • 7,652
  • 21
  • 60
  • 98
  • Excluding `org.eclipse.jetty:jetty-server` would start my application in a tomcat, you're right. But as I want to make use of the dependencies ad-hoc server capabilities, the jetty-server is required as well. So both dependencies have to stay for my software to work. – Sven Hettwer May 24 '18 at 10:23
  • org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration might help you (spring boot 2.x). Perhaps if you look at the imports at the top (@Import annotation) you'll see they import embedded configs that internally have conditional on missing bean annotations so you might be able to define you own beans to take over configuration perhaps. I think it would seem that tomcat should be favoured over jetty when both are present which is why the example excluded tomcat when jetty is included. How are you determining that jetty is being used over tomcat at runtime? – David May 24 '18 at 10:51
  • Thx for the hint! I'll try this. `How are you determining that jetty is being used over tomcat at runtime?` I investigated the issue a little bit further and created a repo to reproduce the issue: https://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. – Sven Hettwer May 24 '18 at 11:50
  • Please see Edit 3. It is only a spring boot < 2.x issue. Therefore the it is outdated. Nevertheless, you'll find the dependencies to reproduce attached to the question. – Sven Hettwer May 24 '18 at 12:32
0

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.

g00glen00b
  • 41,995
  • 13
  • 95
  • 133