Spring multiple ConfigurationProperties for one prefix - spring

I have a following structure in my application.yml
conf:
a:
prop1: abc
prop2: abc
b:
prop3: abc
Now I want to have configuration A in one ConfigurationProperties class and configuration B in another. I can do that like this:
#ConfigurationProperties(prefix = "conf")
class A{
Map<String, String> a;
}
And another class:
#ConfigurationProperties(prefix = "conf")
class A{
Map<String, String> b;
}
But now I'm getting error saying that prefix is duplicated. Is it possible to have #ConfigurationProperties(prefix = "conf.a") and #ConfigurationProperties(prefix = "conf.b") and somehow load all these properties into a map like that?
#ConfigurationProperties(prefix = "conf.a")
class A{
Map<String, String> allProperties;
}

My suggestion would be to do this:
conf:
a:
config:
prop1: abc
prop2: abc
b:
config:
prop3: abc
You will then be able to use the prefixes:
#ConfigurationProperties(prefix = "conf.a")
class A{
Map<String, String> config;
}
#ConfigurationProperties(prefix = "conf.b")
class B{
Map<String, String> config;
}

Related

#ConfigurationProperties failing to parse yaml file

Im trying to convert my yaml file into a list of objects that I can query during runtime. Ive tried to follow the documentation however my use case is a little more complicated than all the examples that I have seen and Im not sure what im missing.
When I try to run the below code I dont get any errors. But when I autowire the component Its empty.
#Data
#Component
#ConfigurationProperties(prefix = "kafka")
public class KafkaProperties {
private Map<String, KafkaTopicProperties> topics = new HashMap<>();
#Data
public class KafkaTopicProperties {
Map<String, KeyProperties> key;
Map<String, ValueProperties> value;
Map<String, BootstrapProperties> bootstrap;
#Data
public class KeyProperties {
Map<String, String> serializer;
}
#Data
public class ValueProperties {
Map<String, String> serializer;
}
#Data
public class BootstrapProperties {
Map<String, String> servers;
}
}
}
kafka:
topic-name:
key:
serializer: org.apache.kafka.common.serialization.StringSerializer
value:
serializer: org.apache.kafka.common.serialization.StringSerializer
bootstrap:
servers: localhost:9092
other-topic:
key:
serializer: org.apache.kafka.common.serialization.StringSerializer
value:
serializer: org.apache.kafka.common.serialization.StringSerializer
bootstrap:
servers: localhost:9092
#Autowired
KafkaProperties properties;

How to speicify list inside map in spring boot application.properties

I need to have list of POJO(ServiceMetadata) inside a map, which will read configuration
from application.properties
#Configuration
#EnableConfigurationProperties
#ConfigurationProperties(prefix = "props")
#Data
#Component
public class ApplicationConfig {
private Map<String, List<ServiceMetadata>> markets = new HashMap<>();
}
#Data
public class ServiceMetadata {
private String applicationName;
private String backendURL;
}
I tried the below, it is not working.
props.markets.UK.serviceEndpoints[0].applicationName=abc
props.markets.UK.serviceEndpoints[1].backendURL=http://localhost:8080/api/v1/markets/{marketId}
props.markets.ES.serviceEndpoints[0].applicationName=xyz
props.markets.ES.serviceEndpoints[1].backendURL=http://localhost:8080/api/v2/markets/{marketId}
Try bellow:
props.markets.UK[0].applicationName=abc
props.markets.UK[0].backendURL=http://localhost:8080/api/v1/markets/{marketId}
props.markets.UK[1].applicationName=def
props.markets.UK[1].backendURL=http://localhost:8080/api/v1/markets/{marketId}
props.markets.ES[0].applicationName=xyz
props.markets.ES[0].backendURL=http://localhost:8080/api/v2/markets/{marketId}

springboot yml map property how to ref bean

I want to inject a map in yml file like that ;
abc-identify:
test:
51L: anhuiAbcIdentifyRule
my config class like that
#ConfigurationProperties(prefix = "abc-identify")
#Component
#Data
public class AbcIdentifyConfig {
private Map<Long, IdentifyRule> test;
anhuiAbcIdentifyRule is a existing bean in container
#Component
public class AnhuiAbcIdentifyRule implements IdentifyRule
I tried above setting which not work,how can I resolve this?
Spring does not support this type of string to bean conversion yet. Your code need to be changed to
private Map<Long, String> test;
If you want to get bean by rule from properties, there is a workaround.
#Data
#Component
#ConfigurationProperties(prefix = "abc-identify")
public class AbcProperties {
private Map<Long, String> test;
#Autowired
private Map<String, IdentifyRule> identifyRuleMap;
public IdentifyRule getRule(Long rule){
String beanName = test.get(rule);
if(beanName != null){
return identifyRuleMap.get(beanName);
}
return null;
}
}
Here Map<String, IdentifyRule> identifyRuleMap will contain all beans of IdentityRule with keys as beanName and values as bean.

ConfigurationProperties in nested classes

With following yml
app:
a:
prop: aaa
b:
prop: bbb
#Component
public abstract class Common {
#Value("${prop}")
private String prop;
#ConfigurationProperties(prefix = "app.a")
#PropertySource("classpath:app.yml")
#Component
public static class A extends Common {
}
#ConfigurationProperties(prefix = "app.b")
#PropertySource("classpath:app.yml")
#Component
public static class B extends Common {
}
}
But those two classes has same value, either for a or b.
How can I solve this?
I found the problem. Simply. yml doesn't work with PropertySource.
I'm still want to believe I'm wrong.
I changed the .yml file to properties and tried with this.
#PropertySource("classpath:/vendor.properties")
#EnableConfigurationProperties
public abstract class Common {
#Value("${prop}")
private String prop;
#ConfigurationProperties(prefix = "app.a")
#Component
public static class A extends Common {
}
#ConfigurationProperties(prefix = "app.b")
#Component
public static class B extends Common {
}
}
And it worked.
You could use a list for your configuration parameters :
app:
props:
- key: a
value: aaa
- key: b
value: bbb
And retreive your value with a more complex way in a separate bean :
#ConfigurationProperties(prefix = "app")
public class CommonConfiguration {
List<Prop> props;
//Getters and setters
public Prop retreiveSpecificConfiguration(String className) {
//some kind of logic here
}
public static class Prop {
private String key, value;
//Getters and setters
}
}
Inject it in your Common class implementation :
#Autowired
CommonConfiguration config;

I can not inject Map<String, String> from YAML file

I have this properties in my YAML file:
request-topic:
topics:
IMPORT_CHARGES: topic-name-1
IMPORT_PAYMENTS: topic-name-2
IMPORT_CATALOGS: topic-name-3
And this class:
#Getter
#Setter
#Component
#ConfigurationProperties(prefix = "topic-properties")
public class TopicProperties {
private Map<String, String> topics = new HashMap<>();
public String getTopicNameByType(String type){
return topics.get(type);
}
}
But when I autowire this properies I get empty Map:
#Service
public class TopicRouterImpl implements TopicRouter {
private final TopicProperties topics;
public TopicRouterImpl(TopicProperties topics) {
this.topics = topics;
}
#PostConstruct
public void init(){
topics.getTopicNameByType("IMPORT_CHARGES");
}
#Override
public String getTopicName(MessageType messageType) {
return topics.getTopicNameByType(messageType.name());
}
}
This is due to the name mismatch in your yaml file it should be equals to the specified prefix : topic-properties. Like this :
topic-properties:
topics:
IMPORT_CHARGES: topic-name-1
IMPORT_PAYMENTS: topic-name-2
IMPORT_CATALOGS: topic-name-3

Resources