17

I have a class of the sort :

@Data
@Component
@ConfigurationProperties("a.config.props")
public class ClientProperties {

    private String hostname;
    private String port;
    private String baseUrl;
    private String endpoint;
}

I have tens of property contexts but for 1 line i have to repeat the whole class. Is there a simple and elegant way to have one class and somehow pass the property context dynamically (maybe an array or something of the sort) so that i use the same class.

3 Answers 3

27

You can just have a single class that describes your numerous & identical property blocks;

@Data
public class ClientProperties {
    private String hostname;
    private String port;
    private String baseUrl;
    private String endpoint;
}

Then refer to it as such to link that single class with different property blocks;

@Configuration
public class PropertyConfigurer {

    @Bean
    @ConfigurationProperties("props.one")
    private ClientProperties propsOne() {
        return new ClientProperties();
    }

    @Bean
    @ConfigurationProperties("props.two")
    private ClientProperties propsTwo() {
        return new ClientProperties();
    }

    @Bean
    @ConfigurationProperties("props.three")
    private ClientProperties propsThree() {
        return new ClientProperties();
    }
}

Then you can access them via their method names as qualifiers;

@Component
public class SomeService {

    @Autowired
    private ClientProperties propsOne;
    @Autowired
    private ClientProperties propsTwo;
    @Autowired
    private ClientProperties propsThree;

    ... some logic
}
Sign up to request clarification or add additional context in comments.

7 Comments

I would also require many instances so the scope would be prototype for clientProperties. So can i get rid of the class PropertyConfigurer ?
@Raghuveer why get rid of the class? I don't understand your point. You have to define like that to bind that class structure for each property block with its path in property file. You cannot just have the ClientProperties with @Component & refer to multiple blocks.
thanks for your quick response. I want all the beans to be spring managed, thats why i want prototype but i want each property context to be bound with the class and instantiated. Any spring tricks ?
@Raghuveer I don't understand, it is default Spring bean declaration through methods. It is given as the default method in the documentation for declaring beans for properties. There is no any such trick, you can do like Sumant suggesting, but that also creates many classes on top of the abstract class which is a mess. The cleanest solution is this one in my opinion.
Is it also possible do this with record instead of mutable class?
|
7

I would suggest to create an abstract class with all the properties and extend the abstract class for as many property variants you have.

@Data
public abstract class BaseClientProperties {
    private String hostname;
    private String port;
    private String baseUrl;
    private String endpoint;
}

@Configuration
@ConfigurationProperties("a.config.props1")
public class Client1Properties extends BaseClientProperties{

}

@Configuration
@ConfigurationProperties("a.config.props2")
public class Client2Properties extends BaseClientProperties{
}

Use them as below:

@Service
public class SomeService {

    @Autowired
    private Client1Properties client1Properties;
    @Autowired
    private Client2Properties client2Properties;

    ... service logic
}

1 Comment

IMHO this is better as it uses abstraction properly.
0

Suppose you want hostname as a list to your properties file then you can rearrange your code like this:

@Component
@ConfigurationProperties("a.config.props")
@Data
public class ClientProperties {
    private List<String>  hostname;
    private String port;
    private String baseUrl;
    private String endpoint;
}

You can then place your configuration properties in your application.properties file like this:

a.config.props.hostname[0]=host1.com
a.config.props.hostname[1]=host2.com
a.config.props.hostname[2]=host3.com
a.config.props.port=8080
a.config.props.baseUrl=baseurl
a.config.props.endpoint=/thisendpoint

Then simply @Autowire your ClientProperties to the class you want and call

List<String> hostnames = clientProperties.getHostname();

You can utilize their values as required then. If I understand your question correctly I think this will answer it. Let me know if you need more information.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.