#ConfigurationProperties failing to parse yaml file - spring-boot

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;

Related

null map when reading nested properties from yaml with configuration properties annotation

My application.yml looks like so
service:
cloud:
piglet:
published-host: http://localhost:29191
webhook:
headers:
gitlab: X-Gitlab-Token
The Config class
#Component
#ConfigurationProperties(prefix = "service.cloud.piglet.webhook")
public class WebhooksConsumerTokenHeadersProperties {
private final Map<String, String> headers;
public WebhooksConsumerTokenHeadersProperties(Map<String, String> headers) {
this.headers = headers;
}
public String getTokenHeaderName(String app) {
return headers.get(app);
}
}
I ran on debug and noticed that the headers map is null when initialising it in the constructor.

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}

Newly created / extended JHipster endpoint does not work (404 error)

I want to create a new endpoint that extends the existing jhimetrics endpoint (or extend the results of the existing jhimetrics). The application is generated with JHipster.
So what I have done is:
add the new endpoint to the array in application.yml file, specifically:
management:
endpoints:
web:
base-path: /management
exposure:
include: [ ..., "health", "info", "jhimetrics", "roxhens"]
created the ExtendedMetricsEndpoint.java with the following content:
// imports, etc...
#Endpoint(id = "roxhens")
public class ExtendedMetricsEndpoint {
private final JHipsterMetricsEndpoint delegate;
private final SimpUserRegistry simpUserRegistry;
public ExtendedMetricsEndpoint(
JHipsterMetricsEndpoint delegate,
SimpUserRegistry simpUserRegistry
) {
this.delegate = delegate;
this.simpUserRegistry = simpUserRegistry;
}
#ReadOperation
public Map<String, Map> getMetrics() {
Map<String, Map> metrics = this.delegate.allMetrics();
HashMap<String, Integer> activeUsers = new HashMap<>();
activeUsers.put("activeUsers", this.simpUserRegistry.getUserCount());
metrics.put("customMetrics", new HashMap(activeUsers));
return metrics;
}
}
created the configuration file for this endpoint:
// imports etc...
#Configuration
#ConditionalOnClass(Timed.class)
#AutoConfigureAfter(JHipsterMetricsEndpointConfiguration.class)
public class ExtendedMetricsEndpointConfiguration {
#Bean
#ConditionalOnBean({JHipsterMetricsEndpoint.class, SimpUserRegistry.class})
#ConditionalOnMissingBean
#ConditionalOnAvailableEndpoint
public ExtendedMetricsEndpoint extendedMetricsEndpoint(JHipsterMetricsEndpoint jHipsterMetricsEndpoint, SimpUserRegistry simpUserRegistry) {
return new ExtendedMetricsEndpoint(jHipsterMetricsEndpoint, simpUserRegistry);
}
}
What step am I missing here, or what am I doing wrong?
I had the same issue and after 2 days of struggle I was able to find a solution which works for me:
#Component
#WebEndpoint(id = "xxxmetrics")
public class XXXMetricsEndpoint {
private final MeterRegistry meterRegistry;
public SrnMetricsEndpoint(MeterRegistry meterRegistry) {
this.meterRegistry = meterRegistry;
}
#ReadOperation
public Map<String, Map> allMetrics() {
Map<String, Map> stringMapMap = new LinkedHashMap<>();
return stringMapMap;
}
}
Application yml:
management:
endpoints:
web:
base-path: /management
exposure:
include: [... , 'health', 'info', 'jhimetrics', 'xxxmetrics' ,'metrics', 'logfile']
This way the request: /management/xxxmetrics works.
The spring docs: https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-features.html#production-ready-endpoints-custom
Edit:
spring version: 5.1.10, spring-boot-actuator: 2.1.9

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

Spring: 2 Repositories out of a single Entity

What I need is 2 Repositories created out of a single entity:
interface TopicRepository implements ReactiveCrudRepository<Topic, String>
interface BackupTopicRepository implements ReactiveCrudRepository<Topic, String>
How is that possible? Right now only one is created.
This is how you would do it.
#Configuration
#ConfigurationProperties(prefix = "mongodb.topic")
#EnableMongoRepositories(basePackages = "abc.def.repository.topic", mongoTemplateRef = "topicMongoTemplate")
#Setter
class TopicMongoConfig {
private String host;
private int port;
private String database;
#Primary
#Bean(name = "topicMongoTemplate")
public MongoTemplate topicMongoTemplate() throws Exception {
final Mongo mongoClient = createMongoClient(new ServerAddress(host, port));
return new MongoTemplate(mongoClient, database);
}
private Mongo createMongoClient(ServerAddress serverAddress) {
return new MongoClient(serverAddress);
}
}
Another configuration
#Configuration
#ConfigurationProperties(prefix = "mongodb.backuptopic")
#EnableMongoRepositories(basePackages = "abc.def.repository.backuptopic", mongoTemplateRef = "backupTopicMongoTemplate")
#Setter
class BackupTopicMongoConfig {
private String host;
private int port;
private String database;
#Primary
#Bean(name = "backupTopicMongoTemplate")
public MongoTemplate backupTopicMongoTemplate() throws Exception {
final Mongo mongoClient = createMongoClient(new ServerAddress(host, port));
return new MongoTemplate(mongoClient, database);
}
private Mongo createMongoClient(ServerAddress serverAddress) {
return new MongoClient(serverAddress);
}
}
Your TopicRepository and BackuoTopicRepository should reside in abc.def.repository.topic and abc.def.repository.backuptopic respectively.
And also you need to have these properties defined in your properties or yml file
mongodb:
topic:
host:
database:
port:
backuptopic:
host:
database:
port:
Lastly, disable springboot autoconfiguration for mongo.
#SpringBootApplication(exclude = {MongoAutoConfiguration.class, MongoDataAutoConfiguration.class})

Resources