How to execute a gradle external task (Exec) in ba

2019-01-19 16:48发布

问题:

I'm using gradle and gulp to build and launch my JEE web application that is based on JDK6+, and the web container is Jetty.

Gulp is used to process static resource, such as concat and minify javascript/css files. Also, there is a watch task in my gulp script, it is used to watch static file changes and rebuild them automatically.

So to launch the application in Jetty, i need to do following things:

  1. Build static resource using gulp [gulp task: build].
  2. Watch static file changes [gulp task: watch], i don't call this gulp task directly, it is call by a gradle task via Exec class [gradle task: watch].
  3. Build my java code and launch Jetty [gradle task: jettyRun].

Since i added the gradle task watch as a dependency of jettyRun task, so i though i only need to call gradle jettyRun from command line, my application will be launched. But the result is not same as i expected.


Following is my script files:

build.gradle

apply plugin: 'war'
apply plugin: 'jetty'

repositories {
    jcenter()
}

// omit the dependencies here

task watch(type: Exec){
    workingDir "${projectDir}"
    // Pass build type to npm and gulp.
    commandLine "gulp", "watch"
}
jettyRun.dependsOn watch

gulpfile.js

var gulp = require('gulp');
gulp.task('build', function(callback) {
    // removed the code to make this question as simple as possible.
    if (callback != null) callback();
});

gulp.task('watch', function(callback) {
    gulp.watch(['./src/static/**/*.js'], ['build']);
    if (callback != null) callback();
});

The result:

Question:

Now, the process hungs when excutes the gradle watch task, there is no change to execute jettyRun task for gradle. I know this hang is caused by the watch process launched by gulp, because it is watching file changes. But i hope that gradle just only launch the gulp watch process and return immediately to execute the next jettyRun task!

How to do this? Also, i want to see the output of watch task from stdout.

I know there is a ProcessBuilder in java, i have tried it, but it doesn't work. Maybe I have done something wrong. :(

Download all files

回答1:

You can use ProcessBuilder to launch an external process in the background and let gradle continue with other tasks. Also finalizedBy can be used to stop watching when runJetty has been completed.

task watch {
    doFirst {
        println("Start watching")
        ext.process = new ProcessBuilder()
            .directory(projectDir)
            .command("gulp", "watch")
            .start()
    }
}

task stopWatching {
    doFirst {
        println("Stop watching")
        if (tasks.watch.process != null) {
            tasks.watch.process.destroy()
        }
    }
}

task runJetty {
    finalizedBy stopWatching
}