JavaExec always running

Hello
This is my first post to Gradle Forums and I’m brand new to Gradle. I am hoping someone can help with some guidance. I have a task that runs the Liferay ServiceBuilder for a Portlet. The task basically loops through each service.xml and generates Java code. I then copy that code to a directory and compile it into classes for a jar. What I noticed is that the task runs the service builder every time regardless of whether the source code has changed. Is there something I can add to my task so that Gradle can determine if the task needs to be re-run. This process takes a few minutes to run and causes the jar to be re-assembled, so it would be nice to prevent it from running. I think the determining factor would be if the source code in SVN has changed, then re-run this task. Is there a good way to achieve my goal or a better way to write this task?

task generateServicesAsync {
        dependsOn 'compileServicesSyncJava'

        description = 'Generates ASync Liferay services via ah-core-dto from service.xml file'
        inputs.file liferayServiceFile
        outputs.dir "$buildDir/serviceAsync/docroot/WEB-INF/service"

        doLast {
                //get a list of server.xml files
                FileTree serviceXMLFiles = fileTree("${projectDir}/docroot/WEB-INF") {
                       include '**/service.xml'
                       exclude  '**/classes/**/service*.xml'
                }

                serviceXMLFiles.each { File svcXMLFile ->
                        println "Processing Async Service: ${svcXMLFile} :"
                        javaexec {
                                println "Processinf Async on ${svcXMLFile} :"
                                println 'Runnin ASYNC Service Builder:  Inputs - '
                                println "lib.dir=${liferayLibDir}"
                                println "base.dir=${buildDir}/serviceSync"
                                println "service.api.dir=${buildDir}/serviceAsync/docroot/WEB-INF/service"
                                println "service.impl.dir=${buildDir}/serviceAsync/docroot/WEB-INF/src"
                                println "lib.dir=${liferayLibDir}"
                                println "serviceConfigPath=${liferayServiceFile}"

                                main = 'com.aonhewitt.portal.tools.async.builder.main.Main'
                                classpath = files(project(':shared:ah-core-dto').tasks.jar.archivePath) +   configurations.servicesGenAsync + files("docroot/WEB-INF/classes") + files("docroot/WEB-INF/src")

                                args = ["base.dir=${buildDir}/serviceSync", // moving projcet dir so we don't modify it base.dir=${projectDir}",
                                        "service.api.dir=${buildDir}/serviceAsync/docroot/WEB-INF/service",
                                        "service.impl.dir=${buildDir}/serviceAsync/docroot/WEB-INF/src",
                                        "lib.dir=${liferayLibDir}",
                                        "serviceConfigPath=${svcXMLFile}"]
                        }//End each Service.xml
                }//End java Exec
        }//End do last
}//end task generateServicesAsync

I have spent some time digging through this and made progress. I think I have resolved my issue but wanted to share what I had done in case other new Gradle users can learn from my struggles.

The issue was due to how I had my my tasks arranged. I have multiple configurations running. There was one point where the javaExec in the second configuration “ASync” was overwriting a file in my first “Sync” configuration output directory. As a result gradle was considering the task to be dirty.

After searching I found that using the --info parameter was quite helpful. It explained why the task was considered not UP-TO-DATE. It listed the exact file that had changed and allowed me to debug further.

So my advice to new users is to try to separate the output of your configuration as much as possible to avoid conflicts. In my opinion Gradle is more Aspect Oriented than Linear so mapping out your dependencies and using list dependency tasks will be crucial to your success for large multi project builds.