Can't add classpath through command line - java

I want to add the classpath through a command line call. The call looks like this:
java -cp ..\conf -jar ..\lib\switcher.jar
In the conf directory is an XML file that defines the application context and the log4j.properties file. But when I run this command, Java obviously can't find those two files, although I've added them to the class path.
I also tried specifying the absolute path of the conf directory, but it didn't work either.
Any hints?

If you use the -jar option, java.exe ignores the classpath. It will only look in that jar.
Try using the manifest Class-Path instead to get Java to look in auxiliary jars.

I guess your XML file may contain the used ClassPath ...
Unfortunatly, the java command doesn't understand any subtle way to express your class path. You HAVE to give it a list of directories/jar/zip. Any other way of setting the classpath will result in no action.

Related

slf4j over log4j configuration after deployment

I have built a java application and I've been using slf4j/log4j for logging. I would now like to provide the user with the possibility of changing logging levels without needing to re build the .jar file.
I've read around that to do this your properties file needs to be inside of the classpath of the application. I've tried using the Class-Path header in the MANIFEST.MF file to achieve this, however it is not working.
These are the two examples I've tried.
Class-Path:./config/
Class-Path:C:/users/user/directory/tools/config/
However none of these seem to be added to the classpath as I've tried printing its contents once the application starts running.
As suggested by this question, I ended up adding a parameter to the java execution command. Bear in mind that if you execute through bash commands, as I do, you need to add the full path to the directory.
java -Dlog4j.configuration=file:/path/to/log4j.properties -jar myApp.jar
I don't like this since it makes it extremely dependent on path configuration but it will suffice.
Please find below a list of possible solutions.
1) java -jar myApp.jar will search for the log4j.properties in following order
root of myApp.jar
the directories specified in the header Class-Path: of the myApp.jar
2) java -Dlog4j.configuration=file://path/to/file//log4j.properties -jar myApp.jar will use the properties file specified by -Dlog4j.configuration=...
3) java -Xbootclasspath/a:../config -jar myApp.jar will search for the log4j.properties in following order
directory ../config/
root of myApp.jar
the directories specified in the manifest header Class-Path: of the myApp.jar
I believe solution 1) should solve your problem like following
make sure there is no log4j.configuration in the root of myApp.jar
the manifest header contina for example Class-Path: config/
and the directory structure of your installation is
./myApp.jar
./config/
edit A possibe solution to avoid the hardcoded path, but use a defined location for the log4j.properties file could be as below.
assume following structure of your application
c:\somewhere\myApp.jar
c:\somewhere\config\log4j.properties
c:\somewhere\run_myapp.cmd
run_myapp.cmd
#echo off
... do your necessary preparation here
java -Dlog4j.configuration=file:%~dp0log4j_2.properties -jar myApp.jar
This will use always the config\log4j.properties relative to your myApp.jar.
%~pd - expands to drive letter and path of run_myapp.cmd
With this solution your users need to store the properties file at the given place but don't need to change the run_myapp.cmd script.

How to set CLASSPATH in Linux to let java find jar file?

Under Linux I am trying to run a jar file as follows:
java -jar plantuml.jar -testdot
while having CLASSPATH set to any of the following (the file is located at /home/user/plantuml.jar):
export CLASSPATH=/home/user
export CLASSPATH=/home/user/
export CLASSPATH=/home/user/plantuml.jar
In either case, no matter how I define CLASSPATH, the java command gives an error Unable to access jarfile plantuml.jar. What am I doing wrong here?
You have to supply the complete path after the parameter -jar. So for your example you have to call
java -jar /home/user/plantuml.jar -testdot
The $CLASSPATH is only evaluated to find additional files (classes/resources) but not the jar file defined in the command line.
export CLASSPATH="/path/to/class_or_jar1":"/path/to/class_or_jar2":"${CLASSPATH}"
Maybe you are missing name of the main class or path to the jar. Have you tried execute it:
java -jar full_path/plantuml.jar package.YourClass -testdot
Is your program depending on other classes? If yes you might want to add -cp parameter.
The classpath is used to find classes when you refer to them by name. It's essentially a list of paths (directories AND jar/zip files) where the JVM needs to look for classes, or other resources when using methods like ClassLoader.getResourceAsStream().
The value passed to the -jar option on the command line is the file-path to the JAR file.
So, it won't find a jar file if you are only referring to the jar file by name. The JAR file path in the CLASSPATH is supposed to be a path element that 'contains' other resources.
What you need to do here, is either
Provide the full path to the jar file when trying to execute the jar
Set the classpath to the jar file's path, and run the java command giving the name of the main class you want to execute.

