Compiling successful, NoClassDefFoundError at ant java task - java

I have googled for hours now and read a lot of similar questions like this and this .
Now I simplified my code to some few short lines, so the problem should be obvious - but I still fail to solve it.
Here are my two simple classes:
package ant;
import my.package.util.exception.UtilTest;
public class Debug {
public static void main(String[] args) {
System.out.println(UtilTest.myTest());
}
}
package my.package.util.exception;
public class UtilTest {
public static boolean myTest(){
return true;
}
}
I built my.package.util.jar and put it into directory lib in the project directory.
Now I run the ant built script (see below) to built the jar for Debug class. The built is sucessfull, the MANIFEST.MF is:
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.9.4
Created-By: 1.8.0_20-b26 (Oracle Corporation)
Main-Class: ant.Debug
Class-Path: lib/my.package.util.jar
with empty line at the end.
Here is the build.xml:
<?xml version="1.0"?>
<project>
<path id="my.classpath">
<fileset dir="lib/" includes="**/*.jar"/>
<pathelement location="."/>
<pathelement location="bin"/>
</path>
<target name="compile">
<mkdir dir="build/classes"/>
<javac includeantruntime="false" srcdir="src" destdir="build/classes" encoding="UTF-8">
<classpath refid="my.classpath"/>
</javac>
</target>
<target name="jar">
<mkdir dir="build/jar"/>
<jar destfile="build/jar/Debug.jar" basedir="build/classes">
<manifest>
<attribute name="Main-Class" value="ant.Debug"/>
<attribute name="Class-Path" value="lib/my.package.util.jar"/>
<!-- EDIT: to solve the issue, use value="../../lib/my.package.util.jar"/-->
</manifest>
</jar>
</target>
<target name="debug">
<java classpath="${my.classpath}" jar="build/jar/Debug.jar" fork="true">
<arg value="${file}"/>
</java>
</target>
</project>
Running "ant debug" now, I get:
debug:
[java] Exception in thread "main" java.lang.NoClassDefFoundError: my/package/util/exception/UtilTest
[java] at ant.Debug.main(Unknown Source)
[java] Caused by: java.lang.ClassNotFoundException: my.package.util.exception.UtilTest
[java] at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
[java] at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
[java] at java.security.AccessController.doPrivileged(Native Method)
[java] at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
[java] at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
[java] at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
[java] at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
[java] ... 1 more
[java] Java Result: 1
BUILD SUCCESSFUL
Total time: 1 second
Who can help? :-/
Any hint is appreciated!

Edit: You can't do this that way, because if you use -jar parameter:
the JAR file is the source of all user classes, and other user class path settings are ignored (source).

Issue solved.
I finally understood that i have to set the class path relativ to destination jar file, not relative to build.xml.
So i have to add ../../ in front of the class path.
<manifest>
<attribute name="Main-Class" value="ant.Debug"/>
<attribute name="Class-Path" value="../..lib/my.package.util.jar"/>
</manifest>

Related

JavaFx Exception in thread "JavaFX Application Thread" Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/log4j/Logger

