ClassNotFoundException: org.apache.commons.cli.ParseException with maven - java

I am trying to run a java project from the command line in linux :
$ java -jar target/my-app.jar -csv test.csv
and got this error
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/cli/ParseException
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2531)
at java.lang.Class.getMethod0(Class.java:2774)
at java.lang.Class.getMethod(Class.java:1663)
at sun.launcher.LauncherHelper.getMainMethod(LauncherHelper.java:494)
at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:486)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.cli.ParseException
I'm using maven-3, here my build maven configuration :
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<encoding>${project.build.sourceEncoding}</encoding>
<sourceEncoding>${project.build.sourceEncoding}</sourceEncoding>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>${appClass}</mainClass>
<classpathPrefix>lib/</classpathPrefix>
<useUniqueVersions>false</useUniqueVersions>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
And my commons-cli dependency declaration
<!-- CLI -->
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
<version>1.2</version>
</dependency>
If I remove code & dependencies into my class I get no more error.
Thank you !

You are using maven but you are running the application from command line so you need to provide all the required jars to your application:
Approach 1: You can provide into your classpath like below:
$ java -jar -cp "list-of-jars" target/my-app.jar -csv test.csv
If you are on Windows the path will be semi colon separated and on Linux it will colon separated. You can use wild cards also like /*.jar to include all the jars(java6+).
Approach 2: You can use one fat/uber/one jar to combine all the jars into on jar run it like you want.
Below is using one-jar:
Using Maven: you need to update the plugins section pom.xml:
<plugin>
<groupId>org.dstovall</groupId>
<artifactId>onejar-maven-plugin</artifactId>
<version>1.4.4</version>
<executions>
<execution>
<goals>
<goal>one-jar</goal>
</goals>
</execution>
</executions>
</plugin>
And update pluginRepositories section in pom.xml
<pluginRepository>
<id>onejar-maven-plugin.googlecode.com</id>
<url>http://onejar-maven-plugin.googlecode.com/svn/mavenrepo</url>
</pluginRepository>
When you will execute the mvn package you will get yourappname-one-jar.jar and you can run it java -jar yourappname-one-jar.jar
Approach 3: To use the maven shade plugin (as Robert suggested):
Add this into the plugins section of pom.xml:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>org.sonatype.haven.HavenCli</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
Upon execution on mvn package the uber jar will be generated.

Using maven-dependency-plugin is a solution.
<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>

Use maven assembly plugin in your pom.xml.
this will bundle all your dependencies in a single jar.
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>com.app.appmain</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</configuration>
</plugin>
<dependencies>
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
<version>1.3</version>
</dependency>
</dependencies>
To build:
mvn clean compile assembly:single

The -jar parameter is incompatible with -classpath or abreviatted -cp.
So when you launch your java process using a jar file you must provide a valid Manifest.mf file which declares a correct classpath.
This is the manifest example from java documentation:
Manifest-Version: 1.0
Class-Path: MyUtils.jar
Created-By: 1.7.0_06 (Oracle Corporation)
Then you may put the .jar file inside the definitive .jar file wherever you want (then you may add the path to it). Or just leave it outside, but respect the path as if it where inside the .jar file.

Related

How to compile a Maven Java with the librarys? [duplicate]

I have a code base which I want to distribute as jar. It also have dependency on external jars, which I want to bundle in the final jar.
I heard that this can be done using maven-assembly-plug-in, but I don't understand how. Could someone point me to some examples.
Right now, I'm using fat jar to bundle the final jar. I want to achieve the same thing using maven.
Note: If you are a spring-boot application, read the end of answer
Add following plugin to your pom.xml
The latest version can be found at
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>CHOOSE LATEST VERSION HERE</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>assemble-all</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
...
After configuring this plug-in, running mvn package will produce two jars: one containing just the project classes, and a second fat jar with all dependencies with the suffix "-jar-with-dependencies".
if you want correct classpath setup at runtime then also add following plugin
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>fully.qualified.MainClass</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
For spring boot application use just following plugin (choose appropriate version of it)
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
<mainClass>${start-class}</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
You can use the maven-shade-plugin.
After configuring the shade plugin in your build the command mvn package will create one single jar with all dependencies merged into it.
Maybe you want maven-shade-plugin, bundle dependencies, minimize unused code and hide external dependencies to avoid conflicts.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<minimizeJar>true</minimizeJar>
<createDependencyReducedPom>true</createDependencyReducedPom>
<dependencyReducedPomLocation>
${java.io.tmpdir}/dependency-reduced-pom.xml
</dependencyReducedPomLocation>
<relocations>
<relocation>
<pattern>com.acme.coyote</pattern>
<shadedPattern>hidden.coyote</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
References:
http://maven.apache.org/plugins/maven-shade-plugin/plugin-info.html
http://maven.apache.org/plugins/maven-shade-plugin/shade-mojo.html
actually, adding the
<archive>
<manifest>
<addClasspath>true</addClasspath>
<packageName>com.some.pkg</packageName>
<mainClass>com.MainClass</mainClass>
</manifest>
</archive>
declaration to maven-jar-plugin does not add the main class entry to the manifest file for me.
I had to add it to the maven-assembly-plugin in order to get that in the manifest
You can use the onejar-maven-plugin for packaging. Basically, it assembles your project and its dependencies in as one jar, including not just your project jar file, but also all external dependencies as a "jar of jars", e.g.
<build>
<plugins>
<plugin>
<groupId>com.jolira</groupId>
<artifactId>onejar-maven-plugin</artifactId>
<version>1.4.4</version>
<executions>
<execution>
<goals>
<goal>one-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Note 1: Configuration options is available at the project home page.
Note 2: For one reason or the other, the onejar-maven-plugin project is not published at Maven Central. However jolira.com tracks the original project and publishes it to with the groupId com.jolira.
An alternative is to use the maven shade plugin to build an uber-jar.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version> Your Version Here </version>
<configuration>
<!-- put your configurations here -->
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
Read if you want to use the maven-assembly-plugin.
As other answers have already outlined, it seems that the maven-shade-plugin offers more features and is the recommended plugin to build a fat jar, but in case you would like to use the maven-assembly-plugin the following plugin configuration will work.
The answer of #jmj explains that the correct classpath can be setup with an additional maven-jar-plugin, but this will only add the classpath to the original jar and not the fat jar. The information must instead be directly included into the configuration section of the maven-assembly-plugin.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.4.2</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.package.YourMainClass</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>assemble-all</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
When you now run maven package, your normal and fat jar will be created and you can run your fat jar with java -jar yourJar.jar.

Use Maven Jar plugin and Spring boot maven plugin simultaneously

I am trying to create jar for my spring boot server using spring boot maven plugin and my test automation framework jar from same project and pom file. To read external resources I am trying to defined manifest entries in maven jar plugin but this is causing spring server to not find application.properties in its default locations when run as a linux service using /etc/init.d/my-jar start.
Here is snippet of my pom file
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.5.3</version>
<configuration>
<descriptors>
<descriptor>src/assembly/dep.xml</descriptor>
</descriptors>
<archive>
<manifest>
<mainClass>com.myorg.mainclass</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
<version>1.2.5.RELEASE</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<finalName>${project.artifactId}-${project.version}-main-only</finalName>
<archive>
<manifest>
<mainClass>com.myorg.mainclass</mainClass>
</manifest>
<manifestEntries>
<Class-Path>./config/</Class-Path>
</manifestEntries>
</archive>
<excludes>
<exclude>**/application-test.properties</exclude>
</excludes>
</configuration>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
I have tried changing phase of my maven assembly and jar plugin to verify but the problem still persists. Removing manifest entry seems to work but then my external resource files are not read.
To solve the problem I removed the manifest entries from maven jar plugin and then while running the test jar. I added the external resource directory path into classpath as follows:
java -classpath my/external/resource/directory/path -jar my-tests.jar

