how to ignore a failure ant task? - ant

I have this ant script that is reading from a parameter a list of components and running other ant tasks (build.xml's):
<for list="${components.locations}" param="component" failonany="false">
<sequential>
<property name="#{component}" value="true"/>
<if>
<and>
<available file="${repository.location}/#{component}"/>
<available file="${repository.location}/${jars.location}"/>
</and>
<then>
<ant inheritAll="false" antfile="${repository.location}/#{component}/build.xml">
<!-- failonerror="false" -->
<property name="copy.libs" value="${copy.libs}"/>
<property name="repository.location" value="${repository.location}"/>
<property name="jars.location" value="${repository.location}/${jars.location}"/>
</ant>
</then>
</if>
</sequential>
</for>
The problem is if one component is failing, the script doesn't continue to next one.
I tried running with -k (-keep-going) argument but it doesn't help.
I found this property failonerror="false" but it's valid for "exec" tasks and couldn't integrate it with "ant" tasks or inside a "target".
Other direction was "failonany" property of the "for" but I didn't manage setting it up explicitly.
Can you please advice...
Thanks.

First of all, I would suggest deleting ant-contrib.jar and never looking back. Believe me, you will be doing yourself a favor.
You can use the subant task to iterate Ant builds on a set of directories or files. Simply define a dirset and pass any extra properties you need.
Instead of using ant-contrib's <if> block, use the standard target's if attribute to switch the entire target on or off. This is much safer and better practice.
<property name="repository.location" location="repository_location" />
<property name="jars.location" location="${repository.location}/jars" />
<property name="components" value="dir1,dir2,dir3" />
<target name="init">
<condition property="jars.available">
<available file="${jars.location}" />
</condition>
</target>
<target name="default" depends="init" if="jars.available">
<subant inheritall="false" failonerror="false">
<dirset id="components.dirs" dir="${repository.location}" includes="${components}" />
<property name="copy.libs" value="${copy.libs}" />
<property name="repository.location" value="${repository.location}" />
<property name="jars.location" value="${jars.location}" />
</subant>
</target>

Related

Generating HTML report with Ant 1.9.7 from Jmeter 3.0 file - "Start and end within the same entity" Error

Here is basically the build.xml that Jmeter 3.0 generated itself. When I try to run the tests with 40 000 users within an hour I get the error after 17 minutes - "${path}/build.xml: Fatal error during transformation using ${path}/jmeter-results-detail-report_21.xsl: XML document structures must start and end within the same entity.; SystemID: file:${path}/Test.jtl;"
<?xml version="1.0"?>
<project name="ant-jmeter" default="all">
<property name="testpath" value="${user.dir}"/>
<property name="jmeter.home" value="${basedir}/.."/>
<property name="report.title" value="Load Test Results"/>
<property name="target.report.dir" location="Asjad/apache-jmeter-3.0/extras/report"/>
<property name="test" value="Test"/>
<property name="show-data" value="n"/>
<property name="format" value="2.1"/>
<condition property="style_version" value="">
<equals arg1="${format}" arg2="2.0"/>
</condition>
<condition property="style_version" value="_21">
<equals arg1="${format}" arg2="2.1"/>
</condition>
<condition property="funcMode">
<equals arg1="${show-data}" arg2="y"/>
</condition>
<condition property="funcMode" value="false">
<not>
<equals arg1="${show-data}" arg2="y"/>
</not>
</condition>
<path id="jmeter.classpath">
<fileset dir="${basedir}">
<include name="ant-jmeter*.jar"/>
</fileset>
</path>
<taskdef
name="jmeter"
classpathref="jmeter.classpath"
classname="org.programmerplanet.ant.taskdefs.jmeter.JMeterTask"/>
<target name="all" depends="run,report"/>
<target name="run">
<echo>funcMode = ${funcMode}</echo>
<delete file="${testpath}/${test}.html"/>
<delete file="${testpath}/${test}.jtl"/>
<jmeter
jmeterhome="${jmeter.home}"
testplan ="${testpath}/${test}.jmx"
resultlog="${testpath}/${test}.jtl">
<property name="jmeter.save.saveservice.output_format" value="xml"/>
<property name="jmeter.save.saveservice.assertion_results" value="all"/>
<property name="jmeter.save.saveservice.bytes" value="true"/>
<property name="file_format.testlog" value="${format}"/>
<property name="jmeter.save.saveservice.response_data.on_error" value="${funcMode}"/>
</jmeter>
</target>
<property name="lib.dir" value="${jmeter.home}/lib"/>
<path id="xslt.classpath">
<fileset dir="${lib.dir}" includes="xalan*.jar"/>
<fileset dir="${lib.dir}" includes="serializer*.jar"/>
</path>
<target name="report" depends="xslt-report">
<echo>Report generated at ${report.datestamp}</echo>
</target>
<target name="xslt-report" depends="_message_xalan">
<tstamp><format property="report.datestamp" pattern="yyyy/MM/dd HH:mm"/></tstamp>
<xslt
classpathref="xslt.classpath"
force="true"
in="${testpath}/${test}.jtl"
out="${testpath}/${test}.html"
style="${basedir}/jmeter-results-detail-report_21.xsl">
<param name="showData" expression="${show-data}"/>
<param name="titleReport" expression="${report.title}"/>
<param name="dateReport" expression="${report.datestamp}"/>
</xslt>
</target>
<condition property="xalan.present">
<and>
<available classpathref="xslt.classpath" classname="org.apache.xalan.processor.TransformerFactoryImpl"/>
<available classpathref="xslt.classpath" classname="org.apache.xml.serializer.ExtendedContentHandler"/>
</and>
</condition>
<target name="_message_xalan" unless="xalan.present">
<echo>Cannot find all xalan and/or serialiser jars</echo>
<echo>The XSLT formatting may not work correctly.</echo>
<echo>Check you have xalan and serializer jars in ${lib.dir}</echo>
</target>
</project>
It is a simple test that just makes requests to the webpage.
I am using Ant build 1.9.7 and Jmeter 3.0.
I can think of 2 possible reasons:
Ant might be trying to convert .jtl to HTML when the .jtl is incomplete. In order to work that around:
Add the next line to <jmeter> section:
<property name="jmeter.save.saveservice.autoflush" value="true"/>
Or alternatively put add the following line to user.properties file (lives in JMeter's "bin" folder)
jmeter.save.saveservice.autoflush=true
It will "tell" JMeter to store the results as soon as they arrive.
40 000 users is quite a "heavy" load and JMeter default configuration might not be suitable for this. I believe you need to add at least some Java Heap space. In case of Ant it would be adding the next lines to <jmeter> section:
<jvmarg value="-Xmx8G"/>
Change that 8G reference value to be around 80% of your available physical RAM. See 9 Easy Solutions for a JMeter Load Test “Out of Memory” Failure guide for more recommendations on JMeter tuning for maximum performance
Showing your jmeter.log file (jmeter 3.0 will tell you where it is generated) will help.
But you may be facing this bug if using ANT + XSL to generated report:
https://bz.apache.org/bugzilla/show_bug.cgi?id=59918
See this :
Generating a faulty report when running JMeter 3.0 test with Ant

Available tag in ant is always true if a file is unavailable also

This code is always returning a true value even if file at given path does not exists
<available file="${x}/schema/#{componentname}-schema.sql" type="file" property="schema.file" />
<if>
<equals arg1="true" arg2="${schema.file}" />
<then>
<debug message="****schemafile is ${schema.file} ******" />
</then>
</if>
Output is always :-
*schemafile is true***
even if file is not available at that path.
Please help me to find the error.
I've refactored your example, in order to use standard ANT tasks:
<project name="demo" default="run" xmlns:if="ant:if">
<property name="src.dir" location="src"/>
<target name="run">
<available file="${src.dir}/schema/schema.sql" type="file" property="schema.file" />
<echo message="****schemafile is ${schema.file} ******" if:set="schema.file"/>
</target>
</project>
Notes:
I don't recognise the "debug" task so use the standard "echo" task instead
I recommend not using the ant-contrib "if" task. ANT 1.9.1 introduced an if attribute which can be used instead.
The following alternative variant will work with older versions of ANT. It uses an "if" target attribute to perform conditional execution:
<project name="demo" default="run">
<property name="src.dir" location="src"/>
<available file="${src.dir}/schema/schema.sql" type="file" property="schema.file" />
<target name="run" if="schema.file">
<echo message="****schemafile is ${schema.file} ******"/>
</target>
</project>
problem was i was iterating above code in for loop, and since property is immutable, it is always set to true if set at-least once. Thats why after 1 iteration even if the file was not found, it echoes schemafile is true** .
i have added below code to set property to false after that code
<var name="schema.file" unset="true"/>
<property name="schema.file" value="false"/>

ANT script to compile all (css) LESS files in a dir and subdirs with RHINO

I want do compile all *.less scripts in a specific folder and it subdirs with less-rhino-1.1.3.js.
There is an example on github for doing this for a specific file, which works perfect. But I want to do the same for a complete folder. I tried a lot, here is my last try.
It doesn't work, propertyregex seems not to be standard ANT, I don't want to use such things. I am not even sure if this code would work.
<project name="test" default="main" basedir="../../">
<property name="css.dir" location="public/css"/>
<property name="tool.less" location="bin/less/less-rhino-1.1.3.js"/>
<property name="tool.rhino" location="bin/tools/rhino/js.jar"/>
<macrodef name="lessjs">
<attribute name="input" />
<attribute name="output" />
<sequential>
<java jar="${tool.rhino}" fork="true" output="#{output}">
<arg path="${tool.less}"/>
<arg path="#{input}"/>
</java>
<echo>Lessjs: generated #{output}</echo>
</sequential>
</macrodef>
<target name="main">
<echo>compiling less css</echo>
<fileset dir="${css.dir}" id="myfile">
<filename name="**/*.less" />
</fileset>
<property name="lessfilename" refid="myfile"/>
<propertyregex property="cssfilename"
input="${lessfile}"
regexp="^(.*)\.less$"
replace="^\1\.css$"
casesensitive="true" />
<lessjs input="lessfile" output="cssfilename"/>
</target>
</project>
You could use the <fileset> to include all the less files need to be compiled. Later, you could use<mapper> to mark the corresponding detination css file.
<project name="test" default="main" basedir="../../">
<property name="css.dir" location="public/css"/>
<property name="tool.less" location="bin/less/less-rhino-1.1.3.js"/>
<property name="tool.rhino" location="bin/tools/rhino/js.jar"/>
<target name="less" description="Convert LESS to CSS then concatenate and Minify any stylesheets">
<echo message="Converting LESS to CSS..."/>
<!-- Clear the former compiled css files -->
<delete includeemptydirs="true">
<fileset dir="${css.dir}" includes="*.css, **/*.css" defaultexcludes="false"/>
</delete>
<apply dir="${css.dir}" executable="java" parallel="false" failonerror="true">
<!-- Give the input bundle of less files-->
<fileset dir="${css.dir}">
<include name="*.less"/>
</fileset>
<arg value="-jar" />
<arg path="${tool.rhino}" />
<arg path="${tool.less}" />
<srcfile/>
<!-- Output the compiled css file with corresponding name -->
<mapper type="glob" from="*.less" to="${css.dir}/*.css"/>
<targetfile/>
</apply>
</target>
</project>
I was able to piece together a working solution with the help of a couple of SO answers:
ANT script to compile all (css) LESS files in a dir and subdirs with RHINO
How to correctly execute lessc-rhino-1.6.3.js from command line
I had to download LESS 1.7.5 from GitHub and modify the Ant target to look like this. The -f argument and LESS JavaScript was key:
<property name="css.dir" value="WebContent/css"/>
<property name="less.dir" value="less"/>
<property name="tool.rhino.jar" value="test-lib/rhino-1.7R4.jar"/>
<property name="tool.rhino.lessc" value="test-lib/lessc-rhino-1.7.5.js"/>
<property name="tool.rhino.less" value="test-lib/less-rhino-1.7.5.js"/>
<target name="compile-less" description="compile css using LESS">
<apply dir="${css.dir}" executable="java" parallel="false" failonerror="true">
<fileset dir="${less.dir}">
<include name="styles.less"/>
</fileset>
<arg value="-jar"/>
<arg path="${tool.rhino.jar}"/>
<arg value="-f"/>
<arg path="${tool.rhino.less}"/>
<arg path="${tool.rhino.lessc}"/>
<srcfile/>
<mapper type="glob" from="*.less" to="${css.dir}/*.css"/>
<targetfile/>
</apply>
</target>
If anyone else is coming to this question recently, as I did, they may find that the less-rhino-1.1.3.js file given in the other answers does not work with the latest version of Rhino (which for me, as of now, is 1.7R4 from MDN). But the 1.4.0 version does, which can be obtained from Github here. So the relevant snippet from my build.xml, using these later versions, is shown. Note that I'm only compiling a single .less file to a single .css file, so no iteration or mappers are used (but obviously you can get those from the other answers). Other tweaks I made were to provide the output file as the final arg to less instead of capturing output from the Ant forked process, and to remove the dependency on ant-contrib stuff (not needed for the simple one-file case).
<property name="tool.rhino" value="build/lesscss/rhino1_7R4/js.jar" />
<property name="tool.less" value="build/lesscss/less-rhino-1.4.0.js" />
<property name="single-input-lesscss-file" value="/path/to/my/style.less" />
<property name="single-output-css-file" value="/output/my/style.css" />
<target name="compileLessCss" description="Compile the single less file to css">
<sequential>
<java jar="${tool.rhino}" fork="true">
<arg path="${tool.less}" />
<arg path="${single-input-lesscss-file}" />
<arg path="${single-output-css-file}" />
</java>
</sequential>
</target>
If maven is an option for you, you could try wro4j-maven-plugin or wro4j-runner (which is a command line utility).
Using one of these, all you have do is to create an resource model descriptor (wro.xml):
<groups xmlns="http://www.isdc.ro/wro">
<group name="g1">
<css>/path/to/*.less</css>
</group>
</groups>
The rest will be handled by the wro4j library. No need to carry about how rhino works or other details.
Disclaimer: I'm working on wro4j project
I had the same issue. I developed a solution using ant-contrib. It expects all of your .less files to be in one flat directory and to be moved to another flat directory. It will change the file extension to .css in the process.
<property name="tool.rhino" value="/rhino/js.jar" />
<property name="tool.less" value="src/js/less-rhino-1.1.3.js" />
<property name="tool.ant-contrib" value="/ant-contrib/ant-contrib-1.0b3-1.0b3.jar" />
<property name="less-files-dir" value="src/css/" />
<property name="css-files-dir" value="build/css/" />
<target name="compilecss" depends="setup-ant-contrib-taskdef, get-less-files-in-dir" description="DO THIS THING">
<for list="${less-files-to-convert}" param="file-name" trim="true" delimiter=",">
<sequential>
<propertyregex property="file-name-without-extension"
input="#{file-name}"
regexp="(.*)\..*"
select="\1"
override="yes" />
<java jar="${tool.rhino}" fork="true" output="${css-files-dir}${file-name-without-extension}.css">
<arg path="${tool.less}" />
<arg path="${less-files-dir}#{file-name}" />
</java>
<echo>Lessjs: generated ${css-files-dir}${file-name-without-extension}.css</echo>
</sequential>
</for>
</target>
<target name="check-for-ant-contrib">
<condition property="ant-contrib-available">
<and>
<available file="${tool.ant-contrib}"/>
</and>
</condition>
<fail unless="ant-contrib-available" message="Ant-Contrib is not available."/>
</target>
<target name="setup-ant-contrib-taskdef" depends="check-for-ant-contrib">
<taskdef resource="net/sf/antcontrib/antlib.xml">
<classpath>
<path location="${tool.ant-contrib}" />
</classpath>
</taskdef>
</target>
<target name="get-less-files-in-dir">
<var name="files-list" value="" />
<for param="file">
<path>
<fileset dir="${less-files-dir}" includes="**/*.less" />
</path>
<sequential>
<propertyregex property="file-name-and-relative-path"
input="#{file}"
regexp=".*\\(.*)"
select="\1"
override="yes" />
<echo>file name: ${file-name-and-relative-path}</echo>
<if>
<equals arg1="${files-list}" arg2="" />
<then>
<var name="files-list" value="${file-name-and-relative-path}" />
</then>
<else>
<var name="files-list" value="${files-list},${file-name-and-relative-path}" />
</else>
</if>
</sequential>
</for>
<property name="less-files-to-convert" value="${files-list}" />
<echo>files to convert: ${less-files-to-convert}</echo>
</target>
I was unable to get this to run using a JDK 1.6 since the javascript stuff has been incorporated to the JDK. The JDK does have a jrunscript executable in the distribution but when I try to run the less-rhino.js file it fails to recognize any readFile() function. Has anyone looked into that. Otherwise I may be giving the lesscss-engine a shot and enhancing it to understand filesets.

In Ant, can I use a property inside a target's "depends"?

I m trying to do this with Ant:
<property name="test" value="123"/>
<target name="helloworld" depends="${test}"/>
But I'm getting error "Target ${test} does not exist in this project."
So I m guessing I can do this?
You can use the AntCall Task to call a Task inside another Task.
<project>
<target name="asdf">
<property name="prop" value="qwer" />
<antcall target="${prop}" />
</target>
<target name="qwer">
<echo message="in qwer" />
</target>
</project>
To make one depend on the other, you can set a parameter in the dependent task and check it in your calling task.
Rather than depends, you can check a property using the if attribute. See the manual for more details.
For example:
<target name="helloworld" if="test"/>
Note this only checks if the property is set (you can use unless to check if it is unset).
An alternative, more complex but powerful, approach is to use a nested condition on a depended target:
<target name="helloworld" depends="myTarget.check" if="myTarget.run">
...
</target>
<target name="myTarget.check">
<condition property="test">
<and>
<available file="foo.txt"/>
<available file="bar.txt"/>
</and>
</condition>

Testing Macrodef Attribute without IF

I am attempting to remove all lines that begin with log if a macrodef attribute is set to prod (example below). I plan on using replaceregexp to remove all lines beginning with log. However, I am not sure how to test if an attribute is set to a specific value, besides using the if task. I would like to not introduce any non-core Ant tasks to perform this, but I can't come up with any other solutions. Do I have any other options besides using the if-task?
Thanks
<macrodef name="setBuildstamp">
<attribute name="platform" />
<sequential>
<if>
<equals arg1="platform" arg2="prod" />
<then>
<replaceregexp match="^log\(.*" value="" />
</then>
</if>
</sequential>
</macrodef>
You should use a reference to a parameter, like this #{platform}.
Also, your replaceregexp task is missing a few parameters.
I think that in your particular case it is better to use linecontainsregexp filter reader. Here is modified code (note negate argument to linecontainsregexp).
<macrodef name="setBuildstamp">
<attribute name="platform" />
<sequential>
<if>
<equals arg1="#{platform}" arg2="prod" />
<then>
<copy todir="dest-dir">
<fileset dir="src-dir"/>
<filterchain>
<linecontainsregexp
regexp="^log\(.*"
negate="true"
/>
</filterchain>
</copy>
</then>
</if>
</sequential>
</macrodef>
They may be a couple of ways to solve this, but none are as straightforward as using the ant-contrib element. I'm not sure if this will get you what you need for your application, but you could try the following:
Using conditional targets. If you can replace your macrodef with a target to call, this may work for you. Note that this will set the property globally, so it might not work for your application.
<target name="default">
<condition property="platformIsProd">
<equals arg1="${platform}" arg2="prod" />
</condition>
<antcall target="do-buildstamp" />
</target>
<target name="do-buildstamp" if="platformIsProd">
<echo>doing prod stuff...</echo>
</target>
Handle the 'else' case. If you need to handle an alternate case, you'll need to provide a few targets...
<target name="default">
<property name="platform" value="prod" />
<antcall target="do-buildstamp" />
</target>
<target name="do-buildstamp">
<condition property="platformIsProd">
<equals arg1="${platform}" arg2="prod" />
</condition>
<antcall target="do-buildstamp-prod" />
<antcall target="do-buildstamp-other" />
</target>
<target name="do-buildstamp-prod" if="platformIsProd">
<echo>doing internal prod stuff...</echo>
</target>
<target name="do-buildstamp-other" unless="platformIsProd">
<echo>doing internal non-prod stuff...</echo>
</target>
Using an external build file. If you need to make multiple calls with different values for your property, you could isolate this in another build file within the same project. This creates a bit of a performance hit, but you would not need the additional library.
in build.xml:
<target name="default">
<ant antfile="buildstamp.xml" target="do-buildstamp" />
<ant antfile="buildstamp.xml" target="do-buildstamp">
<property name="platform" value="prod" />
</ant>
<ant antfile="buildstamp.xml" target="do-buildstamp">
<property name="platform" value="nonprod" />
</ant>
</target>
in buildstamp.xml:
<condition property="platformIsProd">
<equals arg1="${platform}" arg2="prod" />
</condition>
<target name="do-buildstamp">
<antcall target="do-buildstamp-prod" />
<antcall target="do-buildstamp-other" />
</target>
<target name="do-buildstamp-prod" if="platformIsProd">
<echo>doing external prod stuff...</echo>
</target>
<target name="do-buildstamp-other" unless="platformIsProd">
<echo>doing external non-prod stuff...</echo>
</target>
Add ant-contrib to your project. Of course, if you can add a file to your project, the easiest thing would be to just add the ant-contrib.jar file. You could put it under a "tools" folder and pull it in using a taskdef:
<taskdef resource="net/sf/antcontrib/antlib.xml" classpath="${basedir}/tools/ant-contrib.jar" />
It looks like when you are building your project specifically for your Production environment - you are stripping out code you don't want to run in Production. Thus you are creating a different binary than what will run in your Dev or Testing environment.
How about using an environment variable or property file at run-time instead of build-time which determines whether or not logging happens? This way when you're having trouble in Production and you want to use the same exact binary (instead of determining the revision, checking out the code, rebuilding with a different environment flag) you just re-deploy it to your Dev or Test environment and turn on debugging in a properties file or environment variable?

Resources