ClassNotFoundException when running a jar but not when running the app directly - java

My app is facing a NoClassDefFoundError when trying to access external dependencies, but only when run as a jar.
Using Intellij, I have a simple app with main class with some calls to external dependencies such as slf4j.
public class Main {
private static final Logger logger = LoggerFactory.getLogger(Main.class);
///
public static void main(String[] args) {
logger.debug("start");
}
}
The pom.xml includes the relevant dependencies and the app is compiled successfully.
When running the app from the intellij as regular application it is running with no problem.
But when creating an executable jar out of it and trying to run it, it crashes and can't find external dependencies:
java.lang.NoClassDefFoundError: org/slf4j/LoggerFactory
at com.example.Main.<clinit>(Main.java:18)
Caused by: java.lang.ClassNotFoundException: org.slf4j.LoggerFactory
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:338)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 1 more
Exception in thread "main"
Process finished with exit code 1
I added this to the pom to try to solve the problem, but it didn't help:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<!-- Build an executable JAR -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.example.Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
The manifest file is located in src/main/resources/META-INF/MANIFEST.MF:
Manifest-Version: 1.0
Main-Class: com.example.Main

It's simple to understand. The jar that you are creating contains only the .class files of your code, not of the other libraries that you're importing. So when you run your code, it is unable to find the external library (org.slf4j in this case) that you have referenced in your code.
I don't know about the maven jar plugin that you're using, but try the maven assembly plugin. This plugin is used to bundle up all the other libraries that you use along with your code and create a "bundled" jar. Add the following to your pom.xml. You can add this portion between <plugins> and </plugins>.
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>example</id>
<configuration>
<archive>
<manifest>
<mainClass>com.example.Main</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
This additionally binds this "assembly" goal to the package phase of maven. So mvn package should create your jar.

Your meta-inf should have following attributes
Manifest-Version: 1.0
Created-By: xxxx
Main-Class: com.sample.Main
ClassPath: path/to/jars/your.jar
java -cp yourpath/example.jar com.sample.Main
Or
java -jar example.jar

Related

How to run a jar with lib?

I have this jar file 'domain-directory-configurator-cli-3.1.3000.0.0.0.jar' that doesn't contain dependancies
I have also this file 'domain-directory-configurator-cli-3.1.3000.0.0.0-lib.zip'
I want to run the jar file and my application using the libs.
What is the current syntax?
I tried
java -cp 3.1.3000.0.0.0/domain-directory-configurator-cli-3.1.3000.0.0.0.jar com.imperva.itp.directory.configurator.cli.MainClass
but I keep getting the exception :
Exception in thread "main" java.lang.NoClassDefFoundError: org/slf4j/LoggerFactory
so how do I refer the jar to work with the lib file?
You can do this by using the maven plugin maven-assembly-plugin
https://maven.apache.org/plugins/maven-assembly-plugin/usage.html
http://tutorials.jenkov.com/maven/maven-build-fat-jar.html
Assuming domain-directory-configurator-cli-3.1.3000.0.0.0-lib.zip does contain a number of jar files, you would have to extract themand list them one by one on the classpath.
More user friendly would be to have an executable jar where the main class is already mentioned in the manifest. Note you can configure the classpath in the manifest as well,so for a uer it could be sufficient to run java -jar domain-directory-configurator-cli-3.1.3000.0.0.0.jar and both the main class and the classpath are taken from the manifest.
In case you are using Maven, the below combination can help. It downloads all dependencies into the lib directory and configures both the main class and the classpath into the project's jar file.
<project>
<build>
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<archive>
<manifest>
<addDefaultEntries>true</addDefaultEntries>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.imperva.itp.directory.configurator.cli.MainClass</mainClass>
</manifest>
<manifestEntries>
<Build-Date>$(enf.BUILD_DATE)</Build-Date>
<Build-Date-Formatted>$(enf.BUILD_DATE_FORMATTED)</Build-Date-Formatted>
</manifestEntries>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Finally, when distributing your application do not forget to deliver not only your jar but also the lib directory with content.

Jar executable but can not find the classpath for main class

We have this small program we made and we wanna create an executable jar. Screenshot of my maven dependency and the project structure The problem is that I use Maven install and create a jar and in my pom, I have this plugin:
<plugin>
<!-- Build an executable JAR -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
I have been trying Project.Main and as in the code just Main ( Main) but I do always get this error in the terminal:
java -jar /home/haraldur/Desktop/Skolinn/508/Project/target/Project-1.0.jar
Error: Could not find or load main class Main
Caused by: java.lang.NoClassDefFoundError: javafx/application/Application
try dependency !?
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
</dependency>