How can i copy dependencies from external folder java

How can i copy dependencies from an /lib folder in the same jar directory(not build directory), i was using this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.1.2</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>../lib</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</execution>
</executions>
</plugin>
I'm getting ErrorNoClassFound,
java.lang.NoClassDefFoundError: it/unimi/dsi/fastutil/objects/Object2ObjectLinkedOpenHashMap
at org.bukkit.plugin.java.JavaPluginLoader.loadPlugin(JavaPluginLoader.java:133) ~[patched.jar:git-PaperSpigot-"4c7641d"]
at org.bukkit.plugin.SimplePluginManager.loadPlugin(SimplePluginManager.java:331) ~[patched.jar:git-PaperSpigot-"4c7641d"]
at org.bukkit.plugin.SimplePluginManager.loadPlugins(SimplePluginManager.java:254) [patched.jar:git-PaperSpigot-"4c7641d"]
at org.bukkit.craftbukkit.v1_8_R3.CraftServer.loadPlugins(CraftServer.java:293) [patched.jar:git-PaperSpigot-"4c7641d"]
at net.minecraft.server.v1_8_R3.DedicatedServer.init(DedicatedServer.java:202) [patched.jar:git-PaperSpigot-"4c7641d"]
at net.minecraft.server.v1_8_R3.MinecraftServer.run(MinecraftServer.java:563) [patched.jar:git-PaperSpigot-"4c7641d"]
at java.lang.Thread.run(Thread.java:748) [?:1.8.0_281]
Caused by: java.lang.NoClassDefFoundError: it/unimi/dsi/fastutil/objects/Object2ObjectLinkedOpenHashMap
File manager:
Image of how jar path and lib folder looks
If I understand OK now, that exception throws when you try to execute the generated jar. If that is the case, your maven-dependency-plugin looks fine but maybe you are missing to add lib folder name to the classpath of the generated jar:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<id>default-jar</id>
<goals>
<goal>jar</goal>
</goals>
<phase>package</phase>
<configuration>
<finalName>${jar.name}-${project.version}</finalName>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.example.main.MainClass</mainClass>
</manifest>
</archive>
</configuration>
</execution>
</plugin>
${jar.name} and ${project.version} are previously defined variables that you can replace with the desired name for your jar. And com.example.main.MainClass is just an example that you have to replace with your Main class.
There exist multiple ways to add local jar files to a Maven project below I show you 2:
1.Adding directly the dependency as system scope:
Assuming that the JAR is located in <PROJECT_ROOT_FOLDER>/lib add the dependency in your pom.xml:
<dependency>
<groupId>com.example.examples</groupId>
<artifactId>example-jar</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${basedir}/lib/your_jar.jar</systemPath>
</dependency>
2.Install the JAR into a local Maven repository
Use this for example:
mvn install:install-file –Dfile=C:\jar_directory\your_jar.jar -DgroupId=com.example.test -DartifactId=example-jar -Dversion=1.0
Next, add the dependency to your Maven project:
<dependency>
<groupId>com.example.examples</groupId>
<artifactId>example-jar</artifactId>
<version>1.0</version>
</dependency>

