Can you override a library's Spring property placeholders? - java

We are working on moving our application to use only Spring-Boot application.properties files. The old way we were doing was that each library/dependency would have their properties stored in a dedicated properties file like res/environment/some-library-override.properties. The values would then be retrieved in the library using #Value("$some-library-{PROPERTY_NAME}").
However, since moving all of these override properties to dedicated application.properties files, it is no longer resolving the properties and we get errors like java.lang.NumberFormatException: For input string: "$some-library-{PROPERTY_NAME}".
I assume this is because it is still expecting the property to be in that dedicated properties file.
Is there a solution to this that doesn't involve modifying the library/dependency? Is it possible to have it ignore the prefix and only look for the PROPERTY_NAME in the application.properties files?

if you have declared propertie var likeproperty.name=XXXX or added environment var like PROPERTY_NAME=XXXX.
you need to use this way
#Value("some-library-${property.name}")
// will inject value "some-library" + "XXXX"

Related

Reading empty string from consul using spring-cloud-consul

I'm migrating from file based .properties file to consul based configuration in my spring application. I'm using spring-cloud-consul. Earlier in my property file I had a property like following
test.key=
In spring application class corresponding field is like this
#Value("${test.key:defaultVal}")
private String testConsul;
In the runtime, the value of testConsul string is an empty string. But when using the consul, whenever I put key test.key without a value, in the runtime it gets resolved to a null.
Is there anyway I can pass an empty string value through consul ?
This is the work around we're using. use a default value which is not exist
${no.such.key:}
Hope this helps.

Java bean gets property name instead of value

I have a .properties file with bunch of properties in it. Here's an example:
mes.mail.debug=true
cookie.sso.domain = .stuffStuff.com
blabla.endpoint = blabla.com
test.value.property = myValue
The problem is with the last one (Which I have just added to the project we're working on).
I read the properties using #Value("${PropertyName}") annotation and it was working perfectly until lately, when I use the same thing, the variable gets the propertyName instead of its value:
#Value("${test.value.property}")
private String mProperty;
so, mProperty gets "test.value.property" where what I'm looking for is for it to get "myValue".
What's happening exactly? Is there something wrong with my project? I have tested in my friend's computer and it works perfectly.
By the way, i'm using Spring Tool Suite.
EDIT: It turns out that it doesn't detect the changes I make in the properties file. So if I change an old property's value; it acts as if nothing happened.
Does anyone has any idea why it's doing like this?
When you declare a Property Placeholder Configurer to load the properties files, you can set it to ignore unresolvable placeholders.
This means that if the property you are injecting with #Value is not found, its name (or key) will be assigned to the variable.
In your case, this option is enabled and the file that has been loaded by the application is not the one you are editing.
To see from where the file is been loaded, check the placeholder configurer location property.

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.

Overriding dependencies property value in Spring

In my Spring project I am using a dependency project developed in Spring. This dependency has its own properties file and have defined a property which points to localhost. Now in my setup, I want this property to be pointing to another URL but not localhost. I am trying to override this in my properties file using addFirst method of property sources, but the dependency still loads the original property value.
ConfigurableEnvironment environment = applicationContext.getEnvironment();
//here i overload the props
environment.getPropertySources().addFirst(
new ResourcePropertySource("classpath:conf/app.properties"));
LOG.debug("dependency property: " + applicationContext.getEnvironment().
getProperty("server.hostname")); // here it prints the overloaded value in app.properties
When I print the overloaded property I get the overloaded property value, but when the program gets executed it points to localhost. Is this the way to override dependent properties ? Spring version is 3.2
The point is, that in the ProperySources the last one wins.
(Its like in a Database, the last one that writes wins).
Try to use simply add.

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