Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lightweight deployable WAR for a Spring Boot Application

A simple Spring Boot application which just prints a "Hello World" when packaged as an deploy-able WAR is 11.5 MB. When I exploded the WAR, the web-inf/lib folder was the root cause having too many libraries.

  1. How to create the WAR with only the minimum necessary/dependent libraries ?
  2. While mentioning provided as scope for spring-boot-starter-tomcat , does the embedded Tomcat Server still get packaged along with the WAR ?

I was playing around with the 'gs-spring-boot-complete' project that comes with the Spring Test Suite (STS) and here is the default POM that came with it.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.springframework</groupId>
    <artifactId>gs-spring-boot</artifactId>
    <version>0.1.0</version>
    <!-- ... -->
    <packaging>war</packaging>
    <!-- ... -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.1.10.RELEASE</version>
    </parent>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>

        <!-- tag::actuator[] -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!-- end::actuator[] -->
        <!-- tag::tests[] -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- end::tests[] -->
    </dependencies>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <artifactId>maven-failsafe-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>integration-test</goal>
                            <goal>verify</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

Update: i removed the dependency on spring-boot-starter-tomcat and spring-boot-starter-actuator from the POM, still the WAR is 11.5 MB.

Currently there are only 2 direct dependencies spring-boot-starter-web & spring-boot-starter-test (i understand that this might in turn have other dependencies).

My question is that, even if I am not going to have an embedded Tomcat container, do "Spring Boot" applications generate such huge deploy-able WARs ? am trying to confirm if there is anything that could be done to have an optimized (i mean small sized) deploy-able WAR.

like image 685
yathirigan Avatar asked Feb 17 '15 15:02

yathirigan


2 Answers

If you have no interest in running your application as an executable war file and only want to deploy it to a servlet container then you can remove Spring Boot's Maven plugin and declare spring-boot-starter-tomcat as a provided dependency:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>example-app</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.2.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>       
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

Remove Spring Boot's Maven plugin will prevent provided dependencies from being packaging in your war file. Making spring-boot-starter-tomcat a provided dependency, rather than excluding it altogether, will allow you to run integration tests using embedded Tomcat.

This will give you a war file that's 7.6MB. Depending on your application and the technologies that you want to use, you may also want to consider excluding some of spring-boot-starter-web's transitive dependencies. For example, it's pulling in Hibernate Validator (> 0.5MB) and Jackson (> 1MB).

like image 153
Andy Wilkinson Avatar answered Sep 21 '22 01:09

Andy Wilkinson


The intention is to create a war/jar with all your dependencies included. What is the minimum you want to deploy?

Id suggest removing the tomcat and actuator dependency for a start - then recheck the size

like image 29
farrellmr Avatar answered Sep 18 '22 01:09

farrellmr