How to pass objects from one Gradle task to another?

This question was originally posted on the old forum and now copied here:


Hi,

I’m trying to store results in a set of properties or an object from the execution of one Gradle task so I can then pass these results into another task. In other words, I’m trying to work with Gradle tasks as with methods where a method can have a return value of an Object, and a calling method can then get hold of that return value.

I don’t know if this is an advisable approach or not, but I’m not finding much information on that in the Gradle’s user guide. The only information I find is Gradle tasks have inputs and outputs, but these are handled via directories and files, and I don’t want to go through this kind of setup for what appears to be an easy thing I’m trying to accomplish.

Does anyone have any ideas on this?

Thanks!

Dmitriy.

Answer:

That’s generally not the kind of thing that you do in Gradle, but that’s not saying it’s not a good way to solve your problem.

Are you able to give some more information about what your tasks do and what you are trying to achieve? That will help to get to the best solution.

Luke Daley

Principal Engineer, Gradleware

Reply:

In my Custom ReadEnvironmentInfoTask I’m reading various properties files containing connectivity information to a database, and I then connect to that database and query couple of fields for the information which should then drive further conditional logic of the build.

So, my intent for this ReadEnvironmentInfoTask (custom task) was to connect to a database and store described information either in a set of properties or even encapsulate it in a Groovy object which the (other) calling task could then get hold of and further direct the logic of the build. This way I was trying to encapsulate all of the logic for reading propertis files and connecting to a database for furher information in one task and then have other tasks act on such retrieved information and proceed further.

Hope that explains better of what I’m trying to do.

Thanks,

Dmitriy.

Hi Dmitiry, thanks for bringing this to the forum.

You could just define a custom class inline in your build, and have your ReadEnvironmentInfoTask set properties on it:

class Config {
    String name
}
  // Sets a project property, available everywhere
config = new Config()
  task readConf << {
    config.name = "foo"
}

The trick is then making sure that any task that needs to read from the config declares it depends on readConf.

task doSomethingWithConf(dependsOn: [readConf]) << {
    println "name is $config.name"
}

There are some options for wiring the dependencies up all in one go. If you know what they are going to be you could do something like:

def configUsingTasks = [taskA, taskB, taskC, taskD]
configUsingTasks*.dependsOn readConf

We do have some ideas on how to take some of the work out of this, but it won’t happen until after 1.0 unfortunately.

Will the approach above solve your problem?

Thanks Luke, but my Task is a CustomTask, so I need to have something like this from your example:

task readConf(type: ReadEnvironmentInfoTask) {

config.name = <value that is set on the member variable inside of ReadEnvironmentInfoTask class which implementation I have in a different .groovy file> }

So, how can I call out the variable set inside of the ReadEnvironmentInfoTask from within the scope of readConf(.) so I can then set it on the config.name?

Thank you, Dmitriy.

Hi Dmitriy,

I don’t quite understand your last paragraph sorry. Would you mind rephrasing?

Hi,

Basically, inside of the @TaskAction-marked method on the ReadEnvironmentInfoTask I compute some result value that I then want to be available to the caller of this task/method. Thus, I was wondering if there is a way to pass this result from within ReadEnvironmentInfoTask into the config.name variable, which is defined within the scope of the gradle script above, so I can then reference config.name from within other tasks that I would define in the same script.

Hope that clarifies it a little better.

Thanks, Dmitriy.

Tasks have a reference to their owning project (i.e. org.gradle.api.Task:project ) so you can just set config.name in your @TaskAction

@TaskAction
def setTheConfig() {
  project.config.name = "something"
}

There’s no real concept of a caller of a task. The tasks are just organised in a directed graph based on their dependencies, so you can never guarantee that sequence. You can count on a task being executed before another task, but not immediately before. There may be tasks executed in between.

Got you, thank you for the explanation Luke!