How to use SpringBoot PropertySource to read from an external configuration file - java

I've created a configuration class that will store configuration values. These configuration values should be read in from a configuration file "config.properties". Below is the config class:
#Configuration
#ComponentScan(basePackages = {"com.boot.Training.*"})
#PropertySource("file:/src/main/java/config.properties")
public class AppConfig {
#Value("${myFirstName}")
private static String myFirstName;
#Value("${myLastName}")
private static String myLastName;
public static void showVariables() {
System.out.println("firstName: " + myFirstName);
System.out.println("lastName: " + myLastName);
}
}
And below are the contents of the config.properties file:
myFirstName=John
myLastName=Doe
Running my program should simply print the values of these variables. But instead, Eclipse tells me it cannot find the config.properties file, even though I specified that it is located in /src/main/java/config.properties .
I'm likely specifying the file location without taking something else into account. What am I missing here?

The location you are using (file:/src/main/java/config.properties) refers to an absolute path rather than one relative to your project home.
A more common way to do this is to ship config.properties as part of your project in a resources directory, and refer to it via the classpath. If you move it to /src/main/resources/config.properties, you can load it this way:
#PropertySource("classpath:config.properties")
I believe in theory you could just leave it in /src/main/java and change your #PropertySource location to what I have above, but moving it to /resources is the more idiomatic way of doing this.

The basic way to specify a file: location to appoint a properties file that is located elsewhere on your host environment is:
#PropertySource("file:/path/to/application.properties")
Note that /path/to/application.properties should be absolute path pointing to your .properties file (in your example you are mixing file: usage and relative path which is not correct )
it is also possible to specify a system property or an environment variable that will be resolved to its actual value when your application starts. For example, ${CONF_DIR} below will be replaced with its associated value when the Spring application starts:
Open /etc/environment in any text editor like nano or gedit and add the following line:
CONF_DIR=/path/to/directory/with/app/config/files
Check it system variable has been set:
echo $CONF_DIR
/path/to/directory/with/app/config/files
use PropertySource like:
#PropertySource("file:${CONF_DIR}/application.properties")

Related

Spring include relative path in properties

I'm trying to make it so that in config/app.properties, I can have:
myfile.location=./myfile
where . is relative to said properties file. Is this possible ? I tried:
resourceLoader.getResource(appConfig.getMyFileLocation());
where resourceLoader and appConfig are autowired, but it won't work.
I usually reference my files like this:
myfile.location=classpath:myfile
where myfile is at the same location as the properties file.
Java properties are key-value pairs. So when you specify myfile.location=./myfile, this means appConfig.getMyFileLocation() will return './myfile' which is not the correct location.
As a workaround, you can get the location of the properties file and then use it along with the relative location to find the absolute path.
File propertyFileDirectory = .... // get the property file directory
String myfilePath = appConfig.getMyFileLocation();
File file = new File(propertyFileDirectory, myfilePath);

How to specify the path for getResourceAsStream() method in java

