How to execute tasks multiple times in a loop

I want to execute a task multiple times in a loop.
For example:
task firsttask{

println"this is first task"
def parsedfile = (new XmlParser()).parse(“d:/myfile.xml”)
parsedfile.list.each{
list->
println"execute second task multiple times"
tasks.secondtask.execute()

 }

}

task secondtask<<{
println"this is from second task"

}

this is printing the line “execute second task multiple times” multiple times but task is executing only once. Please help

1 Like

Gradle builds a Directed Acyclic Graph at runtime which means each task is represented by one node in the graph. Each node in the graph (meaning a Gradle task) can only be executed once.

The method Task.execute() should never be called. You should use methods like dependsOn or finalizedBy to control the order of execution.

Can you describe the concrete problem you are trying to solve? Do you potential want multiple actions?

We are building a complex system. Which includes multiple workspaces and
projects. Jws(wokspace), jpr(projects). Each jws has n number of jpr files
as child. I am parsing each jws to get child jpr files. I want parse each
file in new target. I don’t want to mix up parsing of jws and jprs in
single task. So calling second task to parse jprs there. I can’t use
depends clause here. Please help
Thanks
Dheeraj M

How about you try the following?

Create a task for each JWS that should be parsed by creating them dynamically.
Create a task for parsing the JPR.
Create an aggregation task that parses all files.

task parseAll

def parsedfile = (new XmlParser()).parse("d:/myfile.xml")
parsedfile.list.each { file ->
    def jwsTask = task "parseJws${file.name.capitalize()}" { 
        doLast {
            // parse logic
        }
    }

    parseAll.dependsOn jwsTask
}

def jprTask = task parseJpr {
    doLast {
        // parse logic
    }
}

parseAll.dependsOn jprTask

Thank you so much for the idea.
But I don’t want to write there.
I want to write logic separately.
My jws file look like below

<?xml version = '1.0' encoding = 'UTF-8'?>
<jws:workspace xmlns:jws="http://xmlns.oracle.com/ide/project">
<list n="listOfChildren">
      <hash><url n="URL" path="firstjpr.jpr"/></hash>
      <hash><url n="URL" path="second.jpr"/></hash>
      <hash><url n="URL" path="thirdjpr.jpr"/></hash>
      <hash><url n="URL" path="fourthjpr.jpr"/></hash>
      <hash><url n="URL" path="fifthjpr.jpr"/></hash>
</list>
</jws:workspace>

Now in my task I parsed this jws file and got the list of jprs.

def parsedJws = (new XmlParser()).parse(jws)
parsedJws.list.hash.each{
jprlist->
def params = [jprlist.url.@path[0]]
sql.execute'insert into jpr_files(filename) values(?)',params
tasks.jprParsing.execute()
}
task jprParsing<<{
parsing of jpr files here

}

If I create tasks dynamically, I have to write logic over there. But I want
to write the logic separately.

Could you please help me to resolve this
Thanks in advance for helping me.

Thanks
Dheeraj M

I don’t fully understand what you mean by “write the logic separately”. Do you mean within in a method or a different location than in the build.gradle (maybe as class)?

Yes. As you can see in my code. I have 2 different tasks. Written
separately. 1)parsejws 2)parsejpr
task parsejws{
def parsedJws = (new XmlParser()).parse(jws)
parsedJws.list.hash.each{
jprlist->
def params = [jprlist.url.@path[0]]
sql.execute’insert into jpr_files(filename) values(?)’,params
tasks.jprParsing.execute()
}
task jprParsing<<{
parsing of jpr files here

}
I don’t want write this parsejpr inside the pasrejws line. I will collect
list of jpr files while parsing jws file and insert them into database. For
each jpr file I want to call the other task to parse it, where I will
collect filename from database and write my logic. My idea is like calling
one method from other method which can be done generally in a loop in java.
But here it is not happening. Hope I am clear with my explanation. Thanks
you so much for making time to help me

Thanks
Dheeraj M

That is generally not how you model tasks in Gradle. If you don’t want to break out multiple tasks then you only have the option of implementing the logic in a single task. If you want to structure the code better (and not separate the logic into multiple tasks), then I’d suggest you implement the logic with a custom task that gives you better options. See the following example:

class ProjectFileParser extends DefaultTask {
    @TaskAction
    void parse() {
        def parsedfile = new XmlParser().parse("d:/myfile.xml")
        parsedfile.list.each { file ->
            parseJpr(file)
        }
    }

    private void parseJpr(file) {
        // parsing logic
    }
}

task parseProjectFiles(type: ProjectFileParser)

Thank you sir. I will execute in this way. Thank u so much for spending
time to help me.

Thanks
Dheeraj M