16 de marzo de 2020

Propiedades y @Value

Spring Boot nos permite externalizar configuraciones como ofrece en una de sus ventajas. De hecho, al crear el proyecto con Spring Initialzr, automáticamente tenemos un nuestra carpeta resources un fichero llamado application.properties. Para encontrar este fichero sigue un convenio por defecto.

Al encontrarlo fichero será leído automáticamente junto con otras muchas fuentes de propiedades posibles (este fichero aparece el número 15). Sigue el mismo principio general que cuando sobrescribimos el bean con el XML: cuanto más unida está la propiedad al código menos prioridad tiene para permitir cambios externos.

Por otro lado, tendremos que leer esas propiedades cargadas y Spring nos ayuda con su anotación @Value para poder marcar un campo o un parámetro en el constructor e inyectar así el valor de una propiedad. El valor recuperado de una propiedad será un "String" que puede ser convertido por Spring para adaptarse al tipo de la variable siguiendo una sintaxis concreta.

Siguiendo con nuestro ejemplo vamos a ponerle un valor a nuestro testString que provenga de una propiedad. Para ello tenemos que poner nuestra propiedad en el fichero application.properties:
datos-deportivos.testString=String desde "application.properties"
Y luego inyectarlo en el campo:
@Value("${datos-deportivos.testString}")
String stringPropiedad;
Con esto se colocará el valor que tenga esa clave de entre todas las fuentes de propiedades y de forma priorizada (en nuestro caso sólo hay una fuente: application.properties)

Para ver ese valor habrá que sobrescribir el método init() pues no servirá querer asignárselo en el constructor (si se prueba se verá que el resultado tras construir el bean sería null). Vamos entonces a usar ese valor:
public void init() {
    testString = stringPropiedad;// System.out.println(stringPropiedad);
    super.init();
}
Por supuesto si hubiera un cambio en stringPropiedad afectaría al valor de testString. En este caso sería mejor inyectarle directamente este valor por el constructor añadiéndolo como parámetro. Primero voy a crearme otra propiedad distinta para diferenciarla de la anterior:
valor.parametro=String por constructor
Y ahora anoto con @Value al parámetro que quiero que tenga ese nuevo valor:
public Test(@Value("${valor.parametro}")// Para usarlo en constructor tiene que ser por parametro
            String stringPropiedad) { // Usa el constructor sin parametro si tambien existe
    System.out.println(stringPropiedad);
    testString = stringPropiedad;
}
De esta forma se asigna el valor de la propiedad al campo testString y el método init() se utiliza sin ningún cambio (ahora se puede ver que sí se dispone del valor dentro del constructor).

No es necesario tener todas las propiedades en un sólo fichero, de hecho sabemos que hay varias fuentes. De esta forma tiene sentido tener ficheros de propiedades para distintos aspectos de nuestra aplicación como el logging, el acceso a datos, credenciales o cambios para distintos entornos. Ahora voy a mover la propiedad valor.parametro a otro fichero nuevo en la misma carpeta que application.properties con el nombre application2.properties. Si ejecuto el código ahora veré que no es capaz de encontrar esa clave, pero se puede añadir un fichero a mi aplicación para contar también con sus propiedades simplemente marcándola con la anotación @ProperySource:
...
@PropertySource({"application2.properties"})
public class DatosdeportivosapiApplication { ... }
NOTA: @PropertySource no es válido para las propiedades que sean de logging ya que el logging se establece antes del ApplicationContext.

Ejecutándolo se va a ver todo correcto.

Aunque @Value parezca un recurso muy potente hay que usarlo con mesura dado que un cambio en un proyecto grande puede obligarnos a recorrer todo el proyecto en busca de una propiedad y además: "no deja de ser un simple String", con los errores tipográficos que puede conllevar. Para eso existen otras aproximaciones que aseguran un tipo, pero queda fuera de lo que se pretende en esta entrada.

Puedes obtener el código hasta este punto en su repositorio.

Lo siguiente será utilizar esta configuración para ver que es el logging, usarlo y personalizarlo con propiedades.

No hay comentarios:

Publicar un comentario

Compárteme

Entradas populares