Spring ConfigurationProperties not loading values(default) from application.yml - spring

PropertyLoader class does not load the default value for "testValue" from application.yml
#ConfigurationProperties(prefix="my-property")
#Component
public class PropertyLoader {
String testValue;
public String getTestValue() {
return testValue;
}
public void setTestValue(String testValue) {
this.testValue = testValue;
}
}
application.yml
spring:
profiles:
active: default
my-property:
testValue: random

You should use #Value(„${testValue}“) over testValue field.
https://www.baeldung.com/spring-value-annotation

Answering my on question as I figured it out after spending some time on it.
Never set active profile in application.yml, in my case someone added active profile to default, as soon as the spring property loader sees the spring.profiles.active it searches for application-{avtive-profile}.yml, in my case application-default.yml since it does not find a file by that name it does not load the default values from application.yml

Related

PropertySourcesPlaceholderConfigurer can't resolve property

I am reading document here
https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-value-annotations
#Component
public class MovieRecommender {
private final String catalog;
public MovieRecommender(#Value("${catalog.name}") String catalog) {
this.catalog = catalog;
}
}
#Configuration
#PropertySource("classpath:application.properties")
public class AppConfig { }
And the following application.properties file:
catalog.name=MovieCatalog
A default lenient embedded value resolver is provided by Spring. It
will try to resolve the property value and if it cannot be resolved,
the property name (for example ${catalog.name}) will be injected as
the value.
What does "it cannot be resolved" mean? If I don't have this property in the application.properties, it gives me error:
Could not resolve placeholder 'catalog.name' in value "${catalog.name}"
Updated:
I figured it out. In Spring core, if property not found, it uses ${catalog.name}
But in SpringBoot, if property not found, it gives error.
Resolve means find. Sometime the resolution (finding) can be complicated.
An SpringBoot each property in application properties can also be injected with an environment variable. So catalog.name could be left out of apllication.properties and used as env var CATALOG_NAME.
AFAIK a value can also come in on a command line.

#Value annotation is only loading default - not using property file

Problem
I think that I havn't understood something properly because my #Value is always loading the default calue.
Java Code
So I have the following:
#Value("${disableQuerySecurityDebug:false}")
private boolean disableQuerySecurityDebug;
And this is set to false always.
Property file: application-disableQuerySecurityDebug.properties
I have a properties file called application-disableQuerySecurityDebug.properties.
And I have the following entry inside the file:
disableQuerySecurityDebugMne=true
And I run the application with the following profile: disableQuerySecurityDebugMne
I was expecting the value to be set to true, but it is always false.
Update
Based on deadpool's answer, I ended up with the following:
#Profile("disableQuerySecurityDebug") #Data
#Configuration
public class DisableSecurityConfig implements DisableQuerySecurityDebug {
#Value("${disableQuerySecurityDebug:true}")
private boolean securityDisabled;
}
#Profile("!disableQuerySecurityDebug") #Data
#Configuration
public class EnableSecurityConfig implements DisableQuerySecurityDebug{
#Value("${disableQuerySecurityDebug:false}")
private boolean securityDisabled;
}
public interface DisableQuerySecurityDebug{
public boolean isSecurityDisabled();
}
#Value annotation is only used to inject properties values into spring Beans from yml or properties file
This annotation can be used for injecting values into fields in Spring-managed beans and it can be applied at the field or constructor/method parameter level.
If you want to inject values based on profile specific then use #Profile on class
#Profile("disableQuerySecurityDebug")
#Configuration
public class Config {
#Value("${disableQuerySecurityDebug:false}")
private boolean disableQuerySecurityDebug;
}
You could also specify it on the command line by using the following switch:
java -jar demo.jar --spring.profiles.active=disableQuerySecurityDebug

Cannot read application.yml

I write Spring Boot application. I use file application.properties to contains configuration of database. But now I want to get properties from application.yml which contains:
rest:
response: RESPONSE
#RestController
public class MyController {
#Value("${rest.response}")
private String restResponse;
#GetMapping("/foo")
public ResponseEntity<String> register() {
return restResponse;
}
}
Directory resources contains application.properties and application.yml. Why I cannot import properties from .yml?
If you are using 'application.yml' , if the RESPONSE that is read from application.yml contains characters such as + , - etc , put the value inside single inverted commas otherwise it won't be read properly(since it is mapped to a string variable).
check that org.yaml:snakeyaml:1.26 is in classpath (or spring-boot-starter is in dependencies)

how to write a value into application.properties in spring boot

I already saw Write/Update properties file value in spring
In Spring boot
How to write a value into application.properties in spring boot?
application.properties:
ews.batch_type=
ews.batch_dat=
...other fields
I want:
application.properties:
ews.batch_type=ALL
ews.batch_dat=20170222
...other fields
Thanks
After you give some more information I guess you want to define default values. The application.properties is still static but you can do something in your Application to handle missing properties.
You can define default values
// Gets the Value of "ews.batch_type" or "ALL" if no property is defined
#Value("${ews.batch_type:ALL}")
private String batchType;
public static String getDate() {
return "..."; // <- the date you want
}
#Value("#{ config['ews.batch_dat'] ?: T(yourClass).getDate() }")
private String date;

How to access a Spring Boot Application's name programmatically?

I've defined an application name using the bootstrap.yml file in my spring boot application.
spring:
application:
name: abc
How can i get this application name during runtime/programmatically ?
You should be able to use the #Value annotation to access any property you set in a properties/YAML file:
#Value("${spring.application.name}")
private String appName;
#Autowired
private ApplicationContext applicationContext;
...
this.applicationContext.getId();
Please, find this:
# IDENTITY (ContextIdApplicationContextInitializer)
spring.application.name=
spring.application.index=
In Spring Boot Reference Manual.
And follow with source code for that ContextIdApplicationContextInitializer class:
#Override
public void initialize(ConfigurableApplicationContext applicationContext) {
applicationContext.setId(getApplicationId(applicationContext.getEnvironment()));
}
Where the default behavior is with this:
/**
* Placeholder pattern to resolve for application name
*/
private static final String NAME_PATTERN = "${vcap.application.name:${spring.application.name:${spring.config.name:application}}}";
Since the #Value annotation is discouraged in Spring Boot when referencing configuration properties, and because applicationContext.getId(); doesn't always return the value of spring.application.name another way is to get the value from the Environment directly
private final Environment environment;
...
public MyBean(final Environment environment) {
this.environment = environment;
}
...
private getApplicationName() {
return this.environment.get("spring.application.name");
}
Another possible way would be to create your own ConfigurationProperties class to get access to the value.
I'm not saying these are the best ways, and I hope/wish that there is a better way, but it is a way.
Note! If your using a SpringBootTest, you need to suplly the properties/yml.
Otherwise, the environment/appcontext does not load the config files.
The, your app name is not set.
Like so:
#PropertySource("classpath:application.properties")
#RunWith(SpringRunner.class)
#SpringBootTest
....
This post is aged but I hate unanswered questions.
So use the following snippet:
#Value("${spring.application.name [: defaultValue]}")
private String appName;
What is between [] is optional.
So I found a really ugly way to do this, but it works so I'm not searching further. Maybe this will help someone.
The basic premise is that spring Environment stores the value inside a propertySource.. It appears that bootstrap config is stored in the ResourcePropertySource and so you can get it from that. For me it is currently throwing an exception, but then I can get the value out of the exception, so I haven't looked any further:
try {
this.environment.getProperty("name", ResourcePropertySource.class);
} catch (ConversionFailedException e) {
String res = (String)e.getValue();
}
And then you can just do this for every property you are interested in.
Like I said ugly, but it works.

Resources