How can I @Autowire in an inner type in my custom @ConfigurationProperties?

138 Views Asked by At

Suppose I create my own custom config properties:

@ConfigurationProperties("a.b")
public record Custom(Topic topics) {
    public record Topics(String topicA, String topicB) {}
}

I can supply my properties in the properties file just fine and I can @Autowire them using the Custom type just fine.

But if I try to @Autowire my Topics it fails.

What is the best way to be able to @Autowire a nested configuration property type like this?

2

There are 2 best solutions below

0
Daniel Pereira On BEST ANSWER

You can achieve that by declaring a bean for your nested configuration. The bean will receive the base property as a param, and from there you extract the inner record you want:

@Configuration
@EnableConfigurationProperties(Custom.class)
public class TopicsConfiguration {

  @Bean
  public Topics topics(Custom custom) {
    return custom.topics();
  }

}
0
MKvectorartist01 On

In Spring Boot, you can use @ConfigurationProperties to bind external configuration properties to a Java object. If you want to use @Autowired within an inner type of your custom @ConfigurationProperties class, you can do so as long as the inner type is a Spring-managed component (e.g., a @Component, @Service, etc.). Here's a step-by-step guide on how to achieve this:

  1. Create a custom @ConfigurationProperties class with an inner component:
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

@Configuration
@ConfigurationProperties(prefix = "myconfig")
public class MyConfigurationProperties {

    private String property1;
    private InnerType innerType = new InnerType();

    public String getProperty1() {
        return property1;
    }

    public void setProperty1(String property1) {
        this.property1 = property1;
    }

    public InnerType getInnerType() {
        return innerType;
    }

    public void setInnerType(InnerType innerType) {
        this.innerType = innerType;
    }

    @Component
    public static class InnerType {
        private String innerProperty;

        public String getInnerProperty() {
            return innerProperty;
        }

        public void setInnerProperty(String innerProperty) {
            this.innerProperty = innerProperty;
        }
    }
}

In this example, MyConfigurationProperties is a @ConfigurationProperties class, and it contains an inner component class InnerType, which is annotated with @Component.

  1. Create a application.properties or application.yml file to define your configuration properties:
myconfig.property1=PropertyValue
myconfig.inner-type.inner-property=InnerPropertyValue
  1. Use @Autowired to inject the inner component (InnerType) into your Spring beans:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class MyService {

    private final MyConfigurationProperties.InnerType innerType;

    @Autowired
    public MyService(MyConfigurationProperties.InnerType innerType) {
        this.innerType = innerType;
    }

    public String getInnerProperty() {
        return innerType.getInnerProperty();
    }
}

In this example, MyService uses @Autowired to inject MyConfigurationProperties.InnerType, which is a Spring component defined within MyConfigurationProperties.

  1. Now, you can use MyService in your application to access the properties:
@Service
public class AnotherService {

    private final MyService myService;

    @Autowired
    public AnotherService(MyService myService) {
        this.myService = myService;
    }

    public String getInnerPropertyFromMyService() {
        return myService.getInnerProperty();
    }
}

By following these steps, you can use @Autowired within an inner type (InnerType) of your custom @ConfigurationProperties class and access its properties in other Spring-managed components.