How to build a WAR file with gradle?

Viewed 51779

I want to build a WAR file (and then deploy it to Tomcat). So, as an exercise, I've started a new Spring Boot Project using Gradle in IDEA IntelliJ. Afterwards, I've apply the plugin in the build.gradle file, like this apply plugin: 'war' .

The problem is that when I try to run gradle war in the terminal, I get no war file! The only thing that happens is that it will generate a \build with 3 subsolders classes, resources and tmp, but there's no WAR in these.

What should I do to get a WAR file? I've watched this video, but this guy uses Maven and doesn't do advanced stuff and gets the war. I think there's got to be a way to keep it simple.

When I run gradle war --info

Initialized native services in: C:\Users\...\.gradle\native The client 

...

Task :compileJava UP-TO-DATE Resolving global dependency management for project 'deleteme' Excluding [org.apache.tomcat:tomcat-annotations-api] Excluding [] Skipping task ':compileJava' as it is up-to-date. :compileJava (Thread[Task worker for ':',5,main]) completed. Took 0.753 secs. :processResources (Thread[Task worker for ':',5,main]) started.

Task :processResources UP-TO-DATE Skipping task ':processResources' as it is up-to-date. :processResources (Thread[Task worker for ':',5,main]) completed. Took 0.003 secs. :classes (Thread[Task worker for ':',5,main]) started.

Task :classes UP-TO-DATE Skipping task ':classes' as it has no actions. :classes (Thread[Task worker for ':',5,main]) completed. Took 0.0 secs. :war (Thread[Task worker for ':',5,main]) started.

Task :war SKIPPED Skipping task ':war' as task onlyIf is false. :war (Thread[Task worker for ':',5,main]) completed. Took 0.0 secs.

5 Answers

I guess that you have applied the spring boot gradle plugin to your project, in addition to the war plugin ? then this behaviour is normal, since the Spring Boot plugin will disable jar and war tasks and replace these with bootWar and bootJar tasks .

With both spring boot and war plugin applied:

./gradlew war
15:35:09: Executing task 'war'...

> Task :compileJava UP-TO-DATE
> Task :processResources UP-TO-DATE
> Task :classes UP-TO-DATE
> Task :war SKIPPED

BUILD SUCCESSFUL in 0s
2 actionable tasks: 2 up-to-date
15:35:10: Task execution finished 'war'.

Note the SKIPPED message

$ ./gradlew bootWar
15:36:35: Executing task 'bootWar'...

> Task :compileJava UP-TO-DATE
> Task :processResources UP-TO-DATE
> Task :classes UP-TO-DATE
> Task :bootWar

BUILD SUCCESSFUL in 1s
3 actionable tasks: 1 executed, 2 up-to-date
15:36:37: Task execution finished 'bootWar'.

Then you will get the expected war file under build/libs.

You can still re-enable the standard jar/war tasks as explained here : https://docs.spring.io/spring-boot/docs/current/gradle-plugin/reference/html/#packaging-executable-wars-deployable (if you need to produce normal archives and not executable archives)

Regarding the Tomcat issue: install Tomcat 8.5.

As rightly said by @M.Ricciuti, the spring boot gradle plugin will disable the jar/war tasks and would only work with bootJar/bootWar tasks. But if you still want your project to be packaged with jar/war tasks just add the below to your build.gradle file

war {
    enabled=true
}

This would enable the gradle war command to generate the war for your project.

Please read: https://docs.gradle.org/current/userguide/war_plugin.html

If using Gradle with IntelliJ, goto build.gradle (or build.gradle.kts for Kotlin) and add

id 'war'

(or just

war

for Kotlin ) under Plugins

Reload Gradle Project and then use gradlew bootWar on the Intellij Terminal.

Add --info or --stackTrace for debugging

I was also facing the same issue.

After a lot of struggle, I figured out that I needed to extend SpringBootServletInitializer in my application. So my effective code looks like

    public class SyncApplication extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(SyncApplication.class);
    }

    public static void main(String[] args) {
        SpringApplication.run(SyncApplication.class, args);
    }

}

Looks like this SpringBootServletInitializer directs war plugins generate bootstrapping code while building the war, and thus spring context is initialized while deploying the app.

If you are using spring boot with gradle, you should follow the steps below:

  1. Edit your build.gradle file adding apply plugin:'war' and then rebuild gradle.

  2. With gradle built two (2) files will be created on your root directory: gradlew (for Linux) and gradlew.bat (for windows)

Open your terminal on your current project and run ./gradlew war

Your project will build and generate a .war file in build/libs/

Related