How to run Java program in terminal with external library JAR - java

This should be simple but I have never done it before and didn't find any solution.
I am currently using Eclipse to code my program, which imports some external JAR library such as google data api library. I can use Eclipse to compile/build/run the program.
But now I want to run it in terminal, so where should I put those JAR files, and how to build and run the program?
Thanks!

You can do :
1) javac -cp /path/to/jar/file Myprogram.java
2) java -cp .:/path/to/jar/file Myprogram
So, lets suppose your current working directory in terminal is src/Report/
javac -cp src/external/myfile.jar Reporter.java
java -cp .:src/external/myfile.jar Reporter
Take a look here to setup Classpath

For compiling the java file having dependency on a jar
javac -cp path_of_the_jar/jarName.jar className.java
For executing the class file
java -cp .;path_of_the_jar/jarName.jar className

you can set your classpath in the in the environment variabl CLASSPATH.
in linux, you can add like
CLASSPATH=.:/full/path/to/the/Jars, for example ..........src/external
and just run in side ......src/Report/
Javac Reporter.java
java Reporter
Similarily, you can set it in windows environment variables.
for example, in Win7
Right click Start-->Computer
then Properties-->Advanced System Setting --> Advanced -->Environment Variables
in the user variables, click classPath, and Edit and add the full path of jars at the end.
voila

Suppose your jar application "myapp.jar" has the following code snippet written inside it.
import org.json.JSONObject;
public class Main {
public static void main(String[] args) {
// write your code here
System.out.println("Hello World!");
JSONObject jo = new JSONObject("{ \"abc\" : \"def\" }");
System.out.println(jo.toString());
}
}
It is using the external library json.jar from which we imported "org.json.JSONObject".
Running the following command will result in an error.
java -jar myapp.jar
Exception message:
Exception in thread "main" java.lang.NoClassDefFoundError: org/json/JSONObject at com.reve.Main.main(Main.java:10)
Caused by: java.lang.ClassNotFoundException: org.json.JSONObject at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(Unknown Source) at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(Unknown Source) at java.base/java.lang.ClassLoader.loadClass(Unknown Source)
... 1 more
We must include the json.jar file while running the jar file. We have to specify the class path of the file before building our myapp.jar file.
Inside META-INF/MANIFEST.MF file:
Manifest-Version: 1.0
Class-Path: lib/json.jar lib/example2.jar
Main-Class: com.reve.Main
Specify the external libraries separated by spaces under the Class-Path keyword. Then after building the project and the artifact, we can run the jar file by simply writing the same command we discussed above.

Related

Problem with java classpath when executing jar

I am trying to execute a java application, which is packaged as jar archive.
java -cp .\lib\json.jar -jar ".\myarchive.jar"
I get an error saying that the classes inside my json.jar archive cannot be found.
Exception in thread "main" java.lang.NoClassDefFoundError: json/serializers/JsonTypeResolversInstance
Caused by: java.lang.ClassNotFoundException: json.serializers.JsonTypeResolversInstance
at java.net.URLClassLoader.findClass(URLClassLoader.java:387)
at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352)
at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
... 2 more
The jar file contains the class, so i think this error should not happen. When executing the code using my IDE it runs without errors.
I have tried to fix this in many ways, without success.
Using the -cp and -jar options at the same time does not work. When you use the -jar option, then the -cp option is ignored.
There are two ways to run code in a JAR file in Java.
First way: Use the -cp option and specify the name of the class that contains the main method on the command line. For example:
java -cp .\lib\json.jar;.\myarchive.jar com.mypackage.MyMainClass
When you do it like this, you specify the classpath on the command line (using -cp). The classpath must contain all JAR files and/or directories that contain all the classes that the application needs. You must also specify the name of the class to run on the command line.
Also, when you do it like this, the manifest file that might be present in the JAR file is ignored.
Second way: Use the -jar option. For example:
java -jar .\myarchive.jar
When you do it like this, then Java will look at the manifest file in the JAR file. The classpath and the name of the class to run will be taken from the manifest file, and the -cp option on the command line will be ignored.
For details see the documentation of the java command.

JAR file is not read even though added in class path

I have a shell script which runs a java class presnet in /opt/mydir/ directory. In this script I am adding the class file along with few other jar files to the java classpath.
Ex:
/usr/bin/java -cp "/opt/mydir"
When the script is run, the java .class file fails with
Exception in thread "main" java.lang.NoClassDefFoundError: com/internal/altsite
The com.inetrnal.altsite comes from an external jar, and is also present in the same classpath as the main class file.
If i add the name of the jar explicitly to the classpath, the shell script runs successfully without any error. Ex:
/usr/bin/java -cp "/opt/mydir:/opt/mydir/altsite.jar:"
The directory structor is as follows:
-/opt
---mydir/
-------runner.class,altsite.jar,jose4j.jar

Unable to compile using Picocli

