I am new to java so not sure I fully understand jar files.
I want to put some common code in a library jar, which I then use from applications that are in different jars. I have searched on this but only come up with people saying yes and then showing examples of classes in class files calling classes in jars, which is not the same as classes in a jar calling classes in a different jar.
I have tried to do this and thought I had it working, until I tried to run the application on the command line, at which point I get class not found errors. Yet the code works in eclipse and from what I have seen that appears to be a common problem where code runs in the ide under development but the minute someone tries to run their code outside of eclipse it fails.
So is it possible for an application built as a jar to call/use classes in an different jar file and if so how?
This is what I tried to test the problem
FoobarInterface.java
package org.myorg.mylibrary;
public interface FoobarInterface
{
String echo(final String val);
}
Foobar.java
package org.myorg.mylibrary;
public class Foobar implements FoobarInterface
{
public String echo(final String val)
{
StringBuilder sb = new StringBuilder("echoed: ");
sb.append(val);
return(sb.toString());
}
}
pom.xml for the library jar
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.myorg</groupId>
<artifactId>mylibrary</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>mylibraryname</name>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<index>true</index>
<manifest>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
which produces mylibrary-0.0.1-SNAPSHOT.jar
The client code is
Main.java
package org.myorg.myapp;
import org.myorg.mylibrary.Foobar;
public class Main
{
public Main(String[] args)
{
Foobar foobar = new Foobar();
StringBuilder sb = new StringBuilder("RESULT: ");
sb.append(foobar.echo(args[0]));
System.out.println(sb.toString());
}
public static void main(String[] args)
{
Main foo = new Main(args);
}
}
pom.xml for the app jar
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.myorg</groupId>
<artifactId>myapp</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>myappname</name>
<dependencies>
<dependency>
<groupId>org.myorg</groupId>
<artifactId>mylibrary</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<index>true</index>
<manifest>
<mainClass>org.myorg.myapp.Main</mainClass>
</manifest>
<manifestEntries>
<Class-Path>.</Class-Path>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
I have also tried all of these settings for the Class-Path element
. ./mylibrary-0.0.1-SNAPSHOT.jar mylibrary-0.0.1-SNAPSHOT.jar
So in theory after all that, I can run the application using this command
java -jar myapp-0.0.1-SNAPSHOT.jar
but I always get this error
Exception in thread "main" java.lang.NoClassDefFoundError: org/myorg/mylibrary/Foobar
no matter how I specify the Class-Path element in the app pom.xml and no matter whether I add classpath to the command line, e.g.
java -classpath mylibrary-0.0.1-SNAPSHOT.jar -jar myapp-0.0.1-SNAPSHOT.jar
and yes both jars iare in the same directory and I am running this on linux.
EDIT:
JB Nizet requested the results of running the command as java -jar but unfortunately I have deleted the test code since he got me past the problem. However if it is any good, here is the output from the source that first raised the problem for me and still exhibits the same exception but is also now working using the 2nd command he suggested.
java -jar FoobarGUI-0.0.1-SNAPSHOT.jar org.myorg.foobar.gui.Main
Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1770)
at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1653)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.Node.fireEvent(Node.java:8390)
at javafx.scene.control.Button.fire(Button.java:185)
at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:182)
at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:96)
at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:89)
at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.Scene$MouseHandler.process(Scene.java:3758)
at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3486)
at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2495)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:350)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:275)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$350(GlassViewEventHandler.java:385)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$$Lambda$201/45156577.get(Unknown Source)
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:404)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:384)
at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
at com.sun.glass.ui.View.notifyMouse(View.java:927)
at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
at com.sun.glass.ui.gtk.GtkApplication.lambda$null$48(GtkApplication.java:139)
at com.sun.glass.ui.gtk.GtkApplication$$Lambda$41/1364335809.run(Unknown Source)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.reflect.InvocationTargetException
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:497)
at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:71)
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:275)
at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1767)
... 50 more
Caused by: java.lang.NoClassDefFoundError: org/myorg/foobar/processor/ProcessorException
at org.myorg.foobar.gui.Main.initCenterSection(Main.java:244)
at org.myorg.foobar.gui.Main.initApplicationScene(Main.java:195)
at org.myorg.foobar.gui.Main.actionLogin(Main.java:413)
at org.myorg.foobar.gui.controller.ControllerLogin.actionLogin(ControllerLogin.java:97)
... 60 more
Caused by: java.lang.ClassNotFoundException: org.myorg.foobar.processor.ProcessorException
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 64 more
META-INF/MANIFEST.MF from the exploded application jar
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Built-By: myorg
Class-Path: FoobarProcessor-0.0.1-SNAPSHOT.jar
Created-By: Apache Maven 3.3.3
Build-Jdk: 1.8.0_45
Main-Class: org.myorg.foobar.gui.Main
this is a listing of the Processor library jar
META-INF/
META-INF/MANIFEST.MF
org/
org/myorg/
org/myorg/foobar/
org/myorg/foobar/processor/
org/myorg/foobar/processor/ProcessorException.class
org/myorg/foobar/processor/Processor.class
META-INF/maven/
META-INF/maven/org.myorg.foobar/
META-INF/maven/org.myorg.foobar/FoobarProcessor/
META-INF/maven/org.myorg.foobar/FoobarProcessor/pom.xml
META-INF/maven/org.myorg.foobar/FoobarProcessor/pom.properties
META-INF/INDEX.LIST
and this is META-INF/MANIFEST.MF from the library jar
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Built-By: myorg
Created-By: Apache Maven 3.3.3
Build-Jdk: 1.8.0_45