I need to execute in parallel an automation suite on three different applications. For that I have created a main class in which I am passing brand value as an arg to execute for each specific brand. Here are the following details:
PROJECT STRUCTURE:
POM PACKAGE- contains all java files of application pages
UTILITY PACKAGE - contains the common utility java classes for performing common operations like filling the form
TESTSUITE PACKAGE - contains test case class and main class.
This is the compile and run part of build file I have created for performing parallel execution:
<!-- building all java file 3 times in different target for separate jars to class binary -->
<target name="compile" depends="init">
<javac srcdir="${basedir}/src/" destdir="${basedir}/build" classpathref="classpath" includeantruntime="true" />
</target>
<target name="compile2" depends="init">
<javac srcdir="${basedir}/src/" destdir="${basedir}/buildB" classpathref="classpath" includeantruntime="true" />
</target>
<target name="compile3" depends="init">
<javac srcdir="${basedir}/src/" destdir="${basedir}/buildC" classpathref="classpath" includeantruntime="true"/>
</target>
<target name="jar" depends="compile,compile2,compile3">
<jar destfile = "${basedir}/ClassFiles/A.jar" basedir = "${basedir}/build/" />
<jar destfile = "${basedir}/ClassFiles/B.jar" basedir = "${basedir}/buildB/" />
<jar destfile = "${basedir}/ClassFiles/C.jar" basedir = "${basedir}/buildC/" />
</target>
<!-- execute generated jar -->
<target name="Run" depends="jar" >
<parallel>
<java fork="true" classname="com.TestSuitePackage.MainClass">
<arg value="brand1"/>
<classpath>
<path refid="classpath"/>
<path location="${basedir}/ClassFiles/classes.jar"/>
</classpath>
</java>
<java fork="true" classname="com.TestSuitePackage.MainClass">
<arg value="brand2"/>
<classpath>
<path refid="classpath"/>
<path location="${basedir}/ClassFiles/B.jar"/>
</classpath>
</java>
<java fork="true" classname="com.TestSuitePackage.MainClass">
<arg value="brand3"/>
<classpath>
<path refid="classpath"/>
<path location="${basedir}/ClassFiles/C.jar"/>
</classpath>
</java>
</parallel>
</target>
In the above build file, I have compiled the same code three times to create diff jars for the same class with diff argument. Running this build, separate jar files get created however independent JVM is not getting invoked.
Please suggest the changes I need to make and inputs on the approach I am using.
Related
When attempting to run tests with JUnit 5 via the Ant junitlauncher task, I receive the following message:
[junitlauncher] WARNING: TestEngine with ID 'junit-jupiter' failed to execute tests
[junitlauncher] java.lang.NoClassDefFoundError: org/hamcrest/SelfDescribing
How do I fix this so that my tests can run?
The answers to similar questions (e.g. this one) mainly say to make sure that hamcrest is on the classpath. I've verified using the print-test-classpath target (see build file below for details) that the classpath I'm using to run my tests includes hamcrest-2.1.jar. Furthermore, the tests compile without any issue.
Here are the sections of my build.xml I think are relevant:
<path id="lib-only-class.path">
<fileset dir="${lib.dir}">
<include name="**/*.jar" />
</fileset>
</path>
<path id="class.path">
<path refid="lib-only-class.path"/>
<pathelement location="${classes.dir}"/>
</path>
<path id="test-class.path">
<path refid="class.path"/>
<pathelement location="${test-classes.dir}"/>
</path>
<target name="compile-tests" depends="compile">
<mkdir dir="${test-classes.dir}"/>
<javac srcdir="${test.dir}" destdir="${test-classes.dir}"
includeantruntime="no" classpathref="class.path"/>
</target>
<target name="test" depends="compile-tests">
<junitlauncher printsummary="yes">
<classpath refid="test-class.path"/>
<testclasses>
<fileset dir="${test-classes.dir}"/>
</testclasses>
</junitlauncher>
</target>
<target name="print-test-classpath">
<pathconvert property="classpathInName" refid="test-class.path"/>
<echo>Classpath is ${classpathInName}</echo>
</target>
in my project there are - among others - two classes: TheProblem and Server.
public class TheProblem {
public static void main (String args []) throws ClassNotFoundException {
ClassLoader.getSystemClassLoader().loadClass("Server");
}
}
When I execute the code from the command line, everything works just fine.
But when I use ANT to execute the code, I get a ClassNotFoundException - although both Server.class and TheProblem.class are inside of the same directory.
The directory structure of my project is fairly simple - I will try to illustrate it here:
root_folder/
- build.xml
- src/
- TheProblem.java
- Server.java
- build/
- TheProblem.class
- Server.class
Here is an excerpt of my build.xml file:
<?xml version="1.0" encoding="UTF-8" ?>
<project name="JAXB" default="compile">
<path id="project.class.path">
<pathelement path="${java.class.path}" />
<pathelement location="build" />
</path>
<target name="init" >
<mkdir dir="build" />
</target>
<target name="compile" depends="init" >
<javac classpathref="project.class.path" srcdir="src" destdir="build"
includeAntRuntime="false" />
</target>
<target name="execute-problem" depends="compile">
<java classpathref="project.class.path" classname="TheProblem" />
</target>
<target name="clean" depends="init">
<delete dir="build" />
</target>
</project>
When I execute ant compile, everything compiles, but when I execute ant execute-problem, the ClassLoader cannot find the Server class and throws a ClassNotFoundException.
When I navigate into the build directory and call java TheProblem, it works just fine. I really have no clue, why it doesn't work using ANT.
Thank you very much for taking the time to read this post.
Instead of
<target name="execute-problem" depends="compile">
<java classpathref="project.class.path" classname="TheProblem" />
</target>
try to use this
<target name="execute-problem" depends="compile">
<java fork="true" dir="." classname="TheProblem">
<classpath>
<path refid="project.class.path" />
</classpath>
</java>
</target>
Is there a way to set the value of the javac classpath property in Apache Ant (v1.9.6) so that I don't have to literally specify all the jars that I want to include e.g. a directory or file glob.
So, if I have something like:
<javac classpath="./lib/one.jar":./lib/two.jar:./lib/three.jar..."
...is there anyway to just specify my ./lib directory once, like the way you can do when you run a java application like:
java -cp ./lib/'*'
I've tried that, and just using ./lib, or./lib/* or ./lib/*.jar but they don't work.
And another solution using a reusable classpath reference:
<path id="compile.path">
<fileset dir="lib" includes="*.jar"/>
</path>
<javac srcdir="${src.dir}" destdir="${classes.dir}" includeantruntime="false" debug="true" classpathref="compile.path"/>
<junit printsummary="yes" haltonfailure="yes">
<classpath>
<path refid="compile.path"/>
<pathelement path="${classes.dir}"/>
</classpath>
..
..
Try putting a <classpath> element under <javac>:
<javac ...>
<classpath>
<fileset dir="lib" includes="*.jar"/>
</classpath>
</javac>
On Eclipse I create war files by using ant.
The issue is that in the war file isn't included the right mypropfile.properties.
The file is properly copied, but also if I use <eclipse.refreshLocal resource="projectdir" depth="infinite"/> the old file is included. I have to refresh manually the project.
For Ant I use the "Run in the same JRE as the workspace" option.
<?xml version="1.0" encoding="UTF-8"?>
<project name="MyProject" basedir=".">
<description>
My Project
</description>
<property name="workspace.dir" value="${basedir}/../../"/>
<property name="src" value="${basedir}/../src"/>
<property name="build" value="${basedir}/../build"/>
<property name="build.classes" value="${basedir}/../build/classes"/>
<property name="lib.dir" value="${basedir}/WEB-INF/lib"/>
<property name="web.dir" value="${basedir}/WEB-INF"/>
<property environment="env"/>
<property name="real.dir" value="${basedir}/real"/>
<property name="real2.dir" value="${basedir}/real2"/>
<path id="classpath.server">
<fileset dir="${env.CATALINA_HOME}/lib" includes="*.jar"/>
<pathelement path="${build.classes}"/>
</path>
<path id="classpath.app">
<fileset dir="${lib.dir}" includes="*.jar"/>
</path>
<target name="refreshResource" if="eclipse.refreshLocal">
<eclipse.refreshLocal resource="projectdir" depth="infinite"/>
</target>
<target name="clean">
<delete dir="${build}/classes"/>
<delete dir="${build}"/>
</target>
<target name="init" depends="clean, refreshResource">
<tstamp/>
<mkdir dir="${build}"/>
<mkdir dir="${build}/classes"/>
</target>
<target name="compile" depends="init">
<javac encoding="UTF8" srcdir="${src}" destdir="${build}/classes" includeantruntime="false">
<compilerarg value="-Xlint:unchecked"/>
<classpath>
<path refid="classpath.server.bin"/>
</classpath>
<classpath>
<path refid="classpath.server"/>
</classpath>
<classpath>
<path refid="classpath.app"/>
<fileset dir="${lib.dir}" includes="*.jar"/>
</classpath>
</javac>
</target>
<target name="deleteConfig">
<delete file="${src}/mypropfile.properties"/>
</target>
<target name="real" depends="deleteConfig">
<copy file="${real.dir}/realprop.properties" tofile="${src}/mypropfile.properties"/>
</target>
<target name="real2" depends="deleteConfig">
<copy file="${real2.dir}/real2prop.properties" tofile="${src}/mypropfile.properties"/>
</target>
<target name="war-real" depends="real, compile">
<input message="Warname (without .war):" addproperty="warname"/>
<war destfile="${workspace.dir}/${warname}.war" webxml="${web.dir}/web.xml">
<fileset dir="${basedir}">
<include name="**/*.*"/>
</fileset>
<classes dir="${build.classes}"/>
</war>
</target>
<target name="war-real2" depends="real2, compile">
<input message="Warname (without .war):" addproperty="warname"/>
<war destfile="${workspace.dir}/${warname}.war" webxml="${web.dir}/web.xml">
<fileset dir="${basedir}">
<include name="**/*.*"/>
</fileset>
<classes dir="${build.classes}"/>
</war>
</target>
EDIT
The target clean was wrong, so I've corrected it, but now build failed with error
BUILD FAILED ... Reference classpath.server.bin not found.
Ant doesn't care if Eclipse has refreshed the file or not. eclipse.refreshLocal is only relevant for editors and compilers inside of the IDE.
When you run the Ant build.xml, Ant copies the file in question in the real target into the source folder and compile copies it into ${build}/classes (at least it should do that). So before you create the WAR, you must make sure the compile step has done its work (i.e. look into each file to make sure that a change is visible in each copy).
What worries my is that you use different ways to access the classes:
${build}/classes
${build.classes}
${basedir}/../build/classes
So the first step should be to define a single way to locate the folder and then use this pattern everywhere.
If that doesn't solve your problem, you need to make sure Ant notices that the file has changed. Old filesystems like FAT support only timestamps which have second resolution. If you use an USB stick for your sources, it's possible to change the file and run Ant so fast that Ant thinks the file hasn't changed.
Lastly, you need to check your classpath. If one of the JAR dependencies also contains a file called mypropfile.properties, then Java resource loading can find either version.
This and other problems made me use a different solution to configure WAR files: I pass a system property with the absolute path of the config file. That way, the WAR file doesn't change when the config changes and I have full control over which config file is loaded.
I am having trouble just creating something simple, and it does not seem that any website is clear on how to do this, and honestly I think it should be simple.
I have a bunch of java files for a project. I want to compile all of them, and then run each file with specific arguments.
Basically I want the order of operations to be something like this
javac prob1.java
javac prob2.java
java prob1 parameter
java prob2 parameter
But I want that in ant (build.xml).
I can do the compile part just fine with
<project default="compile">
<target name="compile">
<javac srcdir="." />
</target>
</project>
I just can not get it to run say prob1 with an argument. I imagine this is extremely easy, but every solution I have found, does not seem to work. Also note prob1.class and prob2.class are in the same directory.
This should work:
<target name="run">
<java classname="prob1">
<classpath>
<pathelement location="."/>
</classpath>
<arg value="parameter" />
</java>
<java classname="prob2">
<classpath>
<pathelement location="."/>
</classpath>
<arg value="parameter" />
</java>
</target>