I'm a dev student
I would love to use Picocli in my project, unfortunately I doesn't understand how to compile using Picocli
I trie to follow the instruction given here https://picocli.info/ or here https://picocli.info/quick-guide.html but the step to compile aren't detailed. I'm not using Gradle nor Maven but they aren't really listed as required.
This is how it tried to compile the Checksum example given in the picocli.info webpage :
jar cf checksum.jar Checksum.java ; jar cf picocli-4.6.1.jar CommandLine.java && echo "hello" > hello
Then I simply copy paste this gived command : https://picocli.info/#_running_the_application
java -cp "picocli-4.6.1.jar:checksum.jar" CheckSum --algorithm SHA-1 hello
And get the following result :
Error: Could not find or load main class CheckSum
Caused by: java.lang.ClassNotFoundException: CheckSum
I tried to compile everything myself and then add the .jar like this :
java CheckSum -jar picocli-4.6.1.jar
But then the error output looks like this:
Exception in thread "main" java.lang.NoClassDefFoundError: picocli/CommandLine
at CheckSum.main(Checksum.java:33)
Caused by: java.lang.ClassNotFoundException: picocli.CommandLine
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
... 1 more
Witch I don't understand since I added the dependency.
What am I missing ?
Thanks in advance
The problem is that the command jar cf checksum.jar Checksum.java only creates a jar file (jar files are very similar to zip files) that contains the Checksum.java source file.
What you want to do instead is compile the source code first. After that, we can put the resulting Checksum.class file (note the .class extension instead of the .java extension) in the checksum.jar. The Java SDK includes the javac tool that can be used to compile the source code. Detailed steps follow below.
First, open a terminal window and navigate to a directory that contains both the Checksum.java source file and the picocli-4.6.1.jar library.
Now, the command to compile (on Windows) is:
javac -cp .;picocli-4.6.1.jar Checksum.java
Linux uses : as path separator instead of ;, so on Linux, the command to compile is:
javac -cp .:picocli-4.6.1.jar Checksum.java
The -cp option allows you to specify the classpath, which should contain the directories and jar/zip files containing any other class files that your project uses/depends on. Since Checksum.java uses the picocli classes, we put the picocli jar in the classpath. Also add the current directory . to the classpath when the current directory contains any classes. I just add . habitually now.
Now, if you list the files in the current directory, you should see that a file Checksum.class has been created in this directory.
Our Checksum class has a main method, so we can now run the program with the java tool:
On Windows:
java -cp .;picocli-4.6.1.jar Checksum
On Linux:
java -cp .:picocli-4.6.1.jar Checksum
Note that when running the program with java you specify the class name Checksum, not the file name Checksum.class.
You can pass arguments to the Checksum program by passing them on the command line immediately following the class name:
java -cp .:picocli-4.6.1.jar Checksum --algorithm=SHA-1 /path/to/hello
When your project grows, you may want to keep the source code and the compiled class files in separate directories. The javac compile utility has a -d option where you can specify the destination for the compiled class files. For example:
javac -cp picocli-4.6.1.jar:otherlib.jar -d /destination/path /path/to/source/*.java
This should generate .class files for the specified source files in the specified destination directory (/destination/path in the example above).
When you have many class files, you may want to bundle them in a single jar file. You can use the jar command for that. I often use the options -v (verbose) -c (create) -f (jar file name) when creating a jar for the compiled class files. For example:
jar -cvf MyJar.jar /destination/path/*.class /destination/path2/*.class
Enjoy!

Read properties file from classpath (non-maven)

When I try to run my jar from another directory it cannot see the "config" folder with the "url.properties" file in it.
Inside MyProperties class I have the following code, which runs perfectly when run from the same dir:
Properties properties = new Properties();
FileInputStream in = new FileInputStream("./config/url.properties");
properties.load(new InputStreamReader(in, Charset.forName("UTF-8")));
in.close();
The class that contains this code is in the following tree:
myproject\MyAppClass.class
myproject\data\MyProperties.class
It runs fine if I run this jar which contains the above piece of code by doing:
C:\myjarfolder\>java -jar myApp.jar
But it does not find "url.properties" inside "config" and returns a error if I do:
C:\>java -jar c:\myjarfolder\myApp.jar
Obviously it seems a classpath problem, so I try the following without success and return the same "file not found" error:
C:\> java -cp "c:\myjarfolder\*;c:\myjarfolder\config" myproject.MyAppClass
C:\> java -cp "c:\myjarfolder\*;c:\myjarfolder\config\" myproject.MyAppClass
C:\> java -cp "c:\myjarfolder\*;config" myproject.MyAppClass
C:\> java -cp "c:\myjarfolder\*;config\" myproject.MyAppClass
C:\> java -cp "c:\myjarfolder\*;\config\" myproject.MyAppClass
C:\> java -cp "c:\myjarfolder\*;c:\myjarfolder\config\url.properties" myproject.MyAppClass
And many other variants with and without quotes, all without success.
Then I thought it could be a loaded resources problem and tryed to change the InputStream(its in a static method):
Properties properties = new Properties();
properties.load(MyProperties.class.getClassLoader().getResourceAsStream("./config/url.properties"));
and then
properties.load(MyProperties.class.getClassLoader().getResourceAsStream("config/url.properties"));
This way it does not work even when running in the same folder.
I also tried to put the config folder in the class-path: inside manifest. Dind't worked.
I tried many things I found here on stack and none seems to work.
Is there a way to make the first option (without getresources) to run from another dir?
If I somehow make it load from getResource, will it run from another dir if I refer the class path?
When using absolute locations like FileInputStream("./config/url.properties"):
Add the config folder inside the jar. From the IDE you can add it as a source and it will compile the folder inside the jar automatically. Then it can be run with "java -jar c:\myjarfolder\myJar.jar" from another folder no problem.
When using getResources("url.properties"):
Can't use the absolute location here or it will be the same problem as before, so to let the folder outside the jar and add it to the classpath (you may not run it from the IDE if not added to the run parameters classpath or the manifest).
The folder can be added by running it like:
'java -cp "c:\myjarfolder*;c:\myjarfolder\config" myproject.MyAppClass'
Also, it can be added to the MANIFEST.MF class-path, as example "class-path: config/".
(it only worked here with "/") and can be run with "java -jar c:\myjarfolder\myJar.jar".
I don't think this is a normal issue people will encounter because normaly you run the jar from the same location it is. But we were creating a RDP to run from server where it can't run the jar it self, but using the java.exe.

How do I run Java .class files?

I've compiled a HelloWorld program, and I'm using the command prompt to run it. The .class file is named HelloWorld2.class
The file is located in C:\Users\Matt\workspace\HelloWorld2\bin
Here's what I'm getting when I go to command prompt, and type "Java HelloWorld2" :
C:\Users\Matt>Java HelloWorld2
Exception in thread "main" java.lang.NoClassDefFoundError: HelloWorld2
Caused by: java.lang.ClassNotFoundException: HelloWorld2
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
Could not find the main class: HelloWorld2. Program will exit.
I was expecting to see a HelloWorld printed out. What am I doing wrong? I have the JDK installed.
If your class does not have a package, you only need to set the classpath to find your compiled class:
java -cp C:\Users\Matt\workspace\HelloWorld2\bin HelloWorld2
If your class has a package, then it needs to be in a directory corresponding to the package name, and the classpath must be set to the root of the directory tree that represents the package.
// Source file HelloWorld2/src/com/example/HelloWorld2.java
package com.example;
...
Compiled class file: HelloWorld2/bin/com/example/HelloWorld2.class
$ java -cp HelloWorld2/bin com.example.HelloWorld2
To run Java class file from the command line, the syntax is:
java -classpath /path/to/jars <packageName>.<MainClassName>
where packageName (usually starts with either com or org) is the folder name where your class file is present.
For example if your main class name is App and Java package name of your app is com.foo.app, then your class file needs to be in com/foo/app folder (separate folder for each dot), so you run your app as:
$ java com.foo.app.App
Note: $ is indicating shell prompt, ignore it when typing
If your class doesn't have any package name defined, simply run as: java App.
If you've any other jar dependencies, make sure you specified your classpath parameter either with -cp/-classpath or using CLASSPATH variable which points to the folder with your jar/war/ear/zip/class files. So on Linux you can prefix the command with: CLASSPATH=/path/to/jars, on Windows you need to add the folder into system variable. If not set, the user class path consists of the current directory (.).
Practical example
Given we've created sample project using Maven as:
$ mvn archetype:generate -DgroupId=com.foo.app -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
and we've compiled our project by mvn compile in our my-app/ dir, it'll generate our class file is in target/classes/com/foo/app/App.class.
To run it, we can either specify class path via -cp or going to it directly, check examples below:
$ find . -name "*.class"
./target/classes/com/foo/app/App.class
$ CLASSPATH=target/classes/ java com.foo.app.App
Hello World!
$ java -cp target/classes com.foo.app.App
Hello World!
$ java -classpath .:/path/to/other-jars:target/classes com.foo.app.App
Hello World!
$ cd target/classes && java com.foo.app.App
Hello World!
To double check your class and package name, you can use Java class file disassembler tool, e.g.:
$ javap target/classes/com/foo/app/App.class
Compiled from "App.java"
public class com.foo.app.App {
public com.foo.app.App();
public static void main(java.lang.String[]);
}
Note: javap won't work if the compiled file has been obfuscated.
This can mean a lot of things, but the most common one is that the class contained in the file doesn't have the same name as the file itself. So, check if your class is also called HelloWorld2.
Go to the path where you saved the java file you want to compile.
Replace path by typing cmd and press enter.
Command Prompt Directory will pop up containing the path file like C:/blah/blah/foldercontainJava
Enter javac javafile.java
Press Enter. It will automatically generate java class file

Categories