I saw running jar from command line.
However my case is different. I put the jars needed for the main class under lib folder. So my jar is like this:
lib
META-INF
VideoFieldsResults.class
in the META-INF I have:
Manifest-Version: 1.0
Main-Class: VideoFieldResults
when I try to run:
java -jar VideoFormat.jar onBa32hgnBg,Lh-BKkLYYBU C:\VideoFormat2.csv
Where the last 2 are arguments I get:
Exception in thread "main" java.lang.NoClassDefFoundError: com/google/gdata/util
/ServiceException
Which does exists under one of the jars inside!
How can I run a command line specifying that all the jars under lib folder inside are required for the jar?
By default, Java cannot load jars from within jars. To accomplish this, you would need a classloader that can handle it. For example One-Jar. There are other options as well (depending on how set you are with including jars inside of a jar or if flattening jars is an option), I'd recommend the answer to this other question
Related
I'v got a simple java program. I'm developing in Eclipse, using gradle, and I'm logging with log4j2. This all works fine.
When I come to run from the command line, I do a gradlew build which works, but when I run the jar I get an error:
java -jar build\libs\testproj.jar
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/logging/log4j/LogManager
at com.xxxxxx.practice.App.<clinit>(App.java:17)
Caused by: java.lang.ClassNotFoundException: org.apache.logging.log4j.LogManager
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:602)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
... 1 more
I can see a bunch of log4j files in my userprofile.gradle folder, and I could run a gradle dist task and then got and unzip the resulting zip file and then point at the contents of that, but if there some way of avoiding this? Surely there's something I can add to the manifest or something so that I can run from the command line at will with no overhead?
To be clear, it's just the logging that has this problem. Other than that it runs, the tests work etc from the command line, and the logging works fine from eclipse.
Someplace in your eclipse project, you'll find a library (these end in .jar) named log4j.jar or org.apache.logging-log4j.jar or log4j-api.jar or something along those lines.
This jar contains the classes that are missing when you run this on the command line. Try it: jar tvf log4j.jar prints the contents of the jar and you'll find it contains, for example, org/apache/logging/log4j/LogManager.class.
During compilation and during running a java app, this class needs to be on the classpath. Eclipse is taking care of the compilation part of it.
If you run java as java com.foo.ClassName, the classpath is defined by the -cp parameter: java -cp testproj.jar:log4j.jar com.foo.yourapp.TestApp would work (use semicolon on windows instead). If you don't specify it, the system environment variable CLASSPATH is used, but you don't want that (you can run multiple java apps on one machine after all, so a global setting makes little sense).
If you run java using java -jar myjar.jar however, the classpath is solely taken from the jar file itself; inside the jar file is a file called META-INF/MANIFEST.MF and it contains (in text) key/value pairs. The relevant one is the Class-Path: foo.jar bar.jar entry: Space-separated listings of jar files, relative to the dir your jar is in.
You cannot use the -cp option when using the -jar option; the -cp option is ignored.
So, next steps:
I don't know if gradle made the Class-Path entry correctly. Best option is to use the jar or zip tool to unpack your jar to check that MANIFEST.MF file and see what's there. If there is, say, Class-Path: lib/log4j.jar in that file, then make sure that if testapp.jar is at /Users/Dev123456/project/testapp.jar, that that log4j jar is at /Users/Dev123456/project/lib/log4j.jar. If there is no class-path entry, then the error lies in your gradle config; you'd have to post your build.gradle file in that case.
There are 'striper plugins' which mix all the various jars together in one giant jar. This is usually a bad idea (it just makes the jar itself humongous, and makes builds take longer. If you're deploying java code to a server, you can manage the Class-Path entry by yourself, and if you are making a desktop app, you need an installer which... can manage the class-path stuff just as well. Really no reason to use stripers). I advise against using these.
Just run with java -cp yourapp.jar:dep1.jar:dep2.jar com.foo.fullyqualified.ClassName instead.
Try to run your jar by specifying Log4j jar as well in classpath and then mention your MainClass from testproj.jar :
java -cp build\libs\testproj.jar:build\libs\log4j.jar com.package.MainClass
I've got a project that is structured liked so:
root/
-- lib/
---- commons-cli-1.2.jar
-- src/
---- my/package/name/*.java
-- bin/
---- my/package/name/*.class
-- .classpath
-- .project
-- manifest.mf
The *.class files in bin/ are made by Eclipse each build. My .classpath has the lib/ included and compiles just fine; it also runs as a "Java Application" just fine with my current stubs.
The issue comes about when I try to create a JAR and include the lib/ dependencies. From the command line I've been issuing:
jar cvfm prog.jar manifest.mf -C bin/ .
The program builds, and then when I try to run java -jar prog.jar, I get:
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/cli/Option... (there is more, but I cant copy from the other machine)
My manifest.mf looks like:
Manifest-Version: 1.0
Main-Class: my.package.Main
Class-Path: ./lib/commons-cli-1.2.jar
Seems to me that the Class-Path isn't being included and the JAR cannot find the classes contained in the commons-cli-1.2.jar. I've isolated this to JAR creation, since I can run the compiled classes with no issue.
What am I doing wrong when creating the JAR and including the lib/*.jar?
I have had issues with specifying classpath in the manifest file before. If I were you, I would skip referencing the required libraries in the manifest file and instead include them directly inside your jar. Eclipse allows you to easily do this link
You probably assume that the build process should pull the commons JAR into the new that holds your classes. Wrong assumption.
The default Java approach is that you only include your classes in your jar. But instruct your users that they need to have the commons jar in their class path as well!
I am trying to run my jar file on a Mac (Haven't yet tried on any other platform). When I run using java -jar MyApp.jar I get the following error
Stacktrace:
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/log4j/Logger
at tabalchi.MyLogger.getLogger(MyLogger.java:51)
at tabalchiApp.TabalchiApp.printSystemProps(TabalchiApp.java:117)
at tabalchiApp.TabalchiApp.main(TabalchiApp.java:37)
So, as you can see the main class is recognized.
This is the manifest file.
--->
Manifest-Version: 1.0
Class-Path: . jars/log4j-1.2.16.jar jars/jfugue-4.1.0-20120125.jar jars/gervill.jar jars/AppleJavaExtensions.jar
Main-Class: tabalchiApp.TabalchiApp
SplashScreen-Image: tabalchiApp/resources/splash.png
<---
And the folder structure in the jar file as follows.
--->
META-INF/MANIFEST.MF
jars/AppleJavaExtensions.jar
jars/gervill.jar
jars/jfugue-4.1.0-20120125.jar
jars/log4j-1.2.16.jar
tabalchiApp/TabalchiApp.class <-- this is the main class
tabalchiApp/otherClasses.....class
<---
I have read many posts about running .jar file but none of the solutions have worked for me. I would really appreciate your help on this one.
I am creating the jar file by exporting from eclipse. If I export to a runnable jar file then I cannot control the making of the manifest file. I need to add the splash image in the manifest file. And I am having some other issues with the runnable jar export. Hence this path.
It seems that log4j is missing.it is expecting jars/log4j-1.2.16.jar in class path .
jars/log4j-1.2.16
should be under folder structure.
jars/log4j-1.2.16.jar
In which directory are you trying to use:
java -jar MyApp.jar
You can specify the packages/directories in the classpath to be sure they are found.
Ok, so according to this link,
http://docs.oracle.com/javase/tutorial/deployment/jar/downman.html
The Class-Path header points to classes or JAR files on the local network, not JAR files within the JAR file or classes accessible over internet protocols. To load classes in JAR files within a JAR file into the class path, you must write custom code to load those classes. For example, if MyJar.jar contains another JAR file called MyUtils.jar, you cannot use the Class-Path header in MyJar.jar's manifest to load classes in MyUtils.jar into the class path.
So, it seems I cannot include other jar files in my jar file.
I am currently trying to make a Jar with all my libraries included.
What I have done.
I have created folders like this :
main folder
class (which contain all my classes)
ressources (containing all my libraries : mongo, jedis...)
MANIFEST.MF
My main class is named process.
My manifest is like this:
Main-Class: process
Class-Path: ressources\commons-pool-1.5.6.jar ressources\jedis-2.0.0.jar resources\mongo-2.6.3.jar class
I have generated the JAR with this command :
jar cvmf MANIFEST.MF process.jar class/*.class ressources/*.jar
My problem : When executing the JAR I have still the message
Exception in thread "main" java.lang.NoClassDefFoundError: process
Any ideas ?
Are you using eclipse? If yes, it have an option in export to export libraries together with jar..
with netbeans, I dont know how to do it.
You could build your jar with Ant using zipfilesets to copy in the content of the other jars (rather than the jars themselves), or you could take a look at jarjar which does that and more.
Eclipse: You have to add the external jar files to the build.properties, otherwise they are no tpart of the generated jar file.
Ar the libraries included in the jar file, you have generated?
I have a big project that uses maven and I'm creating the project's jar. The problems is that the project has several classes that can be executed. How can I accomplish this?
Every time that I try to execute a class I get this message
java -jar library.jar ExecutableClass1
Failed to load Main-Class manifest attribute from
library.jar
The manifest.mf file in your JAR can only have one Main-Class entry.
Main-Class: classname
The jar would then by executed by running below.
java -jar library.jar
If you have several "executables" that could be run then you can either pass command line parameters to the JAR and then run the correct code or you can generate multiple JAR files for each "executable".
A possible alternative to using the -jar switch is to explicitly start one of the "executables":
java -cp library.jar ExecutableClass1
If your jar has dependencies, then these will need adding to the classpath as well.