Getting the used file name from a Properties instance - java

An instance of java.util.Properties is passed to me which has been created using:
[...]
properties = new java.util.Properties();
try {
properties.load(
AutoProperties.class.getClassLoader().getResourceAsStream(propertyFile)
);
}
[...]
I was wondering how I could retrieve the file name (propertyFile above) from the properties instance? I had a glance at the API and couldn't see any easy way to do it.

The file name (or path name in this case) is not stored in the Properties instance. In fact, you haven't even passed the name to the instance.

You can't. It's not saved in the Properties object.

You cannot get this information, as a Properties object is not necessarily linked to a File...
Indeed, you can populate the Properties in several ways:
Load a properties file (as you did in your example).
Populate directly this object (using put() method from the Hashtable class).

Related

Passing a variable to #Value annotation for reading specific property from properties file

In my Spring boot application, a specific value needs to be read from the properties file depending on a string value returned from another function. My properties file is as follows:
A=value_a
B=value_b
A function returns either A or B, and stores it in a String variable called stringValue . I am looking for doing something along the lines of the following:
#Value(stringValue)
String propertyValue
However, I get the following message on my IDE:
Attribute value must be constant
I have tried to convert stringValue to a static final variable, but to no avail.
I do know that I can pass a specific key to be read from the properties file, such as the following:
#Value("${A}")
String valueOfA
My question is whether I can pass a variable to the #Value annotation?
#Value annotations are resolved during startup, when Spring context is built. Since stringValue would not be available at this time, you can't use it for injection purposes.
An exception to this scenario would be if the bean with #Value annotation is prototype-scoped, in which case a new instance of it would be created any time it's requested. Still, stringValue would need to be available to the Spring context in order to be used at injection point.
Without seeing more code, it's not possible to give you any more detailed answer.
You can autowire Environment in your application and use it to read from the properties file as it is supposed to be at runtime.( This is assuming all files where your properties are have been added to environment).
I will be posting my answer with assumptions as you have not updated your question, with all information I requested.
So your code would be-
lets call your class where your making a call to a function called getValue to get value of stringValue- Example. Now lets assume you are making a call to the function getValue in a method in the class Example called doSomething().
class Example{
#Autowire
private Enviornment environment.
private String propertyValue
public void doSomething(){
String value=getValue()// this is where u know whether
its A or B.
propertyValue=environment.getProperty(value);
// do whatever u want know
}
Thanks for the help guys! I read the values from the properties file into a org.springframework.core.io.Resource object, and then used that to retrieve the specific value that I required. The following was how I structured my solution code:
#Value("classpath:config.properties")
private Resource propertiesfile;
I then declared a java.util.Properties object and read the values from the Resource object into it.
Properties properties = new Properties();
try{
properties.load(propertiesfile.getInputStream());
}catch(IOException e){
logger.error("Parsing error while reading properties file",e.toString());
}
Finally, based on the value in my stringValue variable, I read the corresponding value from the properties file
String propertyValue = properties.getProperty(stringValue);
if your variable is another environment variable you can try in this format.
#Value("${${stringvalue}}")
where stringvalue is the environment variable.

is Spring provide Local storage?

I have to develop one desktop base application(it has no request/response) and it has many classes.
my Main/Controller class read (*.properties) file,
like
allExtensions = properties.getProperty("ReportFileExtension");
and i have mention some file extension in .properties file like ReportFileExtensionn = .pdf,.doc etc.
This key read from .properties file in Main class and i want use this key value in other class without passing argument in any method or constructor.
is it spring provide a local storage ? so i can use to store attribute and use it other class.
Thanks in Advc.
Your question is bit confusing but based on comments I think you are struggling to understand how to get keys from properties.
Check PropertiesLoaderUtils
Resource resource = new ClassPathResource("/my.properties");
Properties props = PropertiesLoaderUtils.loadProperties(resource);
Now iterate over the props object
Try this
public Set<Object> getAllKeys(){
Set<Object> keys = prop.keySet();
return keys;
}
Or this
public void printProperties() {
for(Entry<Object, Object> e : props.entrySet()) {
System.out.println(e);
}
}
Properties are available globally but if you want you can create a static map and cache the properties in it.

How to load all key/value pairs in properties file

I'm trying to load all key/value pairs in my properties file.
One approach is that I load all the properties using #Value manually, but for that I should know all the keys.
I cannot do this, since property file may be changed in future to include more set of key/value pairs and I may need to modify code again to accommodate them.
Second approach is that I should some how load the properties file and Iterate over it to load all the key/value pairs without knowing the keys.
Say I have following properties file sample.properties
property_set.name="Database MySQL"
db.name=
db.url=
db.user=
db.passwd=
property_set.name="Database Oracle"
db.name=
db.url=
db.user=
db.passwd=
Here is what I'm trying to do
#Configuration
#PropertySource(value="classpath:sample.properties")
public class AppConfig {
#Autowired
Environment env;
#Bean
public void loadConfig(){
//Can I some how iterate over the loaded sampe.properties and load all
//key/value pair in Map<String,Map<String, String>>
// say Map<"Database MySQL", Map<key,vale>>
// I cannot get individual properties like env.getProperty("key");
// since I may not know all the keys
}
}
Spring stores all properties in Environment.
Environment contains collection of PropertySource. Every PropertySource contains properties from specific source. There are system properties, and java environment properties and many other. Properties from you file will be there as well.
Any source has own name. In your case automatically generated name will be look like "class path resource [sample.properties]". As you see, the name is not so convenient. So lets set more convenient name:
#PropertySource(value="classpath:sample.properties", name="sample.props")
Now you can get source by this name:
AbstractEnvironment ae = (AbstractEnvironment)env;
org.springframework.core.env.PropertySource source =
ae.getPropertySources().get("sample.props");
Properties props = (Properties)source.getSource();
Note that I specified full name of PropertySource class, to avoid conflict with #PropertySource annotation class. After that, you can work with properties. For example output them to console:
for(Object key : props.keySet()){
System.out.println(props.get(key));
}
You can autowire in an EnumerablePropertySource which contains the method getPropertyNames()
you can look up the class Properties in the jdk api and use the method load(InputStream inStream)
InputStream in = new FileInputStream("your properties location");
Properties prop = new Properties();
prop.load(in);
ps: prop is subClass of HashTable and don't forget to close stream

Multiple config block in java properties file

I need to define multiple configuration blocks in a single .properties file in Spring. Currently I am having multiple .properties file like below:
one.properties:
publishing.channel=ftp
ftp.user=user1
ftp.password=pass1
ftp.host=abc.xyz.com
ftp.port=21
two.properties
publishing.channel=ftp
ftp.user=user2
ftp.password=pass2
ftp.host=def.xyz.com
ftp.port=21
What I now require is defining only one .properties file and add all the configuration blocks in it like so:
publishing.channel=ftp
ftp.user=user1
ftp.password=pass1
ftp.host=abc.xyz.com
ftp.port=21
then another one
publishing.channel=ftp
ftp.user=user2
ftp.password=pass2
ftp.host=cdf.xyz.com
ftp.port=21
it could be http too
publishing.channel=http
http.user=user2
http.password=pass2
http.host=cdf.xyz.com
Problem is when I put multiple property blocks like this, I cannot differentiate in code as my bean methods (e.g. getHost()) will only fetch the last declared one in the properties file. I do not want to create many variables like host1, host2, host3 and so on as it would need to be modified in case there is another block of properties added. How can I make it generic?
Thanks in advance.
You can use PropertiesConfiguration from Apache Commons Configuration and then access all the values of same key and add your logic to get the required value.
Use getStringArray(key) method or getList(key) method to access all values.

How to Change init-parameters at Runtime?

If I modify the XML to change the value of init parameter
I see the changes only when web-app is redeployed.
My question is cant I get around this by setting the values at run time.Is there any API that allow me to change the values dynamically.
It's called init-parameter for a reason. So, you can't.
But you can change values at runtime, that's no problem.
After reading the init parameters put them as attributes of the ServletContext (ctx.setAttribute("name", value))
Create a small (password-protected) page that lists all attributes of the ServletContext and gives the ability to change them.
Maybe you could use apache commons configuration, specifically have a look at Automatic Reloading...
Make use of properties files instead and write code so that it 1) reads the value from it everytime, or 2) can reload the value on command, or 3) reloads the file automatically at certain intervals.
If you put the properties file somewhere in the webapp's runtime classpath or add its path to the webapp's runtime classpath, then you can easily access/load it as follows:
Properties properties = new Properties();
properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("filename.properties"));
String value = properties.get("key");

Categories