ant groovy task stdout output - ant

Inside of my ant script (which is startet with the -q (quiet) cli option) I start a groovy script like that:
<groovy src="${groovy.script.filepath}">
<classpath>
<pathelement location="path/to/groovy/src/"/>
</classpath>
<arg line="-arg 1 -arg 2"/>
</groovy>
My groovy script looks like this:
//some imports
class MyClass {
static void main(args) {
System.out.println("Im not beeing printed!")
System.err.println("But I am printed, but on stdout!")
//...
}
//...
}
I expected both the outputs to be displayed like when I do <echo level="default">...</echo> or <echo level="error">...</echo>. However the System.out one is not printed at all and the System.err one is printed on stdout.
Why is that and how can I make groovy print on stdout and stderr like when using ants echo task?

Related

Invoke ant target from another target with <groovy>

I have the following script:
<target name="query">
<taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy" classpathref="libraries"/>
<groovy>
import groovy.sql.Sql
def sql = Sql.newInstance("jdbc:oracle:thin:#mydomain.com:1521:alias", "test", "test", "oracle.jdbc.pool.OracleDataSource")
List productNames = sql.rows("SELECT name from PRODUCT")
//println(productNames.count)
productNames.each {
println it["name"]
// HOW TO INVOKE ANT TARGET TASK HERE? TARGET TASK WILL USE it["name"] VALUE
}
properties."productNames" = productNames
</groovy>
</target>
<target name="result" depends="query">
<echo message="Row count: ${productNames}"/>
</target>
I would like to invoke another ant target from "query" target. Especially inside of productNames loop, like put in comments above.
Do you have any idea how to do it?
There are some binding objects in the <groovy> scope (see the documentation for more details), more specifically there is ant object which is an instance of AntBuilder (see the api here), with this object you can invoke getProject() method to get an instance of org.apache.tools.ant.Project and with this Project you can use executeTarget(java.lang.String targetName) method to execute a different target passing its name. All together looks like: ant.getProject().executeTarget("yourTargetName") and in your code:
<target name="query">
<taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy" classpathref="libraries"/>
<groovy>
import groovy.sql.Sql
def sql = Sql.newInstance("jdbc:oracle:thin:#mydomain.com:1521:alias", "test", "test", "oracle.jdbc.pool.OracleDataSource")
List productNames = sql.rows("SELECT name from PRODUCT")
//println(productNames.count)
productNames.each {
println it["name"]
ant.getProject().executeTarget("yourTargetName")
}
properties."productNames" = productNames
</groovy>
</target>
EDIT BASED ON COMMENT:
Passing parameters to the ant call it's not possible through org.apache.tools.ant.Project methods, however there is another way to do so, using ant or antcall tasks through AntBuilder, using antcall however it's not supported inside <groovy> if you try to use it you will get this error message:
antcall not supported within AntBuilder, consider using 'ant.project.executeTarget('targetName')' instead
So you must use ant task. For example if you have the follow ant target with a parameter in your build.xml:
<target name="targetTest">
<echo message="param1=${param1}"/>
</target>
You can call it from <groovy> passing a parameter like this:
<target name="targetSample">
<taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy" classpathref="groovyLibs"/>
<groovy>
ant.ant(antfile:'build.xml'){ // you antfile name
target(name:'targetTest') // your targetName
property(name:'param1',value:'theParamValue') // your params name and values
}
<groovy>
</target>
If you execute this <groovy> target example with ant targetSampe you will get:
targetTest:
[echo] param1=theParamValue
BUILD SUCCESSFUL
Total time: 0 seconds
Hope this helps,

How to set Ant reference to a FileSet from within <groovy/> Ant task?

I have something like:
<groovy>
import org.apache.tools.ant.types.FileSet
import org.apache.tools.ant.types.selectors.FilenameSelector
def aoeu = new FileSet()
aoeu.setDir(new File('aoeu'))
def snth = new new FilenameSelector()
snth.setName('snth')
aoeu.add(snth)
project.references['aoeu'] = aoeu
</groovy>
But:
<echo message="${toString:aoeu}"/>
emits a NullPointerException.
How can the above be fixed?
The groovy task has preconfigured bindings to an instance of AntBuilder and the Ant "project" object. It makes groovy very attractive for creating programmed logic within the build.
The following example demonstrates how the fileset can be created within the groovy script:
<project name="demo" default="process-text-files">
<path id="build.path">
<pathelement location="/path/to/jars/groovy-all-2.1.1.jar"/>
</path>
<target name="process-text-files">
<taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy" classpathref="build.path"/>
<groovy>
ant.fileset(id:"textfiles",dir:"src", includes:"**/*.txt")
project.references.textfiles.each {
println it
}
</groovy>
</target>
</project>
The following example demonstrates referencing a normal fileset created externally to the script (my preferred way to do it):
Ant : Process the files in the subfolder using tasks

