The great thing about Spring Boot is no need for an external servlet container. All that is needed reside inside a single runnable JAR file. In a very few steps, development of a new application can be started without installation or configuration of any additional software.
Yet, sometimes you might want to deploy your application to some server as a regular WAR file. For instance, you convert an existing application and want to keep your continuous delivery pipe untouched or a particular container is enforced by a company’s policy. The reason for building a WAR file may vary across teams, but for development purpose a simple executable JAR file with an embedded server might be preferable.
Advertisement
Before you even consider dual compilation to achieve executable JAR and deployable WAR you should be aware of another option. In this case, Spring Boot allows you to have your cake and eat it too. You can accomplish a similar result with one build in three easy steps.
<packaging>war</packaging>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency>
@SpringBootApplication public class ApplicationRunner extends SpringBootServletInitializer { public static void main(String[] args) { SpringApplication.run(ApplicationRunner.class, args); } @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { return builder.sources(ApplicationRunner.class); } }
Now, if you run the Maven build your application will be built as a WAR file, which can be easily deployed on any servlet container. Since you marked the embedded Tomcat dependency as provided you probably expect it isn’t packed inside the archive, but the reality is different. All dependencies related to Tomcat are placed in a WEB-INF/lib-provided directory inside the WAR. Thanks to that, these jars aren’t added to the classpath when the application is deployed in a container, but since they are packed inside, Spring Boot can use them to run the application just like a regular JAR file.
But what if you don’t want the extra Tomcat dependencies in your WAR file to make it less heavy? Actually, these libraries are required only for the development phase. To achieve such a goal you can create two separate build profiles. The first one will create a simple executable JAR file, and the second will be responsible for packaging the application into a releasable WAR file.
<packaging>${project.packaging}</packaging>
<profiles> <profile> <id>dev</id> <activation> <activeByDefault>true</activeByDefault> </activation> <properties> <project.packaging>jar</project.packaging> </properties> </profile> </profiles>
<profile> <id>release</id> <properties> <project.packaging>war</project.packaging> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <artifactId>spring-boot-starter-tomcat</artifactId> <groupId>org.springframework.boot</groupId> </exclusion> </exclusions> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> </dependencies> </profile>
What is actually going on here? The profile declares the packaging property as war. Next, the Tomcat dependencies are marked as excluded, this prevents the build from creating the lib-provided directory. However, without these dependencies your project won’t compile. That is why you have to declare another dependency on the servlet API specification. Since your servlet container that is going to be used for deployment definitely has its own copy of the jar you should mark the library as provided.
That is all. By default, your build runs with the dev profile without any additional configuration. If you want to create the release package, just activate the second profile that produces the non-executable WAR file. In case of any problem with the configuration, the whole pom.xml is available here.
Spring Boot allows us to create a deployable WAR file with two possible options. Single build for an executable WAR file is mentioned in the official documentation, which suggests it as a preferable method for the Spring Boot team to achieve the goal. If you’re ok with a few additional megabytes of libraries, that’s definitely the way to go. Especially when you follow the motto “Build once, deploy everywhere”. With the dual build approach a release package is lighter, but in exchange for its ability to execute. Nothing comes for free, yet for some teams a smaller deploy unit may be important. There is no better option, just make the decision based on your real needs.
Short answer: No.Fortunately, you can simulate them.Many programming languages like C++ or modern JavaScript have…
The JavaScript Promise is a concept that every modern self-respecting web developer should be familiar…
In short, a Spring bean is an object which Spring framework manages at runtime. A…
Have you ever wonder why singleton is the default scope for Spring beans? Why isn't…
Do you have multiple parameters annotated with @RequestParam in a request mapping method and feel…
Some teams prefer having a separate Maven build profile for each application runtime environment, like…