Building an executable jar with maven depencies and external jars

I have an application where Im using maven dependecies and Im also using an external jar of a project which is located in my computer, the project is added to the application manually. The problem is whenever I export the project with maven, It only exports all maven dependencies, not the externatl jar that I have included manually. Is there anyway that I can export it?
Here is my pom.xml:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>
${project.build.directory}/libs
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>libs/</classpathPrefix>
<mainClass>
com.cristianruizblog.loginSecurity.LoginSecurityTutorialApplication
</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
Thanks for reading. If anyone can help I would be so happy!
As stated by #M. Deunum, try to get your external jar into a Maven repository to avoid enable any machine to build your jar. If this is no option, you can use the Maven system dependency scope to include the jar. Note that this is only a temporary solution as this scope has been marked as depricated.

Netbeans Maven Project Not adding Main Class to Manifest

I am having a similar problem to this question. I have tried all the suggestions listed and am still at a loss. My issue is that I am trying to build a maven project and distribute it to other machines, but the jar files are not being populated with a correct Manifest. Each time I build and run I get the following error: no main manifest attribute, in myjar.jar. Is there some sort of configuration file I need to edit? I just don't know what is going on. I have attempted this fix also, but to no avail.
You can add it into project's pom file, inside <project> tag:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<mainClass>your.main.class</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
Another option is to use the maven shade plugin. Unlike the maven jar plugin showed by tigran, the maven shade plugin includes your dependencies in the generated jar.
A sample usage of the plugin is :
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>your.main.Class</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

Categories

Resources