How do I tell Spring Boot to ignore Jetty and always use Tomcat?

13,233

Solution 1

Boot's using Jetty as it's on the classpath. The attempt to exclude it by excluding EmbeddedServletContainerAutoConfiguration.EmbeddedJetty.class doesn't work as EmdeddedJetty isn't an auto-configuration class. EmbeddedServletContainerAutoConfiguration is an auto-configuration class and you could exclude it, but then you'd also lose embedded Tomcat support which I don't think is what you want. The easiest thing to do is to eliminate Jetty from your application's classpath.

The dependency tree output shows that you've still got transitive dependencies on org.eclipse.jetty:jetty-server and org.eclipse.jetty:jetty-webapp, both of which are being pulled in by your direct dependency on org.neo4j.app:neo4j-server. Update your pom to exclude them:

<dependency>
    <groupId>org.neo4j.app</groupId>
    <artifactId>neo4j-server</artifactId>
    <version>${neo4j.version}</version>
    <classifier>static-web</classifier>
    <exclusions>
        <exclusion>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
        </exclusion>
        <exclusion>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-access</artifactId>
        </exclusion>
        <exclusion>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
        </exclusion>
        <exclusion>
            <artifactId>javax.servlet</artifactId>
            <groupId>org.eclipse.jetty.orbit</groupId>
        </exclusion>
        <exclusion>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-server</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-webapp</artifactId>
        </exclusion>
    </exclusions>
</dependency>

Update: if excluding Jetty from the dependencies isn't an option, then you can declare your own TomcatEmbeddedServletContainerFactory bean:

@Bean
public TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() {
    return new TomcatEmbeddedServletContainerFactory();
}

This will prevent the auto-configuration of the embedded Jetty server as it's conditional on there being no EmbeddedServletContainerFactory bean in the application context.

Solution 2

You could also import the EmbeddedTomcat configuration directly. Has the same effect as declaring TomcatEmbeddedServletContainerFactory directly and should there be any change with it you won't need to update anything.

@SpringBootApplication
@Import(EmbeddedServletContainerAutoConfiguration.EmbeddedTomcat.class)
... your configuration class
Share:
13,233
MarSik
Author by

MarSik

Updated on June 08, 2022