I know this question has been asked several times but I still can't get it work by those solutions.
I have a maven project. And one Config.java file located in consumer/src/main/java. Here's the content:
import java.util.Properties;
public class Config {
Properties configFile;
public Config() {
configFile = new Properties();
try {
configFile.load(this.getClass().getClassLoader().
getResourceAsStream("property_table.config.txt"));
} catch(Exception e) {
e.printStackTrace();
}
}
public String getProperty(String key) {
String value = this.configFile.getProperty(key);
return value;
}
public static void main(String[] args) {
Config config = new Config();
System.out.println("URL: " + config.getProperty("URL"));
System.out.println("PASSWORD: " + config.getProperty("PASSWORD"));
}
}
I kept getting nullpointer exception. I know that's because it can't find the file property_table.config.txt.
At first I put the property_table_config.txt file in the same folder(consumer/src/main/java/) as Config.java file. And tried use /property_table_config.txt and 'property_table_config.txt`. Neither of them work.
And then I tried using absolute path, not working. And tried using /main/java/property_table_config, not working either.
Then I saw this solution: https://stackoverflow.com/a/2103625/8159477.
So I make a directory called resources and put it under main folder (i.e. the path of the folder is consumer/src/main/resources, and create a sub-folder config under resources. After putting the property_table_config.txt file there, I changed the code into this:
configFile.load(this.getClass().getClassLoader().getResourceAsStream("/config/property_table.config.txt"));
But this still didn't work. Can anyone give some hint on this? Any suggestions will be appreciated!!
According to Class.getResourceAsStream:
This method delegates to this object's class loader. If this object was loaded by the bootstrap class loader, the method delegates to ClassLoader.getSystemResourceAsStream.
Before delegation, an absolute resource name is constructed from the given resource name using this algorithm:
If the name begins with a '/' ('\u002f'), then the absolute name of the resource is the portion of the name following the '/'.
Otherwise, the absolute name is of the following form:
modified_package_name/name
Where the modified_package_name is the package name of this object with '/' substituted for '.' ('\u002e').
This is how I understand the comments:
If you use ClassLoader.getResourceAsStream, send the absolute path from package root, but omitting the first /.
If you use Class.getResourceAsStream, send either a path relative the the current Class object (and the method will take the package into account), or send the absolute path from package root, starting with a /.
But in addition to this, you need to be cognizant of your build system. With maven, resource files are stored under src/main/resources.
So, in your case, I believe making the following changes should resolve the issue:
Put the file in src/main/resources.
Change the code to
this.getClass()
.getResourceAsStream("/property_table.config.txt")
//or `Config.class.getResource...
Alternatively, use
this.getClass().getClassLoader()
.getResourceAsStream("property_table.config.txt")`
I've tried this with a similar setup, and it works as expected.
ClassLoader().getResourceAsStream() is looking files only in classpath.
What you need is to have your config file in directory which is in classpath.
So, you have options:
when you run your java application from command line you can set path to directory in -cp parameter or CLASSPATH system variable. point there is: directory from where you need to get config file must be in class path - not a file. (e.g. if file location is c:\my_projects\test-project\config\my_config.properties and c:\my_projects\test-project\ is in classpath then getResourceAsStream call will be ClassLoader().getResourceAsStream("config/my_config.properties")
you can package your file into jar file and root of jar file is starting point for getResourceAsStream("config/my_config.properties")
If your Maven project is a jar project you need to use Maven resource plugin to put additional resource(s) into jar.
BTW: Maven does not put anything into jar file from src/main/java/ directory (if you do not explicitly specify it for resource plugin)
If you use IDE like Eclipse with your Maven project src/main/resources is a part of build classpath. Double check is it there and if it is not - do "Update Maven Project" or add it manually.
Still ClassLoader will see your properties file from src/main/resources folder only when you run project in IDE not from standalone Jar file - if you did not package your file or provide location in classpath.
hi can you try this one
String dirBase = new ClassPathResource("property_table.config.txt").getURI().getPath().replace("property_table.config.txt", "");
Can you try following code.
Config.class.getResourceAsStream("property_table.config.txt")
Update:
This is the code I tried.
package test;
import java.util.Properties;
public class Config
{
Properties configFile;
public Config()
{
configFile = new Properties();
try
{
configFile.load(Config.class.getResourceAsStream("property_table.config.txt"));
}
catch (Exception e)
{
e.printStackTrace();
}
}
public String getProperty(String key)
{
String value = this.configFile.getProperty(key);
return value;
}
public static void main(String[] args)
{
Config config = new Config();
System.out.println("URL: " + config.getProperty("URL"));
System.out.println("PASSWORD: " + config.getProperty("PASSWORD"));
}
}
And I placed property_table.config.txt file withn test package and it worked.

Standard/Uniform way to locate files inside and outside JAR file?

What is the uniform or standard way to locate and then access files inside and outside JAR files.
I have InJarClass() defined in JAR file which contains configuration text files.
Then I extend this class in my host project which have more configurations.
Let say I have inside the JAR :
config/default.conf
Then in the host project I do :
class MyClass extends InJarClass { .... }
and also :
config/test.conf
then I run it something like this :
XENV=test java myclass
The whole configuration process happens inside InJarClass(), based on environment XENV.
As you see InJarClass() have to access both :
<jar>/config/default.conf
<host_app_dir>/config/test.conf
So to repeat my question is there uniform way to access both, if the directory structure mirror each other.
If you place both the current directory and the .jar file in your classpath:
XENV=test java -classpath .:myjarfile.jar MyClass
you can do this:
String configFile =
"/config/" +
System.getenv().getOrDefault("XENV", "default") +
".conf";
InputStream config = MyClass.class.getResourceAsStream(configFile);
if (config == null) {
throw new FileNotFoundException(
"Cannot locate " + configFile + " in classpath");
}
This works because an application resource is a resource which Java searches for within each location in the classpath. So getResourceAsStream will first search for the requested path relative to the first classpath location, .. If it does not find a file with that name, it will look at the second classpath location, myjarfile.jar, and seeing that it is a .jar file, will search for the requested file inside that .jar.

Export Hazelcast Configuration to file

Does someone knows a way to export a hazelcast config to a file?
I know for importing it, there are following ways:
hazelcast.config system property
hazelcast.xml file in the working directory
hazelcast.xml on the classpath
hazelcast-default.xml that comes with hazelcast.jar
But what can I do, if I want to save the actual config as xml. Perhaps for backup purposes. How can I do this?
I'm not aware of a configuration exporter but there is getter methods on Hazaelcast configuration class com.hazelcast.config.Config. You can use them to extract the configuration for you maps, lists, multimaps, groups, etc. For instance:
Map<String, ListConfig> listConfigs = config.getListConfigs();
for(ListConfig listConfig = listConfigs.values()) {
// export the configuration to an output file
System.out.println("List: " + listConfig.getName()+" has max size: "+listConfig.getMaxSize());
}

Can we specify directory path with the property file while using ResourceBundle class in Java?

I want to place my properties files in some folder, but I am not able to read them because we can specify only the bundle name in static getBundle() method on ResourceBundle object.
Suppose bundle is: myFile.properties
Current path is: src
I want to keep my properties file in: src/temp
So when I am using:
ResourceBundle.getBundle("temp/myfile", currentLocale);
it is throwing an exception "can't find bundle". I want some way to specify the path. Please suggest me some way to do this.
Thank you
Use this:
ResourceBundle.getBundle("temp.myfile", currentLocale);
The baseName supplied in the ResourceBundle.getBundle call is supposed to be a fully qualified class name. So it has to be written separated with dots. Also note that this makes temp a package in your java code (which I don't think is a good idea). It is better to put the properties file in a proper package like com.xyz.abc. Then you can access it using
ResourceBundle.getBundle("com.xyz.abc.myfile", currentLocale);
It is possible that you are using the wrong filename (myfile != myFile).
For a file myFile.properties in a directory temp on the classpath, this code should work:
ResourceBundle.getBundle("temp.myFile");

Categories