30

Is there a way to have a single Spring Boot project be packagable into both JAR and WAR without changing the pom.xml or the application source?

I've read Converting a Spring Boot JAR Application to a WAR, but it converts the project to WAR and it loses the ability to be packaged as JAR.

I don't expect mvn package to do both. What I want is something like mvn i-want-a-jar and it would package the project as JAR. Or I could run mvn i-want-a-war and it would package the project as WAR.

Is this possible?

imgx64
  • 4,062
  • 5
  • 28
  • 44

3 Answers3

43

I managed to do it by adding

<packaging>${packaging.type}</packaging>

to the POM file and then setting different profiles for JAR and WAR:

  <profiles>
    <profile>
      <id>jar</id>
      <properties>
        <packaging.type>jar</packaging.type>
      </properties>
    </profile>
    <profile>
      <id>war</id>
      <properties>
        <packaging.type>war</packaging.type>
      </properties>
      <dependencies>
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-tomcat</artifactId>
          <scope>provided</scope>
        </dependency>
      </dependencies>
    </profile>
  </profiles>

Now mvn package -P war produces a WAR and mvn package -P jar produces a JAR.

Another option is to create separate modules for JAR and WAR, but I didn't go that route.

imgx64
  • 4,062
  • 5
  • 28
  • 44
18

What's wrong with a WAR file that's executable? Isn't that what you really need?

P.S. like
java -jar name.war

Paul Verest
  • 60,022
  • 51
  • 208
  • 332
Dave Syer
  • 56,583
  • 10
  • 155
  • 143
  • 1
    How do I execute a Spring Boot WAR file with `java -jar name.war`? When I try it with the Hello World example I get `java.lang.NoClassDefFoundError: hello/Application` – imgx64 May 27 '14 at 05:26
  • 2
    Never mind that, looks like I forgot to include `spring-boot-maven-plugin`. `java -jar name.war` worked after I included it. – imgx64 May 27 '14 at 05:49
5

We've recently had a similar requirement, where an existing Spring Boot based project that was originally packaged as an executable Jar needed to support Tomcat and WildFly deployments.

Due to some dependencies used in this project (for example WebJars), a simple switch to WAR package wasn't an option since some of those dependencies were required for WildFly (VFS support) but not for other deployment.

The solution was to restructure the project modules in a way that core module contained the actual project but without having Spring Boot’s plugin applied, while several package modules would depend on core module and configure deployment artifact specifics (Boot and other plugins, deployment specific dependencies etc.).

That way project build was able to generate multiple deployment artifacts (Boot's executable JAR, traditional WAR and WildFly specific WAR) in a single build run.

In case anyone finds this useful, the sample project to demonstrate the approach is available on Github. The project can be built by either Gradle or Maven.

Vedran Pavic
  • 2,339
  • 2
  • 27
  • 31
  • This is what I am looking for but my project is maven based. I need your help for this in maven based structure. Can You please update your Github repo for maven based projects. – Mubasher Mar 09 '18 at 07:22
  • Thanks for the suggestion. I've updated the project to also include support for Maven build. – Vedran Pavic Mar 11 '18 at 12:40
  • Thanks, By the way on side note: Is not this can be achieved by profiles of maven? – Mubasher Mar 12 '18 at 06:33
  • 3
    I'm not a fan of that solution - if I'm building a product that needs to support multiple deployment environments, I'd like to have all artifacts produced by a single build run. From a CI or release build standpoint, it's also preferable to have a single build. – Vedran Pavic Mar 12 '18 at 07:11