Class Not Found with Ant, Ivy and Junit - Error in Build.Xml

Class not found with Ant, Ivy and JUnit - error in build.xml?

Example

Project contains the following files:

├── build.xml
├── ivy.xml
└── src
├── main
│   ├── java
│   │   └── org
│   │   └── demo
│   │   └── App.java
│   └── resources
│   └── log4j.properties
└── test
└── java
└── org
└── demo
└── AppTest.java

Build runs as follows:

$ ant 
Buildfile: /home/mark/Files/Dev/ivy/demo/build.xml

resolve:
[ivy:resolve] :: Apache Ivy 2.3.0 - 20130110142753 :: http://ant.apache.org/ivy/ ::
[ivy:resolve] :: loading settings :: url = jar:file:/home/mark/.ant/lib/ivy.jar!/org/apache/ivy/core/settings/ivysettings.xml
[ivy:resolve] :: resolving dependencies :: com.myspotontheweb#demo;working@mark-Lemur-Ultra
[ivy:resolve] confs: [compile, runtime, test]
[ivy:resolve] found org.slf4j#slf4j-api;1.7.5 in public
[ivy:resolve] found org.slf4j#slf4j-log4j12;1.7.5 in public
[ivy:resolve] found log4j#log4j;1.2.17 in public
[ivy:resolve] found junit#junit;4.11 in public
[ivy:resolve] found org.hamcrest#hamcrest-core;1.3 in public
[ivy:resolve] :: resolution report :: resolve 347ms :: artifacts dl 14ms
---------------------------------------------------------------------
| | modules || artifacts |
| conf | number| search|dwnlded|evicted|| number|dwnlded|
---------------------------------------------------------------------
| compile | 1 | 0 | 0 | 0 || 1 | 0 |
| runtime | 3 | 0 | 0 | 0 || 3 | 0 |
| test | 5 | 0 | 0 | 0 || 5 | 0 |
---------------------------------------------------------------------
[ivy:report] Processing /home/mark/.ivy2/cache/com.myspotontheweb-demo-compile.xml to /home/mark/Files/Dev/ivy/demo/build/ivy-reports/com.myspotontheweb-demo-compile.html
[ivy:report] Processing /home/mark/.ivy2/cache/com.myspotontheweb-demo-runtime.xml to /home/mark/Files/Dev/ivy/demo/build/ivy-reports/com.myspotontheweb-demo-runtime.html
[ivy:report] Processing /home/mark/.ivy2/cache/com.myspotontheweb-demo-test.xml to /home/mark/Files/Dev/ivy/demo/build/ivy-reports/com.myspotontheweb-demo-test.html

resources:
[copy] Copying 1 file to /home/mark/Files/Dev/ivy/demo/build/classes

compile:
[javac] Compiling 1 source file to /home/mark/Files/Dev/ivy/demo/build/classes

compile-tests:
[mkdir] Created dir: /home/mark/Files/Dev/ivy/demo/build/test-classes
[javac] Compiling 1 source file to /home/mark/Files/Dev/ivy/demo/build/test-classes

