Using cargo, ensuring war has been built

Hi,

I’m a new gradle user, started eagerly by quick-reading the book Gradle effective implementation guide and then trying to convert my rather complex multi module project from maven.

It has gone fairly well, compilation, tests and packaging all works fine. I’ve done som fair copying from Spring and Hibernate setups. They are a really good help.

The one thing I’m missing from maven is the way maven can recognize that a build-step is missing. For example, if I run:

mvn jetty:run

it automatically runs the goal war:war if needed.

I’d like to simulate this behavior in gradle (if possible). I’m using Cargo (works superb, even downloading the specified version of Jetty).

I’ve managed this by creating a couple of tasks like this (initLogDir is a custom task that ensures that jetty logdir exists):

project('server').cargoRunLocal.dependsOn(initLogDir)
  task aprepareserver(dependsOn:
        [':server:war', ':server:initLogDir']
        ) << {
    println "preparing server"
}
  task runserver(dependsOn: ['aprepareserver', ':server:cargoRunLocal']) << {
    println "running server"
}

Notice that I had to create the task ‘aprepareserver’ that alphabetically comes before cargoRunLocal just to make this work. This (ugly) construction enables me and my fellow (non gradle converts) to start the server by running:

gradle runserver

Is there a more elegant way of doing this?

thanks

Emil

The one thing I’m missing from maven is the way maven can recognize that a build-step is missing.

How is this different from adding a task dependency in Gradle (which, by the way, can often be inferred automatically)?

Is there a more elegant way of doing this?

Gradle doesn’t (yet) have anything similar to Ant’s soft dependencies. In other words, in Gradle ‘foo.dependsOn(bar, baz)’ is just a shorthand for ‘foo.dependsOn(bar); foo.dependsOn(baz)’, whereas in Ant is also means “if possible, run bar before baz”. However, in many cases soft dependencies aren’t really needed, and you can just add a hard dependency (e.g. ‘baz.dependsOn(bar)’) to achieve the desired task order. Is this feasible in your case?

Yes, adding a task dependency was my first thought and it would normally be enough. The core of the problem was really that I couldn’t add a task dependency to :server:cargoRunLocal. Gradle complained about not finding the task or property cargoRunLocal.

I asked Benjamin Muschko (the maintainer of the gradle-cargo-plugin) and he explained it for me:

This is a known issue with the plugin that I want to fix asap. You are not the only one reporting this issue. >This is happening because I am adding the task after the project is evaluated to be able to support different convention properties based on the provided container ID. > >You should be able to declare the task dependency like this:

project.afterEvaluate {
    cargoRunLocal.dependsOn('war')
}

I must say that this is kind of suboptimal and not very straight-forward if you don’t know the implementation.

So, by adding:

project.afterEvaluate {
        cargoRunLocal.dependsOn(initLogDir)
        cargoRunLocal.dependsOn(':server:war')
}

to the server module it works! The order of events wasn’t really important in my case.

/Emil