The app runs perfectly fine in Eclipse and IntelliJ, and also in 'ant run'. Only when I run as Windows cmd to get the following errors:
java -jar TheApp.jar
Exception in thread "JavaFX Application Thread" Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/log4j/Logger
at com.th.app.ui.Login.<clinit>(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplicationWithArgs$2(LauncherImpl.java:352)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$7(PlatformImpl.java:326)
at com.sun.javafx.application.PlatformImpl.lambda$null$5(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$6(PlatformImpl.java:294)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$4(WinApplication.java:185)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.ClassNotFoundException: org.apache.log4j.Logger
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 12 more
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at sun.launcher.LauncherHelper$FXHelper.main(Unknown Source)
Caused by: java.lang.NullPointerException
at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:383)
at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328)
... 5 more
This appears to be a -classpath problem, but I have spent more than one day but still getting the same error.
I'm attaching the build.xml, which works perfectly also:
<?xml version="1.0"?>
<project name="App" default="all" basedir=".">
<property name="src" value="./src"/>
<property name="build" value="./build"/>
<property name="lib" value="./lib"/>
<property name="dest" value="./dest"/>
<property name="main-class" value="com.th.app.ui.Login"/>
<path id="classpath">
<fileset dir="${lib}" includes="**/*.jar"/>
</path>
<target name="all" depends="clean, compile, jar, copy-file" description="Builds the whole project">
<echo>Doing all</echo>
</target>
<target name="clean" description="Removes previous build">
<delete verbose="true">
<fileset dir="${build}"/>
</delete>
</target>
<target name="compile" depends="clean" description="compile whole project">
<echo>compile ${ant.project.name} </echo>
<mkdir dir="${build}/classes"/>
<copy file="./config.properties" tofile="${build}/classes/config.properties"/>
<copy file="./src/log4j.properties" tofile="${build}/classes/log4j.properties"/>
<copy todir="${build}/classes/com/th/app/ui">
<fileset dir="${src}/com/th/app/ui">
<include name="**/*.fxml"/>
<include name="**/*.css"/>
</fileset>
</copy>
<javac srcdir="${src}" destdir="${build}/classes" classpathref="classpath" includeantruntime="false" />
</target>
<target name="jar" depends="compile">
<mkdir dir="${build}/jar"/>
<jar destfile="${build}/jar/${ant.project.name}.jar" basedir="${build}/classes">
<manifest>
<attribute name="Main-Class" value="${main-class}"/>
</manifest>
</jar>
</target>
<property name="args" value="READWRITE"/>
<target name="run" depends="copy-file, input-runargs">
<java fork="true" classname="${main-class}">
<classpath>
<path refid="classpath"/>
<path location="${dest}/jar/${ant.project.name}.jar"/>
</classpath>
<arg line="${args}"/>
</java>
</target>
<target name="input-runargs" unless="args" description="prompts for command line arguments if necessary">
<input addProperty="args" message="Type the desired command line arguments:"/>
</target>
<target name="copy-file">
<copy todir="${dest}"><fileset dir="${build}"/></copy>
</target>
</project>
This is my first JavaFx project and I'm trying hard to get it done.
Please help and any insight is greatly appreciated.
You are using at least one 3rd party library (log4j), you may also be using others. You need to also have those libraries on the classpath. Currently, you only have the application jar on the classpath and not the dependent libraries.
You could modify the manifest of your jar to provide the reference to the dependent jars.
Add the following line to the manifest of your jar file.
Class-Path: log4j-core.jar log4j-api.jar
This can probably be done using the manifest element in the ant script (though I have not tried that).
<manifest>
<attribute name="Main-Class" value="${main-class}"/>
<attribute name="Class-Path" value="log4j-core.jar log4j-api.jar"/>
</manifest>
Then ensure that the libraries are in the same directory as your jar file with the matching names you specified.
Then you can likely run the app as you were trying to do before (again I didn't try it).
java -jar TheApp.jar
Or, you could run using the -cp option and place all jars (including your jar) on the path, and run the app as:
java -cp TheApp.jar:log4j-core.jar:log4j-api.jar com.th.app.ui.Login
If you have other dependent libraries than just log4j, you will need to ensure they are on the classpath similarly.
There is a process called shading which unpacks all of the jar files used by your application and then repacks them into a single jar which you can execute. I do not recommend shading, but that is an alternate option which I won't detail here.
Such execution will likely only be possible on systems running obsolete versions of the JDK such as Oracle JDK 8. Recent versions of JDKs usually do not ship with the JavaFX framework, which is instead provided through a set of separate modules. The packaging and execution of applications built using recent JavaFX versions are quite different than what you are doing for a JDK 8-based JavaFX application.
Advice for future applications
Use up-to-date libraries, frameworks, and development tools. Follow the official documentation for those software versions. For instance, JDK 18+, JavaFX 18+, information at openjfx.io, Maven or Gradle instead of Ant and jlink or jpackage (usually via a Maven or Gradle plugin) for application packaging.

Ant compiling but not running or creating jar

The Ant build below compiles successfully.
Unfortunately, it doesn't execute the run step despite the depends attribute specifying execute the run target after compile step completed successfully.
It also doesn't create a jar file in the specified classpath.
build.xml
<?xml version="1.0" encoding="UTF-8"?>
<project default="run" name="My Project">
<target name="run" depends="compile">
<java classname="com.company.program.project">
<classpath path="staging\" location="C:\my_work\Eclipse\3.6-64\plugins\"/>
</java>
</target>
<target name="compile">
<javac includeantruntime="false" srcdir="./src" destdir="staging">
<classpath>
<fileset dir="C:\my_work\Eclipse\3.6-64\plugins">
<!-- <include name="**/*.jar" /> -->
<include name="org.eclipse.swt.*.jar" />
</fileset>
</classpath>
</javac>
</target>
<jar destfile="./build/jars/swtgui.jar" filesetmanifest="mergewithoutmain">
<manifest>
<attribute name="Main-Class" value="org.swtgui.MainGui" />
<attribute name="Class-Path" value="." />
</manifest>
<fileset dir="./bin/com/company/program/project" includes="**/*.class" />
<fileset dir="C:\my_work\Eclipse\3.6-64\plugins\" includes="org.eclipse.swt.win32.win32.x86_64_3.6.0.v3650b.jar" />
</jar>
<record name="./project.log" loglevel="verbose" action="start"/>
EDIT: Got it to run. Did not edit the build.xml, but went to Project Explorer -> build.xml -> External Tool Configurations -> Build -> Targets and for some reason the run target was unchecked.
I checked it and now the run target runs, but produces the error log below.
run:
[java] running com.company.project.program with default permissions (exit forbidden)
[java] Running in same VM Executing 'com.company.project.program'
The ' characters around the executable and arguments are
not part of the command.
[java] Could not find com.company.project.program. Make sure you have it in your classpath
at org.apache.tools.ant.taskdefs.ExecuteJava.execute(ExecuteJava.java:140)
at org.apache.tools.ant.taskdefs.Java.run(Java.java:834)
at org.apache.tools.ant.taskdefs.Java.executeJava(Java.java:228)
at org.apache.tools.ant.taskdefs.Java.executeJava(Java.java:137)
at org.apache.tools.ant.taskdefs.Java.execute(Java.java:110)
at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:293)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
at org.apache.tools.ant.Task.perform(Task.java:348)
at org.apache.tools.ant.Target.execute(Target.java:435)
at org.apache.tools.ant.Target.performTasks(Target.java:456)
at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1405)
at org.apache.tools.ant.Project.executeTarget(Project.java:1376)
at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
at org.eclipse.ant.internal.launching.remote.EclipseDefaultExecutor.executeTargets(EclipseDefaultExecutor.java:36)
at org.apache.tools.ant.Project.executeTargets(Project.java:1260)
at org.eclipse.ant.internal.launching.remote.InternalAntRunner.run(InternalAntRunner.java:460)
at org.eclipse.ant.internal.launching.remote.InternalAntRunner.main(InternalAntRunner.java:142)
[java] Java Result: -1
run: duration 0 seconds
BUILD SUCCESSFUL
BUILD SUCCESSFUL
Do I need to do anymore editing to the xml file to get this to run and create a jar?
Your jar step is not inside a "target". Create a target named "jar" that depends on "compile", that creates a jar (your "jar" block should work here), and have target "run" depend on it.
It looks like you will need to add the jar you create to your "run" "java" classpath as well.

