Using Configuration classes in place of @Values in Springboot

Owolabi Tobiloba
2 min readApr 15, 2023

--

I was recently working on a Springboot project and I had to integrate with an external API. As usual, I had a few properties in my application.yml and I was doing what a newbie to Springboot would do which is using @Values to pass in the values from the YAML file into my service file.

As time went on and I added more properties, my service class got littered with property values everywhere.

Say your properties file looks like this

  my-app:
external-service:
api-key: ${API_KEY:api_key}
urls:
base-url: ${BASE_URL:https://externalservice.com}
customer-url: ${CUSTOMER_URL:https://externalservice.com/customers}
account-url: ${SUB_ACCOUNT_URL:https://externalservice.com/accounts}
// Autowired variables...
...
@Value("${external-service.api-key}")
private String apiKey
@Value("${external-service.urls.base-url}")
private String baseUrl
@Value("${external-service.urls.customer-url}")
private String customerUrl
@Value("${external-service.urls.account-url}")
private String accountUrl
// Other parts of the service
...

Things can get messy really quickly as the integration continues to evolve.
How I have learnt to keep this clean is by using a configuration class. For you to do that though, you need to add a maven dependency to your pom file.

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>

Then you can create a configuration class. A configuration class is just a normal class annotated with @Configuration. Your class might look like below

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

@Data
@Configuration
@ConfigurationProperties(prefix = "my-app.external-service")
public class ExternalServiceConfiguration {
private String apiKey;
private ExternalServiceUrls urls;

@Data
public static class ExternalServiceUrls {
private String baseUrl;
private String customerUrl;
private String accountUrl;
}
}

Note: The name of the variable for the urls has to match the name in the application.yaml file. if the structure was external-service: urls-changed: //blabla, then the variable name in the configuration class has to be private ExternalService urlsChanged. (hyphens should be replaced with capitalizing the first character of the word.)

The example above shows how you can handle both normal and nested properties. I use the @Data annotation from Lombok to provide automatic getters and setters.
Now you can get rid of all the @Values at the top of our service file and just autowire our newly created ExternalServiceConfiguration like normal.

// Other autowired beans
...
private final ExternalServiceConfiguration externalServiceConfiguration;
// Other autowired beans
...

Now replace any occurence of the previous @Values variables with their respective variables in the ExternalServiceConfiguration object. E.g.

 HttpEntity<Request> customerEntity = new HttpEntity<>(Request, headers);
log.info("Creating Customer Account on external service");
ResponseEntity<Response> response =
restTemplate.exchange(
externalServiceConfiguration.getUrls().getCustomerUrl(),
HttpMethod.POST,
customerEntity,
Response.class);

Clean and straightforward. You can read more on their official documentation here.

If you found this useful, don’t forget to share. Also you can drop your feedback in the comments

--

--

Owolabi Tobiloba
Owolabi Tobiloba

Written by Owolabi Tobiloba

Java Backend Engineer. Interested in developing highly scalable distributed systems

No responses yet