Create Executable Jar with Maven (maven-assembly-plugin) Not Working vs. Eclipse Export Function

I am trying to create a runnable jar using maven (maven-assembly-plugin) which includes all required libraries in a generated jar file, maven successfully creates .jar file however when executing it seems some libraries are not being correctly loaded (specifically it is trying to load com.ibm.mq.jms classes it throws a DetailedJMSException: JMSCC0091), however when exported in eclipse as a runnable jar it successfully creates a runnable jar and when executed no exceptions are thrown.
Just wondering how I can use maven to do the same as the eclipse export runnable jar function without the exception?
Note: I have also tried a similar approach using maven-shade-plugin with the same exception thrown.
Here is the relevant build information in my pom.xml:
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4.1</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<groupId>org.apache.maven.plugins</groupId>
<executions>
<execution>
<id>make-executable-jar-with-dependencies</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.tapcons.execute.Execute</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
seeing other questions related to this you may should remove ur plugin from the pluginmanagement.
see here:
maven assembly plugin is not working with pluginManagement

Run Java Maven project with Linux command line

I have a Java project that prints "Hello world !". It runs well under Eclipse/Windows and on a Linux server with the command:
java MyClass.java; javac MyClass
Now that I have converted the project to a Maven project it's still running fine in Eclipse, but I can't find how to run it with a Linux command. I tried many answers that I found on forums but none work for me.
Here is an example of what I tested:
mvn package install;
cd target;
java -cp myApp-0.0.1-SNAPSHOT.jar mypackage.Mylass;
This results to an error:
Error: Could not find or load main class mypackage.Mylass
So, how can I run the Maven code on Linux without generating a jar file or at least make it work with a command line?
i finally managed to make it work thanks to all the answers.
here is what i did
i moved my Main class to the outside of packages and deleted/regenerated a new POM file with
<manifest>
<mainClass>Myclass</mainClass>
</manifest>
but i got some dependency errors so i generated a jar file with the dependency by adding maven plugin jar-with-dependencies
so here is what the build part of my POM file looks like now
....
</dependencyManagement>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.0</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>MyClass</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>MyClass</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
and here is how i execute it .
rm -rf target/ #delete old generated files
mvn install package # generate new jar files
java -jar target/App-0.0.1-SNAPSHOT-jar-with-dependencies.jar # execution
i hope this can save someone else's time
thanks for your help
You've specify a main class in the manifest of myApp-0.0.1-SNAPSHOT.jar
Add the next snippet of code to your pom file.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>mypackage.Mylass</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
This's the complete pom.file
http://maven.apache.org/maven-v4_0_0.xsd">
4.0.0
com.mycompany.app
my-app
jar
1.0-SNAPSHOT
my-app
http://maven.apache.org
junit
junit
3.8.1
test
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>com.mycompany.app.App</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
Can you confirm the class name you can trying to run ?
As per your comment, originally ran the class using below command.
java MyClass.java; javac MyClass - here the class name is MyClass
After maven install, it should be invoked using
mvn package install;
cd target;
java -cp myApp-0.0.1-SNAPSHOT.jar mypackage.MyClass;

Eclipse and Maven - resources in jar

I know this question was asked many times before, but I still can't manage it to work.
What I want to achieve is to create jar which will load resource (packed in jar) in runtime, without broking resource loading while executing application from Eclipse.
My project structure is standard:
src/main/java
src/main/resources
src/test/java
src/test/resources
Code for load image resource:
ClassLoader classLoader = getClass().getClassLoader();
splashImage = ImageIO.read(new File(classLoader.getResource("img/splash.png").getFile()));
It is working fine when starting the App from the Eclipse. However, when I export the runnable jar from the Eclipse, it doesn't works.
Exported jar have /resources/img folder in it's root directory. But when the app starts, an exception is thrown:
Caused by: javax.imageio.IIOException: Can't read input file!
How it is possible to make it work from runnable jar file and when running the App from the Eclipse?
I was also trying to build jar with maven plugins, but with no luck.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.8</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>foo.bar.App</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
You should go the following way for loading your resource:
classLoader.getResourceAsStream("/img/splash.png")
The point is that src/main/resources will automatically being copied to target/class which is the root of your classpath. This will work in Eclipse as well from the packaged jar.
An runnable jar will be created by maven via maven-assembly-plugin like this:
<project>
[...]
<build>
[...]
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.5.3</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
[...]
</project>
After you have added this you can create the full runnable jar via:
mvn clean package
This will produce a jar file in target folder which looks like: ´whatever-1.0-SNAPSHOT-jar-with-dependencies.jar´.
What i don't understand is the usage of maven-dependency-plugin in your build?

Categories