Add external properties file to classpath - java

My application is packaged into a jar file and is run with the regular "java -jar ..." command.
I have a properties file "myApp.properties" in the directory: /opt/myuser/resources
I want to add the /opt/myuser/resources directory to the classpath. I believe this is advantageous because when the properties files are on the classpath, I can access the properties files in my source code without specifying the full path to the properties files (/opt/myuser/resources/myApp.properties). This way I can keep a properties file with environment-specific properties separate from my application.
I've tried to set the classpath using instructions from Oracle (http://docs.oracle.com/javase/7/docs/technotes/tools/solaris/classpath.html under "Using the JDK tools' -classpath option") like this:
java -cp .:/opt/myuser/resources -jar myApp.jar
but I get an error that the properties file myApp.properties (referenced in the source code) cannot be opened:
Caused by: java.io.FileNotFoundException: class path resource [myApp.properties] cannot be opened because it does not exist
Am I going about this the wrong way? Should I edit the classpath in another way?

Hopefully this will help someone else.
I've used as program arguments for spring boot
--spring.config.location=file:/opt/myuser/resources/myApp.properties
and then it will use that file.

pass this parameter in VM options/environment variables
-Dspring.config.location=/deployments/tomcat/instance-conf/myApp.properties

use gerResource solutions to load file on your Properties Object:
ClassLoader.getResourceAsStream ("some/pkg/resource.properties");
Class.getResourceAsStream ("/some/pkg/resource.properties");
ResourceBundle.getBundle ("some.pkg.resource");

Related

How to access outside file from java jar

I have a jar that is reading a file using below code:
Thread.currentThread().getContextClassLoader().getResource(fileName);
I want to run this jar using java -jar .jar command but I want to keep this file outside my jar, so that I can edit the jar file later on without touching the jar. Can anyone help me, how to run this jar so that it will pick up the file from outside.
There are multiple approaches you can do that and it will depend on where would you like to place this external file. For the sake of this answer, I will refer to this file as config file
Not In The Same Directory
The first approach is where you will need to place this file outside the JAR and not necessarily next to the JAR file in the same directory. In that case, you can pass the file location of the config file using either an environment variable (if you are running the JAR in a shell for example) or a Java property.
To use an environment variable, assuming you are using some Linux distro, then you can use the export command to set the value; something like this:
$ export CONFIG_FILE_LOC=/etc/myapp/config.file
You can then read the value in your code using the System class by using the following code:
String fileLocationEnv = System.getenv("CONFIG_FILE_LOC");
Alternatively, you can set this as a property by adding the following segment to your launch command:
$ java -Dconfig.file.location=/etc/myapp/config.file -jar myapp.jar
You can then read the value in your code using the System class for properties using the following code:
String fileLocationProp = System.getProperty("config.file.location");
In The Same Directory
If you need the config file to co-exist in the same directory as your JAR file, then you can use the following code to get the JAR directory and then append the filename to it. Here's the code (assuming a class named MyApp)
try{
new File(MyApp.class.getProtectionDomain().getCodeSource().getLocation().toURI());
} catch(URISyntaxException exception){
System.out.println("Exception");
}
Hope that helps.
To open the file as a resoure, add the folder containing the file(s) you want to use, to your classpath:
java -classpath .;config -jar myjar.jar
This example adds the current directory and the config directory to your classpath.
Multiple folders can be specified by using a separator. On windows use ';' , on unix use ':' .
To open the file as a File, you can just use
new File("configfile")
which will look in the working directory (directory where you launched your java)

How can I dynamically use externalized properties file with Spring jar?

