PDFBox with Maven - java.lang.NoClassDefFoundError - java

When installing PDFBox with Maven, it places the libraries in the ~/.m2/repository directory.
My program complies fine with mvn package.
When I try to run it with
java -cp target/java-project-1.0-SNAPSHOT.jar com.example.sub.App
then I get
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/pdfbox/pdmodel/PDDocument
Should I also be specifying the libraries in ~/.m2/repository as part of the classpath? This seems a bit too tedious to do it this way. What is the recommended way to specify the classpath of my PDFBox library while using the library location(s) of Maven?

I wasn't able to find a nice solution with leaving the JAR files in ~/.m2, so the answer below is a workaround based on some other answers. I will be including more clarification though for those who are new to both PDFBox and maven as I am.
1) Add the following to your pom.xml file. If you already have a <build> and <plugins> section, just add the <plugin> section below to that. Otherwise you may need to add the whole code below within the <project> element:
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>**REPLACE THIS WITH THE FULL URI OF YOUR MAIN CLASS**</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-my-jar-with-dependencies</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
2) Make sure that you replace the text in the <mainClass> element to match the situation. For example, if your main() method is located in an App class in App.js, and your package name is com.example.sub. Then the above element should read:
<mainClass>com.example.sub.App</mainClass>
3) To compile your app, run mvn package
Note: I have seen some references online using mvn clean compile assembly:single instead of mvn package. I am not sure what the purpose of this is when mvn package seems to run just fine for me.
This will take your project and all of your dependencies and create a single JAR file in the target directory called something like this:
java-project-1.0-SNAPSHOT-jar-with-dependencies.jar
4) To run the project you can do this:
java -cp target/java-project-1.0-SNAPSHOT-jar-with-dependencies.jar com.example.sub.App
Make sure that you modify the above line to it your situation. In other words you may need to change both the name of the jar file and the name of the URI for your main class.

Related

ClassNotFoundEcception when running jar through Terminal (or command prompt)

So I know there are tons of questions like this one, and I have been through all of them, but I can't seem to find one like mine.
Basically, I have a java project with a lot of Maven Dependencies. The project compiles and runs just fine when I run it with IntelliJ, but now I am trying to run it through the terminal (or command prompt). In order to do that, I ran mvn package so I can get a jar file and when I run java -jar server.jar, I get the classic ClassNotFoundEcception exception. In my case, it says that it is:
Caused by: java.lang.ClassNotFoundException: org.apache.commons.fileupload.FileItemFactory
and when I suppress it by (temporarily) commenting out the part of the code that uses this class, I end up with the same error for another class. At this point, I know that I need to have some sort of folder (correct me if I'm wrong, but I believe it is called CLASSPATH) which contains the .jar of each dependency. Can anyone explain to me the situation in a clear way and how am I supposed to organize the .jar file of each dependency (if that is even what I have to do to fix my error).
The org.apache.commons.fileupload.FileItemFactory and most likely other dependencies are not in the classpath. Intellij includes dependencies in the classpath automatically, and this is the reason it works.
To run the program from CMD with all your depedecies included define the following plugin in pom.xml:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.1</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>
</plugins>
and run:
mvn clean package
java -jar server-jar-with-dependencies.jar

Maven: Could not find or load main class

I have the following configuration for my maven build and I have double checked the class name as well as package name multiple times to ensure it's accuracy. But everytime I run:
java -jar <snapshot-with-dependencies>.jar I get Error: Could not find or load main class com.atlassian.JiraRestCaller.
The excerpt from my pom file is as below
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>com.atlassian.JiraRestCaller</mainClass>
</manifest>
</archive>
<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>
</plugins>
I also tried adding <sourceDirectory>src/main/java/com/atlassian/</sourceDirectory> but still get the same error
Solution1:
I spent a decent amount of time trying to solve this problem. I thought that I was somehow setting my classpath incorrectly but the problem was that I typed:
java -cp C:/java/MyClasses C:/java/MyClasses/utilities/myapp/Cool
instead of:
java -cp C:/java/MyClasses utilities/myapp/Cool
I thought the meaning of fully qualified meant to include the full path name instead of the full package name.
Solution2:
If you use Maven to build the JAR file, please make sure to specify the main class in the pom.xml file:
<build>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>class name us.com.test.abc.MyMainClass</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
This might help you if your case is specifically like mine: as a beginner I also ran into this problem when I tried to run a Java program.
I compiled it like this:
javac HelloWorld.java
And I tried to run also with the same extension:
java Helloworld.java
When I removed the .java and rewrote the command like java HelloWorld, the program ran perfectly. :)
So we had this today
[myproject]-[master] $ mvn
[MVNVM] Using maven: 3.5.2
Error: Could not find or load main class html
and we had an issue with Proxies.
Check your MAVEN_OPTS and make sure that if you are sending in a proxy to maven, that it exists and you can use it.
MAVEN_OPTS=-Dhttp.proxyHost=www-proxy.myproxyprovider.com -Dhttp.proxyPort=80 -Dhttps.proxyHost=www-proxy.myproxyprovider.com -Dhttps.proxyPort=80
or if it is set and you shouldnt have one, then get rid of it.
[myproject]-[master] $ mvn -version
[MVNVM] Using maven: 3.5.2
Apache Maven 3.5.2 (138edd61fd100ec658bfa2d307c43b76940a5d7d; 2017-10-18T08:58:13+01:00)
Maven home: /Users/bamcgill/.mvnvm/apache-maven-3.5.2
I experienced the same error. I fixed it by upgrading from Maven 3.3.3 to Maven 3.6.3. I am not sure whether that fix is related to this question, because I did not debug my issue.