java.lang.NoClassDefFoundError ANT build

I am getting an error regarding the classpath in the run stage. The error is
run:
[java] java.lang.NoClassDefFoundError: org/openqa/selenium/WebDriver
[java] at java.lang.Class.getDeclaredMethods0(Native Method)
[java] at java.lang.Class.privateGetDeclaredMethods(Unknown Source)
[java] at java.lang.Class.privateGetMethodRecursive(Unknown Source)
[java] at java.lang.Class.getMethod0(Unknown Source)
[java] at java.lang.Class.getMethod(Unknown Source)
[java] at sun.launcher.LauncherHelper.validateMainClass(Unknown Source)
[java] at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)
[java] Caused by: java.lang.ClassNotFoundException: org.openqa.selenium.WebDriver
[java] at java.net.URLClassLoader.findClass(Unknown Source)
[java] at java.lang.ClassLoader.loadClass(Unknown Source)
[java] at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
[java] at java.lang.ClassLoader.loadClass(Unknown Source)
[java] ... 7 more
[java] Error: A JNI error has occurred, please check your installation and try again
[java] Exception in thread "main"
[java] Java Result: 1
BUILD SUCCESSFUL
Total time: 1 second
This is the xml build code I have written. I am referencing the RunningPower jars folder and I believe the correct folder is being referenced as i able am able to compile. My base directory also contains a .classpath and .project file but not sure if they are important.
<?xml version="1.0" ?>
<project name="SeleniumProjectDataDriven" basedir="." default="run">
<target name="init">
<property name="src.dir" value="src" />
<property name="build.dir" value="build" />
<property name="classes.dir" value="${build.dir}/class" />
<property name="lib.dir" value="RunningPowerJars" />
</target>
<target name="clean" depends="init">
<delete dir="build"/>
</target>
<target name="compile" description="Compiles the code" depends="clean" >
<mkdir dir="${classes.dir}" />
<javac srcdir="${src.dir}" destdir="${classes.dir}" includeantruntime="false">
<classpath>
<fileset dir="${lib.dir}">
<include name="**/*.jar" />
</fileset>
</classpath>
</javac>
</target>
<target name="jar" description="Packages the code into jar" depends="compile">
<mkdir dir="build/jar"/>
<jar destfile="build/jar/RunningPower.jar" basedir="build/class">
<manifest>
<attribute name="Main-Class" value="RunningPower"/>
</manifest>
</jar>
</target>
<target name="run" description="Run the jar file" depends="jar" >
<java jar="build/jar/RunningPower.jar" fork="true"/>
</target>
</project>
In my RunningPowerJars folder, they contain
junit-4.8.1.jar
ojdbc6.jar
poi-3.7-20101029.jar
selenium-java-2.46.0.jar
selenium-server-standalone-2.46.0.jar
testng-6.1.1.jar
Update (7:32 AM PST 8/21/2015)
<target name="run" description="Run the jar file" depends="jar" >
<java jar="build/jar/RunningPower.jar" fork="true">
<classpath>
<fileset dir="${lib.dir}">
<include name="**/*.jar" />
</fileset>
</classpath>
</java>
</target>
I modified the code but ran into another error.
BUILD FAILED
C:\Users\dt208672\Perforce\depot\ebill\Automation\Selenium_eBill\RunningPower\build.xml:37: Problem: failed to create task or type classpath
Cause: The name is undefined.
Action: Check the spelling.
Action: Check that any custom tasks/types have been declared.
Action: Check that any <presetdef>/<macrodef> declarations have taken place.
The classpath is needed also when running the Jar file so that the JVM could find library classes. However, when using the jar attribute in the java task, "all classpath settings are ignored" (see https://ant.apache.org/manual/Tasks/java.html). The simplest way is to specify the main class and add the compiled Jar along with the library Jars located in the RunningPowerJars directory:
<target name="run" description="Run the jar file" depends="jar" >
<java classname="RunningPower" fork="true">
<classpath>
<pathelement location="build/jar/RunningPower.jar"/>
<fileset dir="${lib.dir}">
<include name="**/*.jar" />
</fileset>
</classpath>
</java>
</target>
An unrelated note is that you could use the properties defined in init throughout the buildfile. For example, in the jar target you can use ${classes.dir} instead of repeating build/class.
It still doesn't make sense why the build would fail if the classpath element is added inside the java task when using the jar attribute. Although it is ignored, it is weird that it is failing with the "failed to create task or type" error.
Consider that when you use the -jar parameter using the java.exe in command line the classpath parameter is ignored, that also happens with the java task in ant.
So, what you must do is to provide the libraries you need to have available to the process launching that ant and that will suffice.
Once said that... where should you add those libraries then ? if you're launching from eclipse, you may add them on Window->preferences under Ant->Runtime->Global Entries.
If you're using some C.I. server like jenkins you could add them on numerous ways, I cannot give a direct answer because there could be many.
There is also an alternative. You may declare the dependency on the .jar MANIFEST.MF and put it under /lib or whatever inside that jar.

SPRING java.lang.NoClassDefFoundError: org/springframework/context/ApplicationContext

It seems people have had similar problems, but on IDE's.
I am not using an IDE.
I installed Spring using a Maven dependency as you will see in my build.xml file.
I get the following stacktrace that says org.springframework.context is not found:
run-decouple:
[java] java.lang.NoClassDefFoundError: org/springframework/context/ApplicationContext
[java] at java.lang.Class.getDeclaredMethods0(Native Method)
[java] at java.lang.Class.privateGetDeclaredMethods(Class.java:2442)
[java] at java.lang.Class.getMethod0(Class.java:2685)
[java] at java.lang.Class.getMethod(Class.java:1620)
[java] at sun.launcher.LauncherHelper.getMainMethod(LauncherHelper.java:488)
[java] at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:480)
[java] Caused by: java.lang.ClassNotFoundException: org.springframework.context.ApplicationContext
[java] at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
[java] at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
[java] at java.security.AccessController.doPrivileged(Native Method)
[java] at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
[java] at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
[java] at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
[java] at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
[java] ... 6 more
[java] Exception in thread "main"
[java] Java Result: 1
BUILD SUCCESSFUL
Total time: 4 seconds
Here is my client (java file: DecoupledDataReaderClient.java):
package com.example.decouple.client;
import java.io.*;
import java.util.*;
import com.example.filereader.IReader;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class DecoupledDataReaderClient {
private IReader reader = null;
private ApplicationContext ctx = null;
public DecoupledDataReaderClient() {
ctx = new ClassPathXmlApplicationContext("beans.xml");
}
private String fetchData() {
reader = (IReader) ctx.getBean("reader");
return reader.read();
}
public static void main(String[] args) {
DecoupledDataReaderClient client = new DecoupledDataReaderClient();
System.out.println("Example 1.3: Got data: " + client.fetchData());
}
}
Here is my build.xml file with the spring dependency & classpath and xmlns to use MAVEN
*EDIT: ADDED THE CLASSPATH TO RUN-DECOUPLE*
<project name="data-reader" default="compile" xmlns:artifact="antlib:org.apache.maven.artifact.ant">
<property name="src" location="."/>
<property name="obj" location="../classes"/>
<property name="jarfile" location="../data-reader.
jar"/>
<target name="init">
<mkdir dir="dist" />
<artifact:dependencies pathId="dependency.classpath">
<dependency groupId="org.springframework"
artifactId="spring-context"
version="3.2.4.RELEASE" />
</artifact:dependencies>
</target>
<target name="compile" depends="init">
<mkdir dir="${obj}"/>
<depend srcdir="${src}" destdir="${obj}" />
<javac includeantruntime="false"
srcdir="${src}"
destdir="${obj}">
<classpath refid="dependency.classpath" />
</javac>
</target>
<target name="jar" depends="compile">
<jar basedir="${obj}" destfile="${jarfile}">
<include name="*.class"/>
</jar>
</target>
<target name="run" depends="compile">
<java classpath="${obj}" classname="VanillaDataReaderClient"/>
</target>
<target name="decouple-jar" depends="compile">
<jar destfile="dist/decouple.jar" basedir="${obj}">
<manifest>
<attribute name="Main-Class" value="com.example.decouple.client.DecoupledDataReaderClient"/>
</manifest>
</jar>
</target>
<target name="run-decouple" depends="decouple-jar">
<java fork="true" jar="dist/decouple.jar" >
<classpath>
<path refid="dependency.classpath" />
</classpath>
</java>
</target>
</project>
And lastly, here is my beans.xml file
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean name="reader" class="com.example.filereader.VanillaFileReader">
<constructor-arg value="src/hello.txt" />
</bean>
</beans>
If someone could help me with why it is not finding the class even though the spring dependency is in my build.xml (which downloaded successfully according to the output of build.xml) and with it in the classpath, I would greatly appreciate it.
Thanks in advance.
artifact:dependencies is storing the classpath for the Spring dependencies in the path dependency.classpath, and you're using that when you compile:
<javac ...
...
<classpath refid="dependency.classpath" />
However, when you run, you're only including your compiled source in the classpath:
<target name="run" depends="compile">
<java classpath="${obj}" classname="VanillaDataReaderClient"/>
</target>
This means the Spring classes aren't included.
Try including dependency.classpath as well:
<target name="run" depends="compile">
<java classname="VanillaDataReaderClient">
<classpath>
<pathelement location="${obj}"/>
<path refid="dependency.classpath"/>
</classpath>
</java>
</target>
Edit:
Your run-decouple target is using jar: "When using the jar attribute, all classpath settings are ignored". Switch to specifying the main class and the classpath, so you can include the dependencies:
<target name="run-decouple" depends="decouple-jar">
<java fork="true" classname="com.example.decouple.client.DecoupledDataReaderClient">
<classpath>
<pathelement location="dist/decouple.jar" />
<path refid="dependency.classpath" />
</classpath>
</java>
</target>

