Springboot - #Autowired null with injection - java

I have a Spring-boot project and I need to get values from application.properties file because of profiles.
But when injecting a config file in the class, the object return null.
Application.properties:
server.ip=000.000.000.000
server.port=0000
Config Class:
#Component
#ConfigurationProperties(prefix = "server")
public class AppProperties {
private String ip;
private Integer port;
... getters and setters
the class where I need the values:
#Component
public class Teste {
#Autowired
private AppProperties properties;
...
socket = new Socket(properties.getIp(), properties.getPort());
On debugging, at the start of the application, the values in AppProperties get a correct value.

You can use #Value annotation to access the property values from application.properties file like this
#Value("${<propertname>}")
private String userBucketPath;

Your code looks like correct but I would like to suggest you try with below steps also:
Use #PropertySource annotation to define properties location. (I knew default location is classpath).
If you really need to add a profile to your project. Create a new application property file like application-{profile-name}.properties and while starting an application pass JVM argument -Dspring.profiles.active={profile-name}.
I don't know it's exact need or answer for you. I'm just trying to share an additional step.

I get null values for properties because I instantiate a Teste class with new Teste().
The Solution is use Teste class with Intection.
#Autowired
private Teste teste;

Related

field annotated with `#value` is not initialized in mongock configuration

I need to assure data migration using mongock.
The #ChangeUnit class holds the logic for migration. It has a field annotated with #Value which is always null, even though I properly initialized in application.properties:
mongock.migration-scan-package=my.package
login-secret=test
Then the MigrationConfiguration looks as follows:
#ChangeUnit(id = "test", order = "001", author = "test")
#RequiredArgsConstructor
#Configuration
public class InitUsersChangeLog {
private final MyService service;
private final MongoTemplate template;
#Value("${login-secret}")
private String LOGIN;
#Execution
public void initUser() {
service.create(User.builder().login(LOGIN).build());
}
}
Main class:
#EnableMongock
#SpringBootApplication
public class MailServiceApplication {...}
My assumption is that this value is not injected properly into the MongockConfiguration bean. I tried to configure the bean manually (without using mongock.migration-scan-package=my.package) in the properties, but with no success.
As Mongock currently doesn't support #Value annotation you can try to use getProperty method from Environment bean. Environment bean can be injected same as other beans using constructor or Lombok annotations.
You want to change this:
#Value("your.key.property")
to that:
private final Environment env;
public void method(){
env.getProperty("your.key.property")
}
Mongock currently no supports #value injection via field o method parameter. We will provide that in a future minor release within version 5, but we can't give you dates, yet.
Extending MichalJ's answer, which is absolutely valid. I would like to add that the changeUnits are not retrieved by Mongock via Springboot, they are processed by Mongock independently. So the annotation #Configuration, #Component, etc. won't be taken into account and they could even be damaging.
Related to that, this code won't work, at least not in a near future:
#Value("${login-secret}")
private String LOGIN;
First, as said, Mongock doesn't support value currently, but the first approach will require the constructor parameter to have that #Value("${login-secret}"), not at the field level.

ConfigProperty not injecting the value into the field

I am new to quarkus environment. I have a quarkus application where I'm trying to inject the property config using
org.eclipse.microprofile.config.inject.ConfigProperty
Here is the sample code
public class Temp {
#ConfigProperty(name = "secret.token")
static String SECRET_KEY;
public void display() {
System.out.println(SECRET_KEY);
}
}
Here is the content of my application.properties
secret.token = ${TOKEN_SECRET:Root}
Here display method is always printing null.
The thing is the same property is being injected into the controller/resource endpoint classes properly but not in this class. I also tried using #Inject along with #ConfigProperty but no luck. Any pointers would really help.
The class on which the annotation is used, needs to be a CDI bean.
The easiest way to accomplish that is to annotate the class with #Singleton and use with something like #Inject Temp temp wherever the class is used.
See https://quarkus.io/guides/cdi for an intro to CDI

Requirements for properties being resolved with #ConfigurationProperties

I am using Azure KeyVault in Spring Boot to resolve secrets. The vault has a limitation in that properties can only be separated by -. I am using azure-keyvault-secrets-spring-boot-starter and this dependency replaces dashes with dots to be able to store secrets such as spring-datasource-url.
In my project we are using a fairly complex KeyVault and this requires us to prefix properties to know who owns them. So I store my property as prefix-sampleProperty in the vault. The vault starter lets my use this property on two different ways:
#Value("${prefix.sampleProperty}"
#Value("${prefix-sampleProperty}"
However, since my part of the application is only interested in a single namespace within this vault (the prefix namespace), I want to use the Spring annotation #ConfigurationProperties(prefix = "prefix") and simply disregard writing it for each property:
#Value("${sampleProperty}"
However, this does not work and fails with the following error:
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'sampleProperty' in value "${sampleProperty}"
I have verified that my environment variables in Spring contain the property, and it exists in two forms, both with . (dot) and - (dash). They exist under propertySource -> source -> propertySources -> propertySourcesList -> KeyVaultPropertySource when Spring attempts to resolve the value from here.
All available property sources that Spring iterates through:
When Spring calls propertySource.getProperty(key);, key is sampleProperty, which does not exist, only prefix-sampleProperty and prefix.sampleProperty do.
This in turn calls this method, and here secretName is also sampleProperty, which does not exist in the map in this class.
So, my questions:
Are there any specific requirements for resolving properties with class level annotation ConfigurationProperties other than it has to be separated by .?
Are there any specific requirements for how to add properties to Springs environment to be able to resolve them with ConfigurationProperties?
Is this a fault in the implementation of the Azure KeyVault property source?
Edit:
#Getter
#Component
// #EnableConfigurationProperties // also tried here, not working
#ConfigurationProperties(prefix = "prefix")
public class SampleConfiguration {
private String sampleProperty;
}
I also added #EnableConfigurationProperties at the same place where I added #SpringBootApplication. This is how I wire the configuration:
#Configuration
// #EnableConfigurationProperties(DataLakeConfiguration.class) // also tried, no difference. also removed autowired
public class AzureBeanConfiguration {
#Autowired
public AzureBeanConfiguration(final SampleConfiguration configuration) {
this.configuration = configuration;
}
#Bean
public ADLStoreClient getDataLakeClient() {
// All properties on configuration object is null here
}
}
If I instead use this, it works:
#Getter
#Configuration
public class SampleConfiguration {
#Value("${prefix.sampleProperty}") // or prefix-sampleProperty
private String sampleProperty;
}
Edit 2:
Config class is annotated with:
#Getter
#Setter
#Configuration
#ConfigurationProperties(prefix = "prefix")
public class SampleConfiguration {
private String sampleProperty;
}
I set a breakpoint here, and when I hit it the parameter name equals prefix. I never receive anything like prefix.sampleProperty or anything containing that key, nothing resembling the name sampleProperty.

SpringCloudConfig When I use these annotations #RefreshScope #ConfigurationProperties ,I was in trouble

SpringCloudConfig trouble
When I use these annotations #RefreshScope #ConfigurationProperties, I was in trouble.
#Component
#RefreshScope
#ConfigurationProperties(prefix = "config.message")
public class MessageProperties {
private int max_num;
private boolean begin;
private String ding_department;
// getter, setter...
}
like this ! Config does not work;
but when I use only #ConfigurationProperties,it works. So What's the use of #RefreshScope. And how to fix it?
So when you use "I was in trouble" in stackoveflow you are in trouble that there is high probability no one to answer.
#ConfigurationProperties is used for mapping properties to a POJO, with prefix you start using hierarchical properties structure. SO for example based on your description your code will work if you have the following .yml
config:
message:
max_num:
begin:
ding_department:
If for example you use spring-cloud-config server to store the configuration properties and spring-boot and want on change on the file the corresponding Bean with injected conf file to be update you add #RefreshScope, but even if you do this the bean is not updated you have to call the /refresh url or to trigger event which will refresh it.

Spring Boot - making configuration final

My Spring Boot (1.3.5) application uses externalized configuration using an application.properties file. Alongside, I currently have a configuration class as such:
#Configuration
MyConfig {
#Value("${prop}")
private String prop;
// getters
}
I'm wondering if there is a way to make prop final. Ideally I'd like to access my configuration properties publicly; for example myConfig.prop. I'd like to make all properties public and final; however I believe configuration classes are first instantiated via an empty constructor before properties are loaded. Is there an alternative approach?
You can inject your config values in the constructor and assign to a final field.
#Configuration
class MyConfig {
private String final prop;
public MyConfig(#Value("${prop}") String prop){
this.prop = prop;
}
}
For all the people landing here and asking themself the same question, please have a look at https://stackoverflow.com/a/57191291/11770752
In addition you can use this with lombok if desired, which reduces the class' boilerplate code.

Categories