Execute Jar: Main class cannot be loaded or found

I'm trying to build an executable jar file out of my project.
Since it's a Maven project, I'm trying to achieve it like this:
./mvnw package -Pdev -DskipTests
I get a jarfile out of that, so until here it's working fine. However, when I want to execute the jarfile with:
java -jar myproject-0.0.1-SNAPSHOT-jar-with-dependencies.jar
I get an error that the main class cannot be loaded or found.
I have already googled this issue and added the following lines to my pom.xml:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.david.coinlender.CoinlenderApp</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
</executions>
</plugin>
I have stated my mainClass package and class name, however, that doesn't help.
What I assume the problem could be: Inside the jar file there's a folder classes (with the compiled classes).
Do I need to somehow add a property classpathPrefix for the classes? I only use it for the libs so far.
Can anyone please help me?
Kind regards,
David
#Update:
When I open the JAR file, I see a completely different structure than my app structure. Let me post a screenshot of what I see:
Could there be a problem with building the JAR file?
addClassPath and classPathPrefix are for referencing local class or JAR files that exist outside the JAR file. These directives aren't needed for referencing a class that is contained in the JAR file already.
It sounds very strange that there's a folder classes in your JAR file. The class files should be directly at the top level, e.g.
$ jar tf myproject-0.0.1-SNAPSHOT-jar-with-dependencies.jar
META-INF/
META-INF/MANIFEST.MF
com/
com/david/
com/david/coinlender/
com/david/coinlender/CoinLenderApp.class
It sounds like your project isn't following the Maven standard directory layout, causing the class files to be stored in the wrong location. Could this be the cause of your problem?

Setting classpath for a java project with many libraries and external resources in command line