With this setup (from Eclipse using Windows10)
I was able to correctly start my SpringBoot application. This one worked too (same directory pattern):
Now I'm packaging my project as JAR and I want to use an external properties file. I had an teste32.yml file beside my JAR at the same directory (also tried to use it inside /config directory, as show here, but it didn't work either)
I want to dynamically use a properties file beside my JAR file everytime. Doesn't matter at which directory they are, I wanted to dynamically point to a properties file always at the same directory as the JAR is. I want to say to my client: "take this JAR and this file, put them wherever you want and run this command X and everything will be alright". I'm trying to discover command X but before I add some dynamic path, I'm trying with absolutes paths. I'm using this:
java -jar myJar.jar -Dspring.config.name=teste32 -Dspring.config.location=C:\workspace\myProject\target\
I manually copied teste32 inside target\ to test this. But this didn't work. This didn't work either (only spring.config.location variants):
-Dspring.config.location=file:C:\workspace\myProject\target\
-Dspring.config.location=classpath:/
-Dspring.config.location=file:C:/workspace/myProject/target/
I also tried with no spring.config.location, only name
So my questions are:
What does classpath: and file: mean? Until now I got the 2 correct setups by pure luck and I would like to understand when to use them.
When I have my project package as a JAR, what classpath becomes?
Finally, which combination is necessary to dynamically use a properties always at the same directory as the JAR?
UPDATE
Using --debug at the correct example got me this line at the very begging (Spring banner was still visible):
2018-09-25 15:45:14.480 DEBUG 11360 --- [ main] o.s.b.c.c.ConfigFileApplicationListener : Loaded config file 'file:src/main/resources/xirulei/teste32.yml' (file:src/main/resources/xirulei/teste32.yml)
But after moving myJar.jar and teste32.yml to a specific directory and running java -jar myJar.jar -Dspring.config.name=teste32 --debug (without spring.config.location, since teste32 is at the same directory as JAR), I simply didn't get any ConfigFileApplicationListener debug line.
a) java -jar myJar.jar -Dspring.config.name=teste32 -Dspring.config.location=C:\workspace\myProject\target
Did you check content of target dir? I'm pretty sure your cfg file is placed to target\classes\xirulei and it is why Spring cannot find it in target
b) When you place teste32.yml in the same directory as jar file then Spring must be able to find it (given this directory is working directory) without -Dspring.config.location (but you still need to provide -Dspring.config.name=teste32)
c) When you use -jar and do not provide additional class paths then classpath: points to the root of packages inside jar. Spring cannot find your file at classpath:/ because your file is at classpath:/xirulei/
Well, after all it was a simple mistake. As documentation says and as already pointed here, it should be
java -jar myproject.jar --spring.config.name=myproject
and not
java - jar myproject.jar -Dspring.config.name=myproject
As stated on question, only when using Eclipse -D(JVM argument) is necessary. When using bash/cmd, just --(program argument) is the correct option:

How to override the database.properties bundled in the jar

Using ActiveJDBC (version 1.4.13), I can't find a way to override the database.properties bundled with the application (the one from src/main/resources/database.properties ending inside the jar).
Is there a way to override it with a local file (in the same vein as with application.properties in Spring Boot)?
Please, see documentation here: http://javalite.io/database_connection_management#using-system-property
Basically, provide the location of your database.properties file as a system property:
java com.company.project.Main -cp myprogram.jar -Denv.connections.file=/path/to/file/database.properties
However, if it does not work for you, it is because of this bug that was fixed in Feb 2018:
https://github.com/javalite/activejdbc/issues/681
so, if this configuration does not work, keep in mind that the file is searched on the classpath. This means that if you put your file somewhere on the file system and list the directory of this file first on your classpath, your file will be found first as opposed to the one packaged into the Jar file.
So, if your file is: /opt/project/dir1/database.properties, you can start your process:
java -classpath /opt/project/dir1/:$CLASSPATH com.yourcompany.Main
then the file /opt/project/dir1/database.properties will be loaded first.

Java : How to include a .properties file that is outside of jar into classpath?

We would like to keep the .properties file out of the jar so that we can change the properties used in a module and we do not have to re-install the module.
Before Java 8, we used to run a script and include the .properties file in the way below and it worked. But since when we updated to Java 8 , this way of including .properties file in classpath is not working, means java program fails not finding the .properties file.
My script to run the java project:
/usr/java/latest/bin/java -d64 -Xms1G -Xmx16G -XX:MaxPermSize=128m -XX:-UseGCOverheadLimit -cp "/online/sand/lib/client-api-1.0.0.jar:/online/sand/oap_pub/lib/*:/online/sand/oap/oap_dw/run/client_api/application.properties" team.online.client.api.MasterProcessor | tee -a client_api.log
We are using Sping context to pick up the properties file this way:
<util:properties id="app_props"
location="classpath*:/application.properties" />
Then a property in that appilcation.properties files is being used ( in many different files) this way:
#Value( "#{app_props[\"SERVICE_PATH_GET_METADATA\"]?:''}" )
private String metadataServicePath;
Looking for a way to keep the.properties file out of the jar and in classpath so that Spring context finds that file.
Is their any other way than using ? We need to keep the properties file excluded from jar
class.getClassLoader( ).getResourceAsStream( "application.properties" );
Thanks in advance.
Use this if you are using xml based config
<context:property-placeholder location="classpath:application.properties"/>
Then it will load the properties from anywhere as long as it is in class path not in the jar. You have to include it in class path as $CLASSPATH:application.properties
For annotation based, #PropertySource("classpath:application.properties")
There is a sample here
Java: read properties file using spring annotations
I found a workaround making changes in the script to run the program by using "::" instead of ":" .
Got the idea :
==> java and javac are handling the classpath settings in a different way,
javac is searching for classes in / if the classpath contains double Classpath delimiters ("::" under Unix, ";;" under Windows).
From this link which seemed convincing to me and that works. Please take a look here:
https://bugs.openjdk.java.net/browse/JDK-4809833