Comments

  • MarSik
    MarSik about 2 years

    I have the following setup:

    spring-boot application (using embedded tomcat)
    spring-date-neo4j (embedded mode)
    spring-websockets
    

    and neo4j-browser included using (the goal is to be able to use REST and web browser to debug embedded database):

        <dependency>
            <groupId>org.neo4j.app</groupId>
            <artifactId>neo4j-server</artifactId>
            <version>${neo4j.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>ch.qos.logback</groupId>
                    <artifactId>logback-classic</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>ch.qos.logback</groupId>
                    <artifactId>logback-access</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>javax.servlet</groupId>
                    <artifactId>javax.servlet-api</artifactId>
                </exclusion>
                <exclusion>
                    <artifactId>javax.servlet</artifactId>
                    <groupId>org.eclipse.jetty.orbit</groupId>
                </exclusion>
            </exclusions>
        </dependency>
    
        <dependency>
            <groupId>org.neo4j.app</groupId>
            <artifactId>neo4j-server</artifactId>
            <version>${neo4j.version}</version>
            <classifier>static-web</classifier>
            <exclusions>
                <exclusion>
                    <groupId>ch.qos.logback</groupId>
                    <artifactId>logback-classic</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>ch.qos.logback</groupId>
                    <artifactId>logback-access</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>javax.servlet</groupId>
                    <artifactId>javax.servlet-api</artifactId>
                </exclusion>
                <exclusion>
                    <artifactId>javax.servlet</artifactId>
                    <groupId>org.eclipse.jetty.orbit</groupId>
                </exclusion>
            </exclusions>
        </dependency>
    

    And started using:

    @Autowired
    @Bean(destroyMethod = "shutdown")
    public GraphDatabaseService graphDatabaseService(DatabaseConfiguration dbConf) {
        // removed with every maven clear
        return new GraphDatabaseFactory().newEmbeddedDatabase(dbConf.getDbPath());
    
        // stays after clear
        //return new EmbeddedGraphDatabase("./data/neo4j.db");
    }
    
    @Bean(destroyMethod = "stop")
    public WrappingNeoServerBootstrapper serverWrapper(GraphDatabaseService db) {
        WrappingNeoServerBootstrapper wrapper = new WrappingNeoServerBootstrapper((GraphDatabaseAPI)db);
        wrapper.start();
        return wrapper;
    }
    

    And spring boot is insisting on trying Jetty as the servlet container even with the following config annotations for the main app class:

    @EnableAutoConfiguration(exclude = EmbeddedServletContainerAutoConfiguration.EmbeddedJetty.class)
    @ComponentScan
    @EnableWebMvc
    @Configuration
    public class WebApplication extends WebMvcConfigurerAdapter {
    

    But the jetty version Spring uses (8) does not support web sockets so I am getting

    Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean
    with name 'jettyEmbeddedServletContainerFactory' defined in class path resource 
    [org/springframework/boot/autoconfigure/web/EmbeddedServletContainerAutoConfiguration$EmbeddedJetty.class]:
    Initialization of bean failed; nested exception is java.lang.IllegalStateException:
    Websockets are currently only supported in Tomcat (found class org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainerFactory).
    

    How do I tell Spring Boot to ignore Jetty and always use Tomcat?

    The dependency tree:

    [INFO] Building webapp 1.0
    [INFO] ------------------------------------------------------------------------
    [INFO] 
    [INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ webapp ---
    [INFO] webapp:war:1.0
    [INFO] +- common:jar:1.0:compile
    [INFO] |  +- javax.validation:validation-api:jar:1.1.0.Final:compile
    [INFO] |  +- org.springframework.data:spring-data-neo4j:jar:3.1.0.RELEASE:compile
    [INFO] |  |  +- org.aspectj:aspectjrt:jar:1.7.4:compile
    [INFO] |  |  +- org.springframework.data:spring-data-commons:jar:1.8.0.RELEASE:compile
    [INFO] |  |  +- org.neo4j:neo4j-cypher-dsl:jar:2.0.1:compile
    [INFO] |  |  +- org.neo4j:neo4j:jar:2.0.3:compile
    [INFO] |  |  +- org.slf4j:slf4j-api:jar:1.7.7:compile
    [INFO] |  |  \- org.slf4j:jcl-over-slf4j:jar:1.7.7:compile
    [INFO] |  +- commons-codec:commons-codec:jar:1.9:compile
    [INFO] |  +- org.apache.poi:poi:jar:3.10-FINAL:compile
    [INFO] |  +- org.apache.poi:poi-scratchpad:jar:3.10-FINAL:compile
    [INFO] |  +- com.fasterxml.jackson.core:jackson-annotations:jar:2.3.3:compile
    [INFO] |  \- com.fasterxml.jackson.core:jackson-databind:jar:2.3.3:compile
    [INFO] |     \- com.fasterxml.jackson.core:jackson-core:jar:2.3.3:compile
    [INFO] +- org.springframework.boot:spring-boot-starter-web:jar:1.0.2.RELEASE:compile
    [INFO] |  +- org.springframework.boot:spring-boot-starter:jar:1.0.2.RELEASE:compile
    [INFO] |  |  +- org.springframework.boot:spring-boot:jar:1.0.2.RELEASE:compile
    [INFO] |  |  +- org.springframework.boot:spring-boot-autoconfigure:jar:1.0.2.RELEASE:compile
    [INFO] |  |  +- org.springframework.boot:spring-boot-starter-logging:jar:1.0.2.RELEASE:compile
    [INFO] |  |  |  +- org.slf4j:jul-to-slf4j:jar:1.7.7:compile
    [INFO] |  |  |  +- org.slf4j:log4j-over-slf4j:jar:1.7.7:compile
    [INFO] |  |  |  \- ch.qos.logback:logback-classic:jar:1.1.2:compile
    [INFO] |  |  |     \- ch.qos.logback:logback-core:jar:1.1.2:compile
    [INFO] |  |  \- org.yaml:snakeyaml:jar:1.13:runtime
    [INFO] |  \- org.springframework.boot:spring-boot-starter-tomcat:jar:1.0.2.RELEASE:compile
    [INFO] |     +- org.apache.tomcat.embed:tomcat-embed-el:jar:7.0.52:compile
    [INFO] |     \- org.apache.tomcat.embed:tomcat-embed-logging-juli:jar:7.0.52:compile
    [INFO] +- org.springframework:spring-core:jar:4.0.3.RELEASE:compile
    [INFO] +- org.springframework:spring-context:jar:4.0.3.RELEASE:compile
    [INFO] |  \- org.springframework:spring-expression:jar:4.0.3.RELEASE:compile
    [INFO] +- org.springframework:spring-beans:jar:4.0.3.RELEASE:compile
    [INFO] +- org.springframework.security:spring-security-web:jar:3.2.4.RELEASE:compile
    [INFO] |  +- aopalliance:aopalliance:jar:1.0:compile
    [INFO] |  \- org.springframework.security:spring-security-core:jar:3.2.3.RELEASE:compile
    [INFO] +- org.springframework.security:spring-security-config:jar:3.2.4.RELEASE:compile
    [INFO] +- org.springframework.security:spring-security-taglibs:jar:3.2.4.RELEASE:compile
    [INFO] |  \- org.springframework.security:spring-security-acl:jar:3.2.3.RELEASE:compile
    [INFO] |     \- org.springframework:spring-jdbc:jar:4.0.3.RELEASE:compile
    [INFO] +- org.springframework:spring-webmvc:jar:4.0.3.RELEASE:compile
    [INFO] +- org.springframework:spring-web:jar:4.0.3.RELEASE:compile
    [INFO] +- org.springframework:spring-websocket:jar:4.0.3.RELEASE:compile
    [INFO] +- org.springframework:spring-messaging:jar:4.0.3.RELEASE:compile
    [INFO] +- org.apache.tomcat.embed:tomcat-embed-websocket:jar:7.0.52:compile
    [INFO] |  \- org.apache.tomcat.embed:tomcat-embed-core:jar:7.0.52:compile
    [INFO] +- org.freemarker:freemarker:jar:2.3.20:compile
    [INFO] +- org.springframework:spring-context-support:jar:4.0.3.RELEASE:compile
    [INFO] +- net.glxn:qrgen:jar:1.4:compile
    [INFO] |  \- com.google.zxing:javase:jar:3.0.0:compile
    [INFO] |     \- com.google.zxing:core:jar:3.0.0:compile
    [INFO] +- org.springframework:spring-tx:jar:4.0.3.RELEASE:compile
    [INFO] +- org.springframework:spring-aop:jar:4.0.3.RELEASE:compile
    [INFO] +- org.springframework:spring-aspects:jar:4.0.3.RELEASE:compile
    [INFO] |  \- org.aspectj:aspectjweaver:jar:1.7.4:compile
    [INFO] +- org.hibernate:hibernate-validator:jar:5.1.1.Final:compile
    [INFO] |  +- org.jboss.logging:jboss-logging:jar:3.1.3.GA:compile
    [INFO] |  \- com.fasterxml:classmate:jar:1.0.0:compile
    [INFO] +- javax.el:javax.el-api:jar:2.2.4:compile
    [INFO] +- org.glassfish.web:javax.el:jar:2.2.4:compile
    [INFO] +- org.apache.commons:commons-lang3:jar:3.3.2:compile
    [INFO] +- commons-io:commons-io:jar:2.4:compile
    [INFO] +- commons-fileupload:commons-fileupload:jar:1.3.1:compile
    [INFO] +- org.jsoup:jsoup:jar:1.7.3:compile
    [INFO] +- com.sun.jersey:jersey-server:jar:1.18:compile
    [INFO] |  +- asm:asm:jar:3.1:compile
    [INFO] |  \- com.sun.jersey:jersey-core:jar:1.18:compile
    [INFO] +- com.sun.jersey:jersey-servlet:jar:1.18:compile
    [INFO] +- org.neo4j.app:neo4j-server:jar:2.0.3:compile
    [INFO] |  +- org.neo4j:neo4j:pom:2.0.3:compile
    [INFO] |  |  +- org.neo4j:neo4j-lucene-index:jar:2.0.3:compile
    [INFO] |  |  |  \- org.apache.lucene:lucene-core:jar:3.6.2:compile
    [INFO] |  |  +- org.neo4j:neo4j-graph-algo:jar:2.0.3:compile
    [INFO] |  |  +- org.neo4j:neo4j-udc:jar:2.0.3:compile
    [INFO] |  |  +- org.neo4j:neo4j-graph-matching:jar:2.0.3:compile
    [INFO] |  |  \- org.neo4j:neo4j-jmx:jar:2.0.3:compile
    [INFO] |  +- org.neo4j:neo4j-kernel:jar:2.0.3:compile
    [INFO] |  |  \- org.apache.geronimo.specs:geronimo-jta_1.1_spec:jar:1.1.1:compile
    [INFO] |  +- org.neo4j:server-api:jar:2.0.3:compile
    [INFO] |  |  \- org.neo4j.3rdparty.javax.ws.rs:jsr311-api:jar:1.1.2.r612:compile
    [INFO] |  +- org.neo4j:neo4j-cypher:jar:2.0.3:compile
    [INFO] |  |  +- org.neo4j:neo4j-cypher-commons:jar:2.0.3:compile
    [INFO] |  |  +- org.neo4j:neo4j-cypher-compiler-1.9:jar:2.0.3:compile
    [INFO] |  |  +- org.neo4j:neo4j-cypher-compiler-2.0:jar:2.0.3:compile
    [INFO] |  |  |  +- org.parboiled:parboiled-scala_2.10:jar:1.1.6:compile
    [INFO] |  |  |  |  \- org.parboiled:parboiled-core:jar:1.1.6:compile
    [INFO] |  |  |  \- net.sf.opencsv:opencsv:jar:2.0:compile
    [INFO] |  |  +- com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:jar:1.3.1:compile
    [INFO] |  |  \- org.scala-lang:scala-library:jar:2.10.3:compile
    [INFO] |  +- org.neo4j.app:neo4j-browser:jar:2.0.3:compile
    [INFO] |  +- org.codehaus.janino:janino:jar:2.6.1:compile
    [INFO] |  |  \- org.codehaus.janino:commons-compiler:jar:2.6.1:compile
    [INFO] |  +- org.eclipse.jetty:jetty-server:jar:9.0.5.v20130815:compile
    [INFO] |  |  +- org.eclipse.jetty:jetty-http:jar:9.0.5.v20130815:compile
    [INFO] |  |  \- org.eclipse.jetty:jetty-io:jar:9.0.5.v20130815:compile
    [INFO] |  +- org.eclipse.jetty:jetty-webapp:jar:8.1.14.v20131031:compile
    [INFO] |  |  +- org.eclipse.jetty:jetty-xml:jar:8.1.14.v20131031:compile
    [INFO] |  |  \- org.eclipse.jetty:jetty-servlet:jar:8.1.14.v20131031:compile
    [INFO] |  |     \- org.eclipse.jetty:jetty-security:jar:8.1.14.v20131031:compile
    [INFO] |  +- commons-configuration:commons-configuration:jar:1.6:compile
    [INFO] |  |  +- commons-collections:commons-collections:jar:3.2.1:compile
    [INFO] |  |  +- commons-lang:commons-lang:jar:2.4:compile
    [INFO] |  |  +- commons-logging:commons-logging:jar:1.1.1:compile
    [INFO] |  |  \- commons-beanutils:commons-beanutils-core:jar:1.8.0:compile
    [INFO] |  +- commons-digester:commons-digester:jar:1.8.1:compile
    [INFO] |  |  \- commons-beanutils:commons-beanutils:jar:1.8.0:compile
    [INFO] |  +- org.codehaus.jackson:jackson-jaxrs:jar:1.9.7:compile
    [INFO] |  |  +- org.codehaus.jackson:jackson-core-asl:jar:1.9.7:compile
    [INFO] |  |  \- org.codehaus.jackson:jackson-mapper-asl:jar:1.9.7:compile
    [INFO] |  +- org.rrd4j:rrd4j:jar:2.0.7:compile
    [INFO] |  +- org.mozilla:rhino:jar:1.7R4:compile
    [INFO] |  +- bouncycastle:bcprov-jdk16:jar:140:compile
    [INFO] |  +- com.sun.jersey.contribs:jersey-multipart:jar:1.9:compile
    [INFO] |  |  \- org.jvnet:mimepull:jar:1.6:compile
    [INFO] |  \- org.neo4j:neo4j-shell:jar:2.0.3:compile
    [INFO] |     \- org.apache.servicemix.bundles:org.apache.servicemix.bundles.jline:jar:0.9.94_1:compile
    [INFO] +- org.neo4j.app:neo4j-server:jar:static-web:2.0.3:compile
    [INFO] +- org.eclipse.jetty:jetty-util:jar:9.0.7.v20131107:compile
    [INFO] +- com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer:jar:r239:compile
    [INFO] |  +- com.google.guava:guava:jar:17.0:compile (version selected from constraint [11.0,))
    [INFO] |  \- com.google.code.findbugs:jsr305:jar:3.0.0:compile (version selected from constraint [1.3.9,))
    [INFO] +- junit:junit:jar:4.11:test
    [INFO] |  \- org.hamcrest:hamcrest-core:jar:1.3:test
    [INFO] +- org.mockito:mockito-all:jar:1.9.5:test
    [INFO] +- org.springframework:spring-test:jar:4.0.3.RELEASE:test
    [INFO] +- org.mockito:mockito-core:jar:1.9.5:test
    [INFO] |  \- org.objenesis:objenesis:jar:1.0:test
    [INFO] \- org.hamcrest:hamcrest-library:jar:1.3:test
    
  • MarSik
    MarSik almost 10 years
    Except that is exactly what I can't do, because neo4j-server starts an embedded Jetty server.
  • Andy Wilkinson
    Andy Wilkinson almost 10 years
    That wasn't clear to me from your question. I've updated my answer with an alternative approach.
  • mrlem
    mrlem over 9 years
    Thanks Andy, that's a life saver: I had that same problem with a conflict between activemq-http's jetty and spring-boot-starter-web :)