Tips Spring : [BOOT] propiedades de configuración personalizadas

logo spring

Los parámetros de configuración de Spring Boot y las librerías compatibles se definen en el fichero /src/main/resources/application.properties (o application.yml para los que prefieran el formato YAML). Los disponibles se detallan en esta página.

Además, seguimos contando con la posibilidad de crear nuestros ficheros de configuración con los mecanismos estándar de Spring. A ellos dedico este extenso artículo. No obstante, voy a indicar los pasos para hacerlo rápidamente.

  • Añadir el fichero al classpath dentro de /src/main/resources, siempre y cuando vaya a ser empaquetado en la aplicación.
song=ride like the wind
  • Importarlo en una clase de configuración (anotada con @Configuration, ya implícita en @SpringBootApplication) con @PropertySource. Admite una lista de ficheros ubicados en el classpath y \ o en una ruta absoluta en el sistema de archivos (prefijo file:).
@SpringBootApplication
@PropertySource("classpath:custom.properties")
public class SpringBootPropertiesApplication {
  • Inyectamos las propiedades de forma individual con @Value.
@SpringBootTest
class CustomPropertiesTests {

    @Value("${song}")
    private String song;

    @Test
    void testSongFromValue() {
        assertEquals(SONG_NAME, song);
    }

}
@Autowired
 private Environment environment;

@Test
void testSongFromEnvironment() {
    String song = environment.getProperty("song");

    assertEquals(SONG_NAME, song);
}

Podemos escribir nuestros propios parámetros en el application.properties y leerlos con las dos estrategias que acabo de explicar. Sin embargo, la razón de ser de este pequeño artículo es que Spring Boot, gracias a la anotación @ConfigurationProperties, permite modelar en clases esos parámetros para abstraer su uso con métodos getters. De este modo, no necesitamos ni conocer ni codificar sus nombres en constantes.

Vamos a crear una clase que modele un grupo de propiedades de configuración en atributos con sus correspondientes getters y setters. La marcamos con @ConfigurationProperties y en ella declaramos, opcionalmente, el prefijo de las propiedades. Lo razonable es agrupar las propiedades que se utilizan para configurar cierta librería o módulo de nuestra aplicación siguiendo una jerarquía de nombres, tal y como hace Spring Boot (spring.datasource, spring.mvc, etcétera).

Los atributos pueden validarse con las anotaciones de Bean Validation (en este caso la clase debe ser anotada con @Validated), lo que precisa añadir spring-boot-starter-validation al pom.xml.

<dependency>
   <groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
package com.danielme.springboot;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;

import javax.validation.constraints.NotBlank;

@Validated
@ConfigurationProperties("custom")
public class CustomProperties {

    @NotBlank
    private String song;

    public String getSong() {
        return song;
    }

    public void setSong(String song) {
        this.song = song;
    }
}

La anotación @NotBlank impone que el valor exista y no sea una cadena de espacios en blanco. Si no se satisface esta restricción, se lanzará una excepción y el inicio de Spring se aborta. Esto nos asegura que la configuración sea correcta.

***************************
APPLICATION FAILED TO START
***************************
Description:
Binding to target org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'custom' to com.danielme.springboot.CustomProperties failed:

    Property: custom.song
    Value: "null"
    Reason: must not be blank

Action:

Update your application's configuration

La clase CustomProperties hay que declararla en la configuración de Spring con @EnableConfigurationProperties, o bien activar el escaneo automático de las clases con propiedades con @ConfigurationPropertiesScan, anotación disponible a partir de Spring Boot 2.2 (octubre 2019). Por comodidad, he optado por la segunda opción.

@SpringBootApplication
@PropertySource("classpath:custom.properties")
@ConfigurationPropertiesScan
public class SpringBootPropertiesApplication {

Ahora leemos las propiedades inyectando CustomProperties y llamando a sus getters.

@Autowired
private CustomProperties customProperties;

@Test
void testConfigurationPropertiesClass() {
    assertEquals(SONG_NAME, customProperties.getSong());
}

Naturalmente, para que la prueba anterior sea exitosa la propiedad debe existir en el application.properties. De hecho, la hemos declarado como obligatoria.

custom.song = ride like the wind

También es posible utilizar una clase de tipo @ConfigurationProperties para recoger las valores de cualquier fichero de configuración. Tan sencillo como importar esos ficheros con la anotación @ConfigurationProperties que vimos al principio del tip (no hay por qué hacerlo en la clase @ConfigurationProperties).

@Configuration
@Validated
@ConfigurationProperties
@PropertySource("classpath:servers.properties")
public class ServersProperties {

    @NotBlank
    private String email;
    @NotBlank
    private String ftp;

Un último consejo. Si añadimos al pom la siguiente dependencia

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

al compilar el proyecto se creará el fichero /target/classes/META-INF/spring-configuration-metadata.json que detalla las propiedades personalizadas.

{
  "groups": [
    {
      "name": "custom",
      "type": "com.danielme.springboot.CustomProperties",
      "sourceType": "com.danielme.springboot.CustomProperties"
    }
  ],
  "properties": [
    {
      "name": "custom.song",
      "type": "java.lang.String",
      "sourceType": "com.danielme.springboot.CustomProperties"
    }
  ],
  "hints": []
}

Esta información permite a los IDE como IntelliJ Ultimate ofrecer autocompletado en el fichero de configuración, entre otras funcionalidades.

Código de ejemplo

El código de ejemplo se encuentra en GitHub. Para más información sobre cómo utilizar GitHub, consultar este artículo.

Deja una respuesta

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Salir /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Salir /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Salir /  Cambiar )

Conectando a %s

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.