Spring-Boot: как привязать настраиваемые свойства вложенного приложения к классу @ConfigurationProperties?

Я пытаюсь добавить некоторые настраиваемые свойства приложения в свой проект Spring-Boot. Они выглядят так:

application:
    kafka:
        topic1: topicA
        topic2: topicB

А это класс @ConfigurationProperties:

@ConfigurationProperties(prefix = "application", ignoreUnknownFields = false)
public class ApplicationProperties {

    public static class Kafka {
        private String topic1;
        private String topic2;

        public String getTopic1() {
            return topic1;
        }

        public void setTopic1(String topic1) {
            this.topic1 = topic1;
        }

        public String getTopic2() {
            return topic2;
        }

        public void setTopic2(String topic2) {
            this.topic2 = topic2;
        }
    }
}

Когда я запускаю приложение, я получаю следующую ошибку:

Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled.
2018-11-16 16:13:04 [restartedMain] ERROR o.s.boot.SpringApplication - Application startup failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'application-com.project.config.ApplicationProperties': Could not bind properties to ApplicationProperties (prefix=application, ignoreInvalidFields=false, ignoreUnknownFields=false, ignoreNestedProperties=false); nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'kafka[topic1]' of bean class [com.project.config.ApplicationProperties]: Cannot access indexed value in property referenced in indexed property path 'kafka[topic1]'; nested exception is org.springframework.beans.NotReadablePropertyException: Invalid property 'kafka[topic1]' of bean class [com.project.config.ApplicationProperties]: Bean property 'kafka[topic1]' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
    at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.postProcessBeforeInitialization(ConfigurationPropertiesBindingPostProcessor.java:336)
    at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.postProcessBeforeInitialization(ConfigurationPropertiesBindingPostProcessor.java:292)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:409)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1626)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
    at com.project.projectApp.main(projectApp.java:68)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
Caused by: org.springframework.beans.NotWritablePropertyException: Invalid property 'kafka[topic1]' of bean class [com.project.config.ApplicationProperties]: Cannot access indexed value in property referenced in indexed property path 'kafka[topic1]'; nested exception is org.springframework.beans.NotReadablePropertyException: Invalid property 'kafka[topic1]' of bean class [com.project.config.ApplicationProperties]: Bean property 'kafka[topic1]' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
    at org.springframework.beans.AbstractNestablePropertyAccessor.getPropertyHoldingValue(AbstractNestablePropertyAccessor.java:403)
    at org.springframework.beans.AbstractNestablePropertyAccessor.processKeyedProperty(AbstractNestablePropertyAccessor.java:296)
    at org.springframework.beans.AbstractNestablePropertyAccessor.setPropertyValue(AbstractNestablePropertyAccessor.java:287)
    at org.springframework.beans.AbstractNestablePropertyAccessor.setPropertyValue(AbstractNestablePropertyAccessor.java:278)
    at org.springframework.boot.bind.RelaxedDataBinder$RelaxedBeanWrapper.setPropertyValue(RelaxedDataBinder.java:726)
    at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:95)
    at org.springframework.validation.DataBinder.applyPropertyValues(DataBinder.java:860)
    at org.springframework.validation.DataBinder.doBind(DataBinder.java:756)
    at org.springframework.boot.bind.RelaxedDataBinder.doBind(RelaxedDataBinder.java:137)
    at org.springframework.validation.DataBinder.bind(DataBinder.java:741)
    at org.springframework.boot.bind.PropertiesConfigurationFactory.doBindPropertiesToTarget(PropertiesConfigurationFactory.java:287)
    at org.springframework.boot.bind.PropertiesConfigurationFactory.bindPropertiesToTarget(PropertiesConfigurationFactory.java:250)
    at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.postProcessBeforeInitialization(ConfigurationPropertiesBindingPostProcessor.java:331)
    ... 22 common frames omitted
Caused by: org.springframework.beans.NotReadablePropertyException: Invalid property 'kafka[topic1]' of bean class [com.project.config.ApplicationProperties]: Bean property 'kafka[topic1]' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
    at org.springframework.beans.AbstractNestablePropertyAccessor.getPropertyValue(AbstractNestablePropertyAccessor.java:631)
    at org.springframework.beans.AbstractNestablePropertyAccessor.getPropertyHoldingValue(AbstractNestablePropertyAccessor.java:400)
    ... 34 common frames omitted

Как это должно было быть объявлено в моих ApplicationProperties, чтобы было правильно привязано?

вы добавляли процессор конфигурации в pom.xml? <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency>

Paizo 19.11.2018 11:30
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Версия Java на основе версии загрузки
Версия Java на основе версии загрузки
Если вы зайдете на официальный сайт Spring Boot , там представлен start.spring.io , который упрощает создание проектов Spring Boot, как показано ниже.
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
1
1
1 357
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Не уверен, почему вы хотите, чтобы это было так, но это можно сделать с помощью следующего решения:

@Component
@ConfigurationProperties(prefix = "application", ignoreUnknownFields = false)
public class ApplicationProperties {

    public static class Kafka {
        private String topic1;
        private String topic2;

        public String getTopic1() {
            return topic1;
        }

        public void setTopic1(String topic1) {
            this.topic1 = topic1;
        }

        public String getTopic2() {
            return topic2;
        }

        public void setTopic2(String topic2) {
            this.topic2 = topic2;
        }
    }
    private Kafka kafka;

    public Kafka getKafka() {
        return kafka;
    }

    public void setKafka(Kafka kafka) {
        this.kafka = kafka;
    }
}
Ответ принят как подходящий

Ваш объект ApplicationProperties должен иметь поле с соответствующими геттерами и сеттерами для хранения экземпляра объекта Kafka. Поле должно называться kafka, чтобы соответствовать содержимому файла конфигурации:

@ConfigurationProperties(...)
public class ApplicationProperties {

    public static class Kafka {
        ...
    }

    private Kafka kafka;

    public Kafka getKafka() {
        return kafka;
    }

    public void setKafka(Kafka aKafka) {
        kafka = aKafka;
    }
}

Другие вопросы по теме