ant custom-task, where should i place the new class file?

writing your own task should be a simple task.
according to the documentation all you need is to extend org.apache.tools.ant.Task.
the site provide a simple class example:
package com.mydomain;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
public class MyVeryOwnTask extends Task {
private String msg;
// The method executing the task
public void execute() throws BuildException {
System.out.println(msg);
}
// The setter for the "message" attribute
public void setMessage(String msg) {
this.msg = msg;
}
}
and in order to use it using the build.xml:
<?xml version="1.0"?>
<project name="OwnTaskExample" default="main" basedir=".">
<taskdef name="mytask" classname="com.mydomain.MyVeryOwnTask"/>
<target name="main">
<mytask message="Hello World! MyVeryOwnTask works!"/>
</target>
</project>
my question is, where should i put the MyVeryOwnTask.java file, should it be .jar file?
should it be relative in some way to the build.xml file?
com.mydomain.MyVeryOwnTask does it represents a file structure like a java project in eclipse?
my ant directory is C:\ant.
i have all the environment vars set.
thanks.
The best approach is to put it in a jar file and then add a <classpath> inside the <taskdef> pointing to the jar:
<taskdef name="mytask" classname="com.mydomain.MyVeryOwnTask">
<classpath>
<fileset file="mytask.jar"/>
</classpath>
</taskdef>
You can put the jar in ant's own lib directory instead, and then you don't need the classpath, but using an explicit classpath element as above means your build file will work with a standard unmodified ant installation so it's a good habit to get into particularly if you are going to be collaborating with other developers.

How to redirect stderr to stdout in an Ant JUnit target?

I have a simple Ant build file to produce a JUnit test report in XML format (see below). This produces a report with each test method's output (if any) on stdout and stderr. I'd like the output on the two streams to be merged into one for each test method. But I'm not sure how to do this; how can I tell the JUnit target to redirect stderr to stdout?
<target name="test" depends="compile">
<junit>
<classpath refid="classpath.tests"/>
<formatter type="xml"/>
<test name="tests.Tests1"/>
<test name="tests.Tests2"/>
</junit>
</target>
ant test | grep -w junit 2>&1
The Alternate option is : run Ant with q option.
ant -q test

Move a ant dir project after the ant or subant task completes

Currently i'm using a shell script to do the following:
cd myproject1/
ant
cd ..
if grep 'sucessful' myproject/buil.log then move myproject ../backup/today/
And so on for myproject2, myproject3.
If some error happens, the project stay in the current dir to be reprocessed but the whole process continues.
I want to migrate this process to an ant build script but i have no clue on how to do this.
I have looked at ant and subant tasks. Ant looks more suitable to the job but i can't find a way to loop through a directory list using ant and move task togheter, checking if the ant task completes or not.
Thank you.
Checkout this answer:
running specific target in different ant scripts in different directories
I recommend that your submodule builds should throw an error rather than try and duplicate the log parsing logic.
Update
If this is designed to support deployment, perhaps you should consider a groovy script?
Would better support exception conditions:
def ant = new AntBuilder()
scanner = ant.fileScanner {
fileset(dir:".", includes:"test*/build.xml")
}
scanner.each { f ->
try {
ant.ant(antfile:f)
}
catch (e) {
ant.mkdir(dir:"backup")
ant.move(todir:"backup", file:f.parent)
}
}
Groovy has excellent ANT integration and can also be embedded within your ANT build:
<target name="run">
<taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy" classpathref="build.path"/>
<fileset id="buildFiles" dir="." includes="test*/build.xml"/>
<groovy>
project.references.buildFiles.each {
def f = new File(it.toString())
try {
ant.ant(antfile:f)
}
catch(e) {
ant.mkdir(dir:"backup")
ant.move(todir:"backup", file:f.parent)
}
}
</groovy>
</target>
Something along these lines may be what you're looking for :
<target name="compile" >
<javac srcdir="${src.dir}" destdir="${class.dir}" />
</target >
<target name="copy" depends="compile" >
<mkdir dir="${dest.dir}" />
<copy todir="${dest.dir}" overwrite="true">
<fileset dir="${class.dir}" includes="**" />
<fileset dir="${src.dir}" includes="**" />
...
</copy>
</target>

Resources