This question already has answers here:
Add external library .jar to Spring boot .jar internal /lib
(8 answers)
Closed 4 years ago.
When I mvn clean package the project and run it with java -jar target/project.jar it throws an error that it cannot find some class from an external jar.
Steps taken
All external jars are in a folder of my project: /jars or /jars/morejars/
Adding the jars to the build path: In Eclipse I right click on project, go to build path and select add external archives. I can see that eclipse creates a library folder "referenced libraries" below the "Maven dependencies" folder. When I check project -> Properties -> Java Build Path -> Libraries I can see all the imported jars.
Some of those external jars are described as <dependency> (with <systemPath) in pom.xml, so they will not be seen in Referenced Libraries but in Maven dependencies (interestingly, the class that cannot be found when running my packaged project is in an external jar that doesn't reside in Referenced Libraries but Maven dependencies)
e.g.
<dependency>
<groupId>external.jar.groupid</groupId>
<artifactId>external.jar.artifactid</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${basedir}/jars/external-jar.jar</systemPath>
</dependency>
Use the maven assembly plugin (as described here), this is my full <build> config:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
Run mvn clean package -> BUILD SUCCESS
java -jar target/project.jar -> Cannot find some.class from external.jar
Thanks for the help
The problem is clearly with dependencies. While your application starts loading it looking for required classes to run properly. While it loading a class from a jar library and that library class also refer to some other class from a another jar library file but that library (jar file) is not available in your class path, it will give you the above error. So check for maven dependency and get all the jars required by your application. Also based on error message also you can add the jar reference in your pom.xml file. For example if you get an error like Failed to load com.apache.some.Example.class just google the Example.class jar file and get it from maven repository.
Hope this will help you.
Related
I'm trying to deploy my first java application using Maven. In this case, this is just a simply telegram bot, but I get this error when trying to run it locally. After a little investigation, I found that java.lang.NoClassDefFoundError is an error that occurs when a jar file is not able to access a specific class in runtime, and in order to solve this, is necessary to add that class on classpath.
I understand that when working on Maven, there is a simple way to add classes on the classpath, and it's by adding the right dependency on the pom.xml file.
So this is what i've added:
<dependencies>
<dependency>
<groupId>org.telegram</groupId>
<artifactId>telegrambots-abilities</artifactId>
<version>5.0.1.1</version>
</dependency>
<dependency>
<groupId>org.telegram</groupId>
<artifactId>telegrambots</artifactId>
<version>5.0.1</version>
</dependency>
<dependency>
<groupId>org.telegram</groupId>
<artifactId>telegrambots-meta</artifactId>
<version>5.0.1.1</version>
</dependency>
</dependencies>
And I think it was successfully added on the classpath because this is what I get when I read the MANIFEST.MF file on my jar file:
Manifest-Version: 1.0
Created-By: Apache Maven 3.6.3
Built-By: agujared
Build-Jdk: 15.0.1
Class-Path: telegrambots-abilities-5.0.1.1.jar commons-lang3-3.11.jar ma
pdb-3.0.8.jar kotlin-stdlib-1.2.71.jar kotlin-stdlib-common-1.2.71.jar
annotations-13.0.jar eclipse-collections-api-11.0.0.M1.jar eclipse-coll
ections-11.0.0.M1.jar eclipse-collections-forkjoin-11.0.0.M1.jar lz4-1.
3.0.jar elsa-3.0.0-M5.jar slf4j-api-1.7.30.jar telegrambots-5.0.1.jar j
ackson-annotations-2.11.3.jar jackson-jaxrs-json-provider-2.11.3.jar ja
ckson-jaxrs-base-2.11.3.jar jackson-module-jaxb-annotations-2.11.3.jar
jackson-core-2.11.3.jar jakarta.xml.bind-api-2.3.2.jar jakarta.activati
on-api-1.2.1.jar jackson-databind-2.11.3.jar jersey-hk2-2.32.jar jersey
-common-2.32.jar osgi-resource-locator-1.0.3.jar jakarta.activation-1.2
.2.jar hk2-locator-2.6.1.jar aopalliance-repackaged-2.6.1.jar hk2-api-2
.6.1.jar hk2-utils-2.6.1.jar javassist-3.25.0-GA.jar jersey-media-json-
jackson-2.32.jar jersey-entity-filtering-2.32.jar jersey-container-griz
zly2-http-2.32.jar jakarta.inject-2.6.1.jar grizzly-http-server-2.4.4.j
ar grizzly-http-2.4.4.jar grizzly-framework-2.4.4.jar jakarta.ws.rs-api
-2.1.6.jar jersey-server-2.32.jar jersey-client-2.32.jar jersey-media-j
axb-2.32.jar jakarta.annotation-api-1.3.5.jar jakarta.validation-api-2.
0.2.jar json-20180813.jar httpclient-4.5.13.jar httpcore-4.4.13.jar com
mons-logging-1.2.jar commons-codec-1.11.jar httpmime-4.5.13.jar commons
-io-2.8.0.jar telegrambots-meta-5.0.1.1.jar guava-30.0-jre.jar failurea
ccess-1.0.1.jar listenablefuture-9999.0-empty-to-avoid-conflict-with-gu
ava.jar jsr305-3.0.2.jar checker-qual-3.5.0.jar error_prone_annotations
-2.3.4.jar j2objc-annotations-1.3.jar
Main-Class: domain.Main
As you can see, telegrambots-meta-5.0.1.1.jar is part of the classpath attribute.
How can I solve this?
By the way, I'm using Heroku Cloud to deploy this
Sounds like you want and need to create a runnable/ executable JAR file (with external dependencies).
This requires your build process to be enhanced by this step, regardless of where it is executed Heroku, Jenkins, Bamboo or on your local - this is a maven setting and will affect each of them.
Also on your local you can run the build of your project by executing mvn clean package in your IDE and afterwards to run the created JAR from the target folder with: java -jar ${yourJarName}. It'll likely fail for the same reason.
This is, because Maven dependencies are added with a so called scope. These are for example:
compile
provided
runtime
test
Whereby compile is the default one and being implicitly applied in case you don't specify it - like in your case. (You can read more about the scopes here)
This means Maven will add your dependency to your IDE at compile time, but it will be missing at the runtime, when your trying to execute it.
The solution is to create a runnable/ executable JAR file (also called *fat JAR *) containing all the needed dependencies.
You can do it directly within Maven with the help of the maven-assembly-plugin like so:
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>fully.qualified.MainClass</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
Then you need to build your JAR like:
mvn clean compile assembly:single
Note: The compile goal must be added before assembly:single or otherwise the code on your own project is not included.
To ease the handling of the process this goal commonly is tied to a Maven build phase to execute automatically. This ensures the JAR is built when executing mvn clean package, mvn clean install or performing a deployment/ release:
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>fully.qualified.MainClass</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</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>
Like this you can simply build your project with the mvn clean package command (probably the most common one) and it'll include the creation of the runnable/ executable JAR file. This will include all your needed dependencies and should resolve your java.lang.NoClassDefFoundError issue.
Just a short additional note
Creating runnable/ executable JAR file respectively fat JAR is not the only solution and maybe in some contexts unwanted. Since fat JAR files include all their needed dependencies, they are fairly big with all the related drawbacks (requires more bandwith to transmit, download size increases, same dependencies might be carried in multiple different JARs, ...).
For this reasons the fat JAR creation is avoided in Web Application Development with Java EE. Dependencies are only added at compile time, since it is known that a Servlet Container or Application Container like Tomcat or Wildfly will provide these at runtime to avoid the java.lang.NoClassDefFoundError. Therefore the different applications (JARs or in this context called WARs) don't need to provide the dependencies themself.
In your case it might also be the solution that you'll still build the thin JAR, but will provide the needed dependencies at runtime (e.g. separately downloading it and then specifying in the classpath before the execution).
I am using IntelliJ version 11.0.7 (2020.1.3) created a simple maven project and added my jar to it by
File -> Project Structure -> New Project Library -> Java -> Selected my jar -> Ok -> Ok
in that jar file, all the dependencies present which requires to run the application.
There are no compile-time errors but when I run my maven project then it is throwing this exception:
Exception in thread "main" java.lang.NoClassDefFoundError: com/fasterxml/jackson/core/JsonProcessingException
After adding this jar it is throwing an exception about the next missing jar, likewise when I added all the dependencies which are used inside that jar then everything works fine.
Is there any way to auto-generate all the dependencies and add to External Libraries from the jar when I added to it?
in that jar file, there are all the dependencies present which requires to run the application.
Are you sure that all dependencies present? Your next statement saying After adding this jar it is throwing exception about the next missing jar, likewise when I added all the dependencies which are used inside that jar then everything works fine.
Is your jar file hosted in maven repository? If yes, simply declare it in maven pom.xml file, it will manage all the transitive dependencies. If it is not in maven repository, you need to run mvn install command to install that into your local maven repository, later on refer it in your pom.xml file. It will auto resolve your transitive dependencies as well, if you package your jar file properly which include correct pom.xml inside.
Finally, I added this in my pom.xml where I generated the Jar file
To get Maven to build a Fat JAR from your project you must include a Fat JAR build configuration in your project's POM file. You configure Maven to build a Fat JAR from your project by including the maven-assembly-plugin in your POM file's plugin section. Maven refers to an output product that it builds as an assembly. Hence the name maven-assembly-plugin.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
Now it is working as expected.
Reference: http://tutorials.jenkov.com/maven/maven-build-fat-jar.html
I am getting classNotFound while running the jar. This class is present in external jar which was added through build path. Before I got compile time error so I added following code in pom.xml. So Now I am not getting compile time error but now I am getting error while run that executable jar.
I read other article also as per them some time external jar file path not found at run time so we need to java classpath (Source attachment). So I added through Build path > jar > added source attachment. But Still it that class not found at run time.
Pom.xml
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<classifier>spring-boot</classifier>
<mainClass>
com.main.Application
</mainClass>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Error Page :
It solved my issue after added my external jar in maven dependency.
Steps :
create libs folder in your project. Right click on project > New > Folder > libs
Put your external jar file in that folder.
Open pom.xml file and add that dependency into your code.
Name of jar : ReleaseVersion.jar
<dependency>
<groupId>ReleaseVersion</groupId>
<artifactId>ReleaseVersion</artifactId>
<scope>system</scope>
<version>1.0</version>
<systemPath>${basedir}/libs/ReleaseVersion.jar</systemPath>
</dependency>
By using this steps I solved my issue.
So i have a following problem:
I have a maven-project with several maven-dependencies. When i run mvn install it'll be packaged as .jar and the .jar together with the .pom-File will be placed inside my maven-repository. Now, this .jar does not contain other dependencies (and is also not supposed to!). Now, given that i have all the dependencies needed installed in my maven repository (which obviously maven will take care of), how can i run this jar on the command line without setting the classpath to point to every damn jar in the maven-repository? Is there any other way? mvn exec:java only seems to work within the maven-source directory, where it looks for the "pom.xml". But after installing, "pom.xml" becomes "name-version.pom" and i have a .jar instead of direct source/class-files. Is there any other way to point mvn exec:java to work with the .jar and .pom-File within the maven repository? Or maybe some other and better approach to do so?
Thanks in advance :)
EDIT1: I'll just put my comment from below in here to avoid further misunderstandings:
I do not want to put the dependency jars somewhere. I want to use the repository maven already takes care of.Theoretically given, that i have ALL libraries i will ever need already in my local maven repository. I want to be able to download any other maven project, that might be using some of the libraries i already have installed in my local repository, also install it using "maven install", then remove the source i downloaded and then execute the .jar created by maven and tell java or maven (depending on what the best approach is) to look for the dependencies of that project in my local maven repository.
I hope i made it clear enough :)
EDIT 2: So i decided to use mvn install to install the projects into my local .m2 repo and also keep the projects unpackaged in some defined folder.Then i can just call mvn exec:java inside those projects to run them and maven will resolve all the dependencies for me.
You may exclude some dependency that you don't want to be in your project like this -
<project>
...
<dependencies>
<dependency>
<groupId>sample.ProjectA</groupId>
<artifactId>Project-A</artifactId>
<version>1.0</version>
<scope>compile</scope>
<exclusions>
<exclusion> <!-- declare the exclusion here -->
<groupId>sample.ProjectB</groupId>
<artifactId>Project-B</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>
For more information you may check the link
Make a Jar executable and define classpath dependencies with maven can be done using maven-jar-plugin to create a manifest file. The manifest file is usually used for that
example
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<configuration>
<archive>
<manifest>
<!-- It define the classpath dependencies -->
<addClasspath>true</addClasspath>
<classpathPrefix>dependency-jars/</classpathPrefix>
<!-- it makes the jar executable -->
<mainClass>com.mycompany.App</mainClass>
</manifest>
<!-- it define some entries about your artifact -->
<manifestEntries>
<Build-Maven>Maven ${maven.version}</Build-Maven>
<Build-Java>${java.version}</Build-Java>
<Build-OS>${os.name}</Build-OS>
<Build-Label>${project.version}</Build-Label>
</manifestEntries>
</archive>
</configuration>
</plugin>
When you run the command mvn package|install, the following meta-inf/manifest.mf file will be created and added into the Jar.
If you need the dependency jar be in somewhere, that can be done easily, you will use maven-dependency-plugin to copy project dependencies to somewhere you want. you can copy into your project build directory into the manifest prefix folder defined
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.5.1</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>
${project.build.directory}/dependency-jars/
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
all dependencies will be in {project}/target/dependency-jars/
That approach not include any dependency into the jar all will be out the jar in somewhere you define.
You can configurate your projects using this approach as you need
whit this approach you only have to do mvn clean install and execute your jar
I hope this aproach be the solution that you need.
I'm working on an Android project and have some core code(that has some dependencies) that i'd like to version and make into a library/artifact(?) that I can pull into other projects. I'm using Maven to build and my editor is IntelliJ. I've never created a .jar but I think that's what I want to do.
In IntelliJ, i've gone to File->Project Structure->Artifacts->+ but I'm lost. I don't know how to define which source directories and files to include in the jar and I'm unsure if I need to include the actual jars of its dependencies in the jar? or define those dependencies in a pom.xml file and include the pom.xml file in the jar?
Any clarification would be much appreciated.
Maven project's dependencies are defined in its pom.xml file (basically, changing the dependencies from here is what are you visually doing using Intellij, by File->Project Structure->Artifacts). The source files that Maven takes are the ones which are into the src/main directory of your project. The build is done by default excluding the dependencies, so if you want to include them in your final jar, you have to specify this in your pom file (plugins):
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>attached</goal>
</goals>
</execution>
</executions>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
After that you have to execute mvn install command to have your jar created. You can do it running maven externally or from your IDE (if you have some Maven plugin installed) and the jar will be created in project's target folder.
The settings in IntelliJ IDEA will only create the JAR when you build using the IntelliJ IDEA compiler. To have maven create the JAR and deploy it to the maven repository, you need to use the maven assembly plugin. There is a predefined configuration for creating a jar with dependencies.
The Maven Shade Plugin can also create JARs and handle more advanced use cases. But you'll probably want to start with the assembly plugin/