Runnig task programmatically


(Mansour Al Akeel) #1

I am writing a task that needs to run another tasks. How do I do this programmatically ?

tasks = project.getTasks().getAll();
  System.out.println("found " + tasks.size() + " tasks");
  for (Task t : tasks) {
   if (t.getName().equals("classes"))
    this.task = t;
  }
  // how do I run this.task ??

(Benjamin Muschko) #2

You should be able to run a task by invoking the method execute(). At the moment this method is not part of the public API but you can invoke it. This might change in the future.


(Mansour Al Akeel) #3

Benjamin,

thank you for your reply. A bit more details would really help.

I don’t know execute() is available in which class. I am assuming it’s Action.execute(T). If this is the case, what parameters I need to pass it ? I am passing it a task. But that’s not doing anything. Here’s the code

for (Task task : tasks) {
   for (Action a : task.getActions()) {
    try {
     System.out.println("Executing action" + a.toString() + " from task " + task.getName());
     a.execute(task);
    } catch (Exception e) {
     e.printStackTrace();
     System.out.println("Failed to excute task: "+ task.getName());
    }
   }
  }

On the other hand I am getting Exception on some tasks:

Done rebuild in 173 milliseconds
Executing actionorg.gradle.api.internal.project.taskfactory.OutputDirectoryPropertyAnnotationHandler$2$1@3124f9f4 from task compileJava
Executing actionorg.gradle.api.internal.project.taskfactory.OutputDirectoryPropertyAnnotationHandler$2$1@63d6b63f from task compileJava
Executing actionorg.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$Validator@15ec1be1 from task compileJava
Executing actionorg.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$2@401a5c05 from task compileJava
java.lang.IllegalStateException: Task history is currently not available for this task.
        at org.gradle.api.internal.tasks.DefaultTaskOutputs.getPreviousFiles(DefaultTaskOutputs.java:78)
        at org.gradle.api.internal.tasks.compile.SimpleStaleClassCleaner.execute(SimpleStaleClassCleaner.java:32)
        at org.gradle.api.internal.tasks.compile.IncrementalJavaSourceCompiler.execute(IncrementalJavaSourceCompiler.java:71)
        at org.gradle.api.tasks.compile.Compile.compile(Compile.java:55)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:601)
        at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
        at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
        at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1054)
        at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:884)
        at org.gradle.api.internal.BeanDynamicObject.invokeMethod(BeanDynamicObject.java:158)
        at org.gradle.api.internal.CompositeDynamicObject.invokeMethod(CompositeDynamicObject.java:93)
        at org.gradle.api.tasks.compile.Compile_Decorated.invokeMethod(Unknown Source)
        at groovy.lang.GroovyObject$invokeMethod.call(Unknown Source)
        at org.gradle.util.ReflectionUtil.invoke(ReflectionUtil.groovy:23)
        at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$2.execute(AnnotationProcessingTaskFactory.java:129)
        at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$2.execute(AnnotationProcessingTaskFactory.java:127)
        at DefaultFileHandler.reinvokeTask(DefaultFileHandler.java:55)
        at DefaultFileHandler.fileModified(DefaultFileHandler.java:68)
        at TomcatMonitor.routeEvents(TomcatMonitor.java:46)
        at TomcatMonitor.access$000(TomcatMonitor.java:18)
        at TomcatMonitor$SourceMonitor.run(TomcatMonitor.java:82)
        at java.lang.Thread.run(Thread.java:722)
Failed to excute task: compileJava
Executing actionorg.gradle.api.internal.project.taskfactory.OutputFilePropertyAnnotationHandler$2$1@491b58d6 from task war
Executing actionorg.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$Validator@22656f19 from task war
Executing actionorg.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$2@3160e3f3 from task war
Done rebuild in 174 milliseconds

In case you need to know tasks I want to execute :

if (name.equals("classes") || name.equals("assemble")
     || name.equals("build")
     || name.equals("processResourceskk")
     || name.equals("compileJava") || name.equals("war"))
   {
    System.out.println("adding task: " + t.getName());
    this.tasks.add(t);
   }

(Peter Niederwieser) #4

Each task has a parameterless execute method (declared in the TaskInternal interface). But first, what is it that you want to achieve, and why can’t it be achieved with task dependencies?


(Mansour Al Akeel) #5

Thank you Peter. Still this didn’t help. Here’s what I trying to do. I need to compile classes when modified and to put them under build/classes directory. So I wrote a task that will monitor them the resources and when modified, it triggers an event that will invoke a method to run these tasks in the background.

The code I am doing it not working, and the version on the classes is not changing. However the war task when run, it updates the war but other tasks don’t do anything.

Here’s how I am doing it:

for (Task task : tasks) {
   try {
    System.out.println("Executing task " + task.getName());
    TaskInternal t2 = (TaskInternal) task;
    t2.execute();
   } catch (Exception e) {
    e.printStackTrace();
    System.out.println("Failed to excute task: " + task.getName()
      + " because " + task.getState().getExecuted());
   }

Any idea ?


(Peter Niederwieser) #6

I don’t have enough information to judge what’s going on. The tasks will definitely get executed, but not their task dependencies. This is the expected behavior when calling execute().

There may be better ways to achieve what you want. You could think about firing off nested builds with the http://gradle.org/docs/current/dsl/org.gradle.api.tasks.GradleBuild.html task.


(Mansour Al Akeel) #7

I don’t think nested builds will work since gradle obtains a lock on some files. I will need to check and get back to you.


(Mansour Al Akeel) #8
GradleBuild build = new GradleBuild();
  build.setBuildFile(project.getBuildFile());
  build.setDir(project.getBuildDir());
  StartParameter param = new StartParameter();
  LinkedList<String> taskNames = new LinkedList<String>();
  taskNames.add("tasks");
  param.setTaskNames(taskNames);
  build.setStartParameter(param);
  build.setTasks(taskNames);
  try {
   build.execute();
  } catch (Exception e) {
   e.printStackTrace();
  }

The results:

java.lang.NullPointerException
                                                                                                                                                                                                            at org.gradle.api.internal.AbstractTask$TaskInfo.access$000(AbstractTask.java:426)
                                                                                                                                                at org.gradle.api.internal.AbstractTask.<init>(AbstractTask.java:106)
                                                                                                                                                             at org.gradle.api.internal.AbstractTask.<init>(AbstractTask.java:96)
                                                                                                                                                              at org.gradle.api.DefaultTask.<init>(DefaultTask.java:31)
                                                                                                                                                                         at org.gradle.api.internal.ConventionTask.<init>(ConventionTask.java:29)
                                                                                                                                                          at org.gradle.api.tasks.GradleBuild.<init>(GradleBuild.java:32)
                                                                                                                                                                   at DefaultFileHandler.reinvokeTask(DefaultFileHandler.java:68)
                                                                                                                                                                    at DefaultFileHandler.fileModified(DefaultFileHandler.java:109)
                                                                                                                                                                   at TomcatMonitor.routeEvents(TomcatMonitor.java:52)
                                                                                                                                                                               at TomcatMonitor.access$000(TomcatMonitor.java:18)
                                                                                                                                                                                at TomcatMonitor$SourceMonitor.run(TomcatMonitor.java:80)
                                                                                                                                                                         at java.lang.Thread.run(Thread.java:722)

what is going on ?


(Luke Daley) #9

You can’t instantiate any Task object directly. The only way to do so is via the Task DSL or via the TaskFactory (i.e. dsl:org.gradle.api.Project:tasks).


(Mansour Al Akeel) #10

That’s what I did:

build = project.getTasks().add(“continuousBuild”, ContinuousGradleBuild.class);

However the Custom build class doesn’t have input or output file. getInputs.getFiles has no files. Not sure if there’s another way to create a task from a class properly.


(Luke Daley) #11

However the Custom build class doesn’t have input or output file

I don’t understand this.


(Mansour Al Akeel) #12

I have extended GradleBuild with my own class to prevent TaskStateInternal from being change. This will allow to run the task to be executed multiple times. However creating the task the way you gave me, doesn’t initialize input or output files for this task.


(Luke Daley) #13

This is well beyond the realms of supported API, so you’ll have to just keep experimenting to get it working. Another thing to keep in mind is that whenever using internal parts, they can change without notice in newer Gradle versions.


(Peter Niederwieser) #14

Tasks aren’t supposed to be executed multiple times. I’d try to have one “continuous” build task that watches for changes and executes a new GradleBuild task each time it encounters a change.

In the future, Gradle might provide explicit support for a “continuous” mode of operation, or at least better primitives to build upon.


(Mansour Al Akeel) #15

Thank you Peter. Since I am working on this now, and I believe I am close to get it to work, I will need your support. Running a single task multiple times is not an issue when keeping the state fixed.


(Mansour Al Akeel) #16

I understand that GradleBuild Task depends on other tasks that has to executed once as well. What are those tasks and their class names ?

I tried to run a continuous version of Compile, Copy, GradleBuild but still no luck seeing the newer version of my classes under build/classes/main …

any idea what other classes I am missing.

I am using the info from here:

http://gradle.org/docs/current/userguide/java_plugin.html#N118E6


(Peter Niederwieser) #17

The GradleBuild task doesn’t depend on other tasks. It executes a nested build.

You need to run a continuous version of your own task only. This task needs to somehow monitor for changes (I assume you have this implemented already) and execute a new GradleBuild task each time it detects a change.

That’s my proposal. I can’t say if and how well it works in practice. I wouldn’t try to execute a task multiple times because Gradle isn’t designed for this and what happens to work today (if it works at all) may break tomorrow.