Jar-program built by Ant doesn't see the class with the explicitly set classpath

So, here's my build.xml:
<?xml version="1.0"?>
<project name="test" default="hello_jar">
<path id="commons" >
<fileset dir="lib">
<include name="commons-lang-2.6.jar"/>
</fileset>
</path>
<target name="compile">
<mkdir dir="build/classes"/>
<javac srcdir="src/test_package" destdir="build/classes" classpathref="commons"/>
</target>
<target name="hello_jar" depends="compile">
<mkdir dir="build/jar"/>
<jar destfile="build/jar/hello.jar">
<fileset dir="build/classes">
<include name="test_package/Hello.class"/>
</fileset>
<manifest>
<attribute name="Main-Class" value="test_package.Hello"/>
</manifest>
</jar>
</target>
After successfully building a jar, I execute it with explicitly set classpath:
java -classpath lib/commons-lang-2.6.jar -jar build/jar/hello.jar test_package.Hello
and I get the following:
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/lang/math/Range
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2451)
at java.lang.Class.getMethod0(Class.java:2694)
at java.lang.Class.getMethod(Class.java:1622)
at sun.launcher.LauncherHelper.getMainMethod(LauncherHelper.java:494)
at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:486)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.lang.math.Range
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
... 6 more
Why can't it find the 'commons-lang' jar?
You should choose:
either you use -jar, and the JVM will use the classpath specified in the manifest file inside the jar. It will also use the manifest to know which main class must be executed. There should thus be no -cp option, and no class name specified:
java -jar build/jar/hello.jar
or you use -cp (or -classpath), and you should add every jar in the classpath (commons and hello), and you should specify the main class name to execute:
java -cp lib/commons-lang-2.6.jar:build/jar/hello.jar test_package.Hello
In your case, since you haven't configured the classpath in the manifest, you should choose the second option.

Categories

Resources