I have the following project. It has some property files in the conf folder, some data in the data folder, some jar files in the lib folder and also some external libraries that are not shown in the photo due to size limitation. Imagine I want to run the RecDriver class. How exactly should I set the classpath so that I can run it in command line? This is how I did it but it does not work as it cannot fine some other files in the project.
C:\Users\myUserName\Downloads\librec-2.0.0\librec-2.0.0\core\src\main\java\net\librec\tool\driver> javac RecDriver.java
The project can be downloaded here:
https://github.com/guoguibing/librec
You can use bin/librec or bin/librec.cmd to run it from commandline.
If you want to build your launch command you can see those start scripts and adapt them for your purposes.
To run your app through command line, once you have the .class files in some dir (usually build) all you have to do is run your application with java -cp "path where jvm can find every .class that you project needs" MainClass.
The -cp flag only tells where to look for compiled .class files, since you are using IntellIJ you can see the command it runs when executing your program, there is a class path that it uses.
Class Path points to where your .class files are, they can be in separate folders, but you need to include every dir when giving the class path, separated by ";"
Example taken from another question in SO.
java -cp "Test.jar;lib/*" my.package.MainClass
Three things to do:
Use the Maven Shade Plugin to create a fat jar (jar with dependencies)
Use the Maven-Jar-Plugin to make the Jar executable
Set <project><build><finalName> to ${artifactId}
Now, after your build ran successfully, you can run your app with
java -jar target/YourArtifactId.jar
(Substitute your project's artifactId for "YourArtifactId")
Okay, here's the full setup.
Add a build section like this to your pom.xml (merge it with any existing one).
<build>
<plugins>
<!-- number 1 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<minimizeJar>true</minimizeJar>
</configuration>
</execution>
</executions>
</plugin>
<!-- number 2 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>fully.qualified.MainClass</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
<!-- number 3 -->
<finalName>${project.artifactId}</finalName>
</build>

How maven jar project works when it is packaged to jar?

I am new to maven. I have created a maven project which will be packaged to JAR. I did clean package then jar is created. When i extracted the same jar, i could not see any dependencies (jars) i added in pom.xml inside the packaged jar. If i give this jar to third party clients how will the code work without any dependent jars ? Please help me how maven manages the jars?
Thanks!
Maven handles dependencies based on how you configure the dependency plugin.
See this reference for a simple example of how to do this.
In this example, the following code configures where your dependencies will end up:
<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>
<includeGroupIds>log4j</includeGroupIds>
<outputDirectory>${project.build.directory}/dependency-jars/</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
Then this code sets up the classpath for your main jar, which will allow anyone running it to find these dependencies
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.mkyong.core.App</mainClass>
<classpathPrefix>dependency-jars/</classpathPrefix>
</manifest>
</archive>
</configuration>
</plugin>
Your other option would be to create a single jar, with all dependencies included, by following this example here
You could distribute the jar and the POM file if you want to try and provide your users with the files in that manner, but they'd need to be able to access your Maven repository where those dependencies are kept.
Core maven doesn't handle this. Maven is a build tool, its work is to build an artifact (a jar in your case). Dependencies you define in your module's pom.xml file are needed to get the code compiled. You'll need maven plugins to do so.
Now, you're asking not about the build, but the distribution of your compiled binaries.
If I understand it should be a lot of jars (your and your dependencies). Alternatively you may distribute the code as a jar + dependencies inside.
Example:
A first case:
If your code resides in module A (say, the code is in packages org.a.*) and depends on some thirdparty (say, log4j, whose classes reside in org.apache.log4j) than you can expect that you jar will only contain the classes of module a and you expect that the log4j will be added by the user of your module automatically (The first case).
A second case:
module a.jar will contain both org.a.* and org.apache.log4j.* classes, everything in the same module.
In general the first approach is more "healthy" and in this case you shouldn't do anything in maven. Maybe your distribution tool/documentation should contain this information.
If someone uses the module a in his/her code like a thirdparty (if you develop a framework or something) and if his/her project is mavenized, than the fact you've defined a dependency on log4j will make the maven to download the log4j as well as your a.jar (In maven notation, this is called "transitive dependencies").
If you're interested in the second case (this can be relevant if you define some "client application", like "jndi client for some server" for example) you might want to take a look on Maven shade plugin
Beware this can lead to dependency hell (what if the application that uses your client also makes use of log4j? what if the log4j-s are of different version)/
Bottom line, you probably want the first approach, think twice before you decide the second approach :)
One more tip, if you just want to download all the dependencies of your module "a" you might want to use maven dependency plugin - type the following in the command prompt
mvn dependency:copy-dependencies
and you'll find all the dependencies in target/dependencies folder
Hope this helps and happy mavening
The simplest solution to the problem is to use the maven-assembly-plugin which can create such jar with dependencies like the following:
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<id>distro-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Afterwards you can distribute the created jar xyz-1.0-jar-with-dependencies which contains the defined dependencies.
If you need more control on how the resulting artifact is created or if some files needed to be overwritten etc. you might take a deeper look into maven-shade-plugin

Categories