test:
[mkdir] Created dir: /home/mark/Files/Dev/ivy/demo/build/test-reports
[junit] Running org.demo.AppTest
[junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.085 sec

build:
[ivy:retrieve] :: retrieving :: com.myspotontheweb#demo
[ivy:retrieve] confs: [runtime]
[ivy:retrieve] 3 artifacts copied, 0 already retrieved (512kB/16ms)
[jar] Building jar: /home/mark/Files/Dev/ivy/demo/build/dist/demo.jar

BUILD SUCCESSFUL
Total time: 4 seconds

ivy.xml

A very powerful feature of ivy is configurations. These allow you to group dependencies together.

<ivy-module version="2.0">
<info organisation="com.myspotontheweb" module="demo"/>

<configurations>
<conf name="compile" description="Required to compile application"/>
<conf name="runtime" description="Additional run-time dependencies" extends="compile"/>
<conf name="test" description="Required for test only" extends="runtime"/>
</configurations>

<dependencies>
<!-- compile dependencies -->
<dependency org="org.slf4j" name="slf4j-api" rev="1.7.5" conf="compile->default"/>

<!-- runtime dependencies -->
<dependency org="org.slf4j" name="slf4j-log4j12" rev="1.7.5" conf="runtime->default"/>

<!-- test dependencies -->
<dependency org="junit" name="junit" rev="4.11" conf="test->default"/>
</dependencies>

</ivy-module>

Notes:

  • The configurations use the "extends" feature in order to emulate the Maven "compile", "runtime" and "test" Maven scopes.
  • Note the special "conf" attribute on each dependency. This is the mapping from local to remote. For more details on how remote Maven modules are managed by ivy see: How are maven scopes mapped to ivy configurations by ivy

build.xml

Ivy configurations can be leveraged by tasks like cachepath (to create an ANT path) and retrieve (copy files into your build).
I also recommend using the report target so that you can see which jars appear in each configuration (Useful to managing transitive dependencies)

<project name="demo" default="build" xmlns:ivy="antlib:org.apache.ivy.ant">

<!--
================
Build properties
================
-->
<property name="src.dir" location="src/main/java"/>
<property name="resources.dir" location="src/main/resources"/>
<property name="test.src.dir" location="src/test/java"/>
<property name="build.dir" location="build"/>
<property name="classes.dir" location="${build.dir}/classes"/>
<property name="test.classes.dir" location="${build.dir}/test-classes"/>
<property name="ivy.reports.dir" location="${build.dir}/ivy-reports"/>
<property name="test.reports.dir" location="${build.dir}/test-reports"/>
<property name="dist.dir" location="${build.dir}/dist"/>

<property name="jar.main.class" value="org.demo.App"/>
<property name="jar.file" value="${dist.dir}/${ant.project.name}.jar"/>

<available classname="org.apache.ivy.Main" property="ivy.installed"/>

<!--
===========
Build setup
===========
-->
<target name="install-ivy" description="Install ivy" unless="ivy.installed">
<mkdir dir="${user.home}/.ant/lib"/>
<get dest="${user.home}/.ant/lib/ivy.jar" src="http://search.maven.org/remotecontent?filepath=org/apache/ivy/ivy/2.3.0/ivy-2.3.0.jar"/>
<fail message="Ivy has been installed. Run the build again"/>
</target>

<target name="resolve" depends="install-ivy" description="Use ivy to resolve classpaths">
<ivy:resolve/>

<ivy:report todir='${ivy.reports.dir}' graph='false' xml='false'/>

<ivy:cachepath pathid="compile.path" conf="compile"/>
<ivy:cachepath pathid="test.path" conf="test"/>
</target>

<!--
===============
Compile targets
===============
-->
<target name="resources" description="Copy resources into classpath">
<copy todir="${classes.dir}">
<fileset dir="${resources.dir}"/>
</copy>
</target>

<target name="compile" depends="resolve,resources" description="Compile code">
<mkdir dir="${classes.dir}"/>
<javac srcdir="${src.dir}" destdir="${classes.dir}" includeantruntime="false" debug="true" classpathref="compile.path"/>
</target>

<target name="compile-tests" depends="compile" description="Compile tests">
<mkdir dir="${test.classes.dir}"/>
<javac srcdir="${test.src.dir}" destdir="${test.classes.dir}" includeantruntime="false" debug="true">
<classpath>
<path refid="test.path"/>
<pathelement path="${classes.dir}"/>
</classpath>
</javac>
</target>

<!--
============
Test targets
============
-->
<target name="test" depends="compile-tests" description="Run unit tests">
<mkdir dir="${test.reports.dir}"/>
<junit printsummary="yes" haltonfailure="yes">
<classpath>
<path refid="test.path"/>
<pathelement path="${classes.dir}"/>
<pathelement path="${test.classes.dir}"/>
</classpath>
<formatter type="xml"/>
<batchtest fork="yes" todir="${test.reports.dir}">
<fileset dir="${test.src.dir}">
<include name="**/*Test*.java"/>
<exclude name="**/AllTests.java"/>
</fileset>
</batchtest>
</junit>
</target>

<!--
=====================
Build and run targets
=====================
-->
<target name="build" depends="test" description="Create executable jar archive">
<ivy:retrieve pattern="${dist.dir}/lib/[artifact]-[revision](-[classifier]).[ext]" conf="runtime"/>

<manifestclasspath property="jar.classpath" jarfile="${jar.file}">
<classpath>
<fileset dir="${dist.dir}/lib" includes="*.jar"/>
</classpath>
</manifestclasspath>

<jar destfile="${jar.file}" basedir="${classes.dir}">
<manifest>
<attribute name="Main-Class" value="${jar.main.class}" />
<attribute name="Class-Path" value="${jar.classpath}" />
</manifest>
</jar>
</target>

<target name="run" depends="build" description="Run code">
<java jar="${jar.file}" fork="true"/>
</target>

<!--
=============
Clean targets
=============
-->
<target name="clean" description="Cleanup build files">
<delete dir="${build.dir}"/>
</target>

<target name="clean-all" depends="clean" description="Additionally purge ivy cache">
<ivy:cleancache/>
</target>

</project>

Note:

  • The conditional "install-ivy" target will install ivy automatically. Just re-run the build, only needs to be done once.

App.java

Hello world logging example.

package org.demo;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Hello world!
*
*/
public class App {
static final Logger log = LoggerFactory.getLogger(App.class);

public static void main( String[] args ) {
App a = new App();
a.speak("hello world");
}

public void speak(String message) {
log.info(message);
}
}

AppTest.java

This is an old example from my archives. Not using the Junit assertions.

ackage org.demo;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

/**
* Unit test for simple App.
*/
public class AppTest
extends TestCase
{
/**
* Create the test case
*
* @param testName name of the test case
*/
public AppTest( String testName )
{
super( testName );
}

/**
* @return the suite of tests being tested
*/
public static Test suite()
{
return new TestSuite( AppTest.class );
}

/**
* Rigourous Test :-)
*/
public void testApp()
{
assertTrue( true );
}
}

log4j.properties

# Set root logger level to DEBUG and its only appender to A1.
log4j.rootLogger=DEBUG, A1

# A1 is set to be a ConsoleAppender.
log4j.appender.A1=org.apache.log4j.ConsoleAppender

# A1 uses PatternLayout.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n

ant 1.9.2 + junit.. Class not found error

You must add the compiled classes to the class path of the junit task.

    <junit fork="yes" haltonfailure="no" printsummary="yes" >
<classpath>
<path refid="testcase.path">
<pathelement location="${test.dest}"/>
</classpath>
<batchtest todir="${test.reportsDir}" fork="true">
<fileset dir="${test.dest}">
<include name="anttestcase/Login.class"/>
</fileset>
</batchtest>
<formatter type="xml"/>
</junit>

On Github there's an example ant project, which uses JUnit: https://github.com/mplacona/java-junit-template-project Have a look at it's build.xml.

Apache Ant: NoClassDefFoundError when using Junit

The source directories are wrong. Here are the correct properties:

<property name="src.dir" location="${basedir}/src" />
<property name="testsrc.dir" location="${basedir}/testsrc" />

another java.lang.ClassNotFoundException in ant's junit task

Are you sure your test class is in the build folder? You're invoking junit in a separate JVM (fork=true) so it's possible that working folder would change during that invocation and with build being relative, that may cause a problem.

Run ant from command line (not from Eclipse) with -verbose or -debug switch to see the detailed classpath / working dir junit is being invoked with and post the results back here if you're still can't resolve this issue.

Trouble with Apache Ant Tutorial - JUnit

On top of including the junit.jar file within my lib dir, I added the following line to my build.xml file right above the junit task declaration:

<path id="application" location="${jar.dir}/${ant.project.name}.jar"/>

which is a copy of the 'application' path id declaration within the 'run' task definition.

The application builds successfully, and I get the following output with ant junit (test failure is expected):

ant junit
Buildfile: /Users/jtyler/Projects/AntHelloWorld/build.xml

compile:
[javac] /Users/jtyler/Projects/AntHelloWorld/build.xml:20: warning: 'includeantruntime' was not set, defaulting to build.sysclasspath=last; set to false for repeatable builds

jar:

junit:
[junit] Running HelloWorldTest
[junit] Tests run: 2, Failures: 1, Errors: 0, Time elapsed: 0.001 sec
[junit] Test HelloWorldTest FAILED

BUILD SUCCESSFUL
Total time: 1 second

Comments the following questions would be greatly appreciated:

  1. Is the fact I actually needed to include the junit.jar file in my lib folder something I should be concerned about? I would assume this is not necessary if ant's tutorial explicitly states "Because Ant has a built-in JUnit 3.8.2 you could start directly using it."

  2. Is the fact I needed to define the 'application' path id outside of the run task definition a typo within the apache ant tutorial? Or are there other things I missed or should consider?

Thanks to all those that helped.

Ant build error while running run target

this appears to be a known bug in ANT 1.9.0. see here: Bamboo Ant Task fails when running junit task

read comments #4, #5, #8 & #20 @ THIS Link for some help.



Related Topics



Leave a reply



Submit