What exactly is a class path in java?

I wrote a program that works on my laptop perfectly, but I really want it to work on a server that I have. Using NetBeans, I've clean and built the project. I copied the contents of the folder dist on my server but I cannot seem to get to work by using command
java -jar nameOfFile.jar
I get the error
java.lang.NoClassDefFoundError: org/....
I have been doing some reading and from what I gather is that I need to pretty much specify where the libraries that I've used are located. Well they are located in a subfolder called lib.
Question:
So what would I need to do in order to be able to run my jar?
CLASSPATH is an environment variable that helps us to educate the Java Virtual Machine from where it will start searching for .class files.
We should store the root of the package hierarchies in the CLASSPATH environment variables.
In case of adding or using jar libraries in our project, we should put the location of the jar file in the CLASSPATH environment variable.
Example: If we are using jdbc mysql jar file in our java project, We have to update the location of the mysql jar file in the CLASSPATH environment variable. if our mysql.jar is in c:\driver\mysql.jar then
We can set the classpath through DOS in Windows
set CLASSPATH=%CLASSPATH%;c:\driver\mysql.jar
In Linux we can do
export CLASSPATH=$CLASSPATH:[path of the jar]
Hope it helps!
Try that:
java -classpath "$CLASSPATH:nameOfFile.jar:lib/*" path.to.your.MainClass
What this does is setting the classpath to the value of $CLASSPATH, plus nameOfFile.jar, plus all the .jar files in lib/.
Classpath
A compiler(e.g. javac) creates from .java - .class files and JVM uses these .class files.
classpath - local codebase[About] - points on the root of source. classpath + import_path = full path
For example for MacOS
//full path
/Users/Application.jar/my/package/MainClass
//classpath
/Users/Application.jar
//import_path
my.package.MainClass
Android classpath
ANDROID_HOME/platforms/android-<version>/android.jar
//e.g
/Users/alex/Library/Android/sdk/platforms/android-23/android.jar
When you use a META-INF/MANIFEST.MF file to specify the Main-Class dependencies must be specified in the manifest too.
The -jar switch ignores all other classpath information - see the tools docs for more.
You need to set class path using
The below works in bash .
This is temporary
set CLASSPATH=$CLASSPATH=[put the path here for lib]
If you want it permanent then you can add above lines in ~/.bashrc file
export CLASSPATH=$CLASSPATH:[put the path here for lib]:.
You have 2 questions, one is the "title question" and another is the "foot note question" after elaborating your problem.
Read this documentation bellow to get a better understanding of CLASSPATH.
https://docs.oracle.com/javase/tutorial/essential/environment/index.html
https://docs.oracle.com/javase/8/docs/technotes/tools/windows/classpath.html
This is fast and straight forward for what you need.
For your first question, this will do:
The documentation recommends us to set a classpath for every application we are running at the moment using (use in the command-line):
java -classpath C:\yourDirectoryPath myApp
For your second question, look this exercise in the java documentation. It seems to be the same problem:
https://docs.oracle.com/javase/tutorial/essential/environment/QandE/answers.html
Answers to Questions and Exercises: The Platform Environment
Question 1.A programmer installs a new library contained in a .jar file. In order to access the library from his code, he sets the CLASSPATH environment variable to point to the new .jar file. Now he finds that he gets an error message when he tries to launch simple applications:
java Hello
Exception in thread "main" java.lang.NoClassDefFoundError: Hello
In this case, the Hello class is compiled into a .class file in the current directory — yet the java command can't seem to find it. What's going wrong?
Answer 1. A class is only found if it appears in the class path. By default, the class path consists of the current directory. If the CLASSPATH environment variable is set, and doesn't include the current directory, the launcher can no longer find classes in the current directory. The solution is to change the CLASSPATH variable to include the current directory. For example, if the CLASSPATH value is c:\java\newLibrary.jar (Windows) or /home/me/newLibrary.jar (UNIX or Linux) it needs to be changed to .;c:\java\newLibrary.jar or .:/home/me/newLibrary.jar."

Categories

Resources