How can I specify run-time variables in a jar's manifest file?

More specifically, when I run my java program from the command line before I jar it, I do something like this:
java -cp a.jar;b.jar;c.jar;. -Djavax.net.ssl.trustStore=jssecacerts Main
I can put the jar's into the Manifest file like so:
Class-Path: a.jar b.jar c.jar
And then create the jar file like this:
jar -cmf MANIFEST Main.jar Main.class
So that when I run it, I can just write:
java -jar Main.jar -Djavax.net.ssl.trustStore=jssecacerts
However, I'd like to simplify my command line even further and specify the -D variable inside the manifest if possible. Based on this reference:
http://docs.oracle.com/javase/tutorial/deployment/jar/manifestindex.html
It doesn't seem obvious how to do it, so I'm wondering if there's any way to do it.
You can't do it by setting anything in the manifest, however this provides some interesting alternatives that you might consider.
In general, you could put a properties file in your Jar file and access it via the classpath (Class.getResourceAsStream()) so that will have close to the same effect and you won't have to change your code when you need to reset properties.

Does java -jar option alter classpath options

I have a jar file which mentions the main class in the manifest.
When I try to execute the jar using the following command
java -cp .;./* com.foo.MainClass
The code executes and works.
When I try to execute the jar using the following command
java -cp .;./* -jar myjar.jar
I get class not found execptions for some jars which are in the same folder as myjar.jar. I hoping that the -cp option will include those jars in class path.
I modified my code to print java.class.path property. In the first case it listed all jars in the current directory, in second case it just listed myjar.jar
I also modified the manifest to add Class-Path element to it with all jars. Then the second command works. But in my code I am trying to load a aribtrary class whose name is provided at command prompt, so I want the class path to contain all jars in a folder. How do I make the second command work in this scenario?
From this,
An executable JAR must reference all the other dependent JARs it
requires through the Class-Path header of the manifest file. The
environment variable CLASSPATH and any class path specified on the
command line is ignored by the JVM if the -jar option is used.
You will need your own classloader to deal with this. -jar only respects the information in the Manifest and wildcards are not allowed there.
You might find the example of a reloadable class useful: http://www.exampledepot.com/egs/java.lang/ReloadClass.html
Here is a good discussion on this issue.

How can I add a .jar file dependencies when building it with the command line tool?

Pretty straightforward question. Can it be done without the use of Ants or Maven? (And by that, I mean the command line tool specifically)
Please notice that I don't want to create an uberjar, I just want the archived unit to "know" where its external dependencies are.
You can make it through META-INF/MANIFEST.MF. You can add other jars to the classpath like this:
Manifest-Version: 1.0
Main-Class: org.domain.MyMainClass
Class-Path: lib/slf4j-log4j12-1.5.8.jar lib/slf4j-api-1.5.8.jar
I believe, that it works only if you define Main-Class and start your application like this:
java -jar my-app.jar
Also notice, that classpath paths are relative to the main jar. So in my example directory structure should look like this:
my-app.jar
lib
slf4j-log4j12-1.5.8.jar
slf4j-api-1.5.8.jar
Presuming you're talking about a command line invocation of javac, what you're talking about is "can I provide libraries as arguments to javac to fulfill requirements during compilation".
Top entry for man javac says
-classpath classpath
Sets the user class path, overriding the user class path in the
CLASSPATH environment variable. If neither CLASSPATH or -class-
path is specified, the user class path consists of the current
directory. See Setting the Class Path for more details.
Effectively I suspect you just need to say
javac -classpath path/to/library1.jar Main.java
I think what you are looking for is a manifest file, Look here for more details
http://download.oracle.com/javase/tutorial/deployment/jar/downman.html

Categories