Capítulo 4. Configuración
Este trabajo se ha traducido utilizando IA. Agradecemos tus opiniones y comentarios: translation-feedback@oreilly.com
En este capítulo aprenderás lo siguiente sobre cómo establecer los parámetros de configuración:
-
Cómo configurar un servicio Quarkus
-
Cómo inyectar parámetros de configuración en el servicio
-
Cómo aplicar los valores en función del entorno
-
Cómo configurar correctamente el sistema de registro
-
Cómo crear personalizaciones para el sistema de configuración
4.1 Configurar la Aplicación con Propiedades Personalizadas
Solución
Quarkus utiliza varias especificaciones del Microperfil de Eclipse. Una de ellas es la especificación Configuración; sin embargo, para simplificar la configuración, Quarkus utiliza un único archivo para todas las configuraciones, application.properties, que debe colocarse en la raíz del classpath.
Este archivo puede utilizarse para configurar propiedades de Quarkus como el registro o la ruta por defecto, extensiones de Quarkus como el origen de datos o Kafka, o propiedades personalizadas que definas para la aplicación. Vas a verlas todas en el libro, pero en esta receta, verás esta última.
Abre el archivo src/main/resources/application.properties y añade la siguientepropiedad:
greeting.message
=
Hello World
Puedes inyectar el valor de la propiedad definida en application.properties utilizando la anotación org.eclipse.microprofile.config.inject.ConfigProperty
en un campo.
Abre org.acme.quickstart.GreetingResource.java
e inyecta el valor de la propiedad greeting.message
:
@ConfigProperty
(
name
=
"greeting.message"
)
String
message
;
@GET
@Produces
(
MediaType
.
TEXT_PLAIN
)
public
String
hello
(
)
{
return
message
;
}
Inyecta el valor de la propiedad
greeting.message
Coloca los campos en el ámbito protegido del paquete
Devuelve el valor configurado
Consejo
Por razones de rendimiento al utilizar GraalVM y la reflexión, te animamos a que utilices el ámbito paquete-protegido en los campos que se inyectarán en tiempo de ejecución. Puedes leer más sobre ello en la Guía de Referencia CDI de Quarkus.
En una nueva ventana de terminal, haz una petición a /hello
para comprobar que el mensaje de salida es el valor configurado en application.properties:
curl http://localhost:8080/hello
Hello World
Si quieres que un campo de configuración no sea obligatorio y proporcionar un valor por defecto, puedes utilizar el atributo defaultValue
de la anotación @ConfigProperty
.
Abre el archivo org.acme.quickstart.GreetingResource.java
e inyecta el valor de la propiedad greeting.upper-case
:
@ConfigProperty
(
name
=
"greeting.upper-case"
,
defaultValue
=
"true"
)
boolean
upperCase
;
@GET
@Path
(
"/optional"
)
@Produces
(
MediaType
.
TEXT_PLAIN
)
public
String
helloOptional
(
)
{
return
upperCase
?
message
.
toUpperCase
(
)
:
message
;
}
Y en una ventana de terminal, haz una petición a /hello/optional
para ver que el mensaje de salida está en mayúsculas:
curl http://localhost:8080/hello/optional
HELLO WORLD
Se admiten propiedades multivalor: sólo tienes que definir el tipo de campo como uno de los siguientes: Arrays
, java.util.List
o java.util.Set
, según tus requisitos/preferencias. El delimitador del valor de la propiedad es una coma (,
) y el carácter de escape es la barra invertida (\
).
Abre el archivo src/main/resources/application.properties y añade la siguiente propiedad con tres valores:
greeting.suffix
=
!!, How are you???
Abre org.acme.quickstart.GreetingResource.java e inyecta los valores de la propiedad greeting.suffix
:
@ConfigProperty
(
name
=
"greeting.suffix"
)
List
<
String
>
suffixes
;
@GET
@Path
(
"/list"
)
@Produces
(
MediaType
.
TEXT_PLAIN
)
public
String
helloList
()
{
return
message
+
suffixes
.
get
(
1
);
}
Y en una ventana de terminal haz una petición a /hello/list
para ver que el mensaje de salida contiene el segundo sufijo:
curl http://localhost:8080/hello/list
Hello World How are you?
También se admite el formato YAML para configurar la aplicación. En este caso, el archivo se llama application.yaml o application.yml.
Para empezar a utilizar el archivo de configuración YAML, tienes que añadir laextensión config-yaml
:
./mvnw quarkus:add-extension -Dextensions="config-yaml"
Dado el siguiente archivo de configuración utilizando el formato properties
:
greeting.message
=
Hello World
%staging.quarkus.http.port
=
8182
quarkus.http.cors
=
true
quarkus.http.cors.methods
=
GET,PUT,POST
El equivalente en formato YAML es el siguiente
greeting
:
message
:
Hello
World
"
%staging
"
:
quarkus
:
http
:
port
:
8182
quarkus
:
http
:
cors
:
~
:
true
methods
:
GET,PUT,POST
Debate
La Configuración de Eclipse MicroProfile viene con los siguientes conversores incorporados para mapear un valor de configuración en un objeto Java:
-
boolean
yjava.lang.Boolean
; los valores de verdadero sontrue
,1
,YES
,Y
, yON
, mientras que cualquier otro valor se considerafalse
-
byte
yjava.lang.Byte
-
short
yjava.lang.Short
-
int
yjava.lang.Integer
-
long
yjava.lang.Long
-
float
yjava.lang.Float
-
double
yjava.lang.Double
-
char
yjava.lang.Character
-
java.lang.Class
en función del resultado de la llamada aClass.forName
Si no existe un convertidor incorporado o personalizado, se comprueban los siguientes métodos en el objeto destino. Si existe un convertidor incorporado o personalizado, se utiliza el método descubierto/encontrado para instanciar el objeto convertidor y se pasa el argumento cadena para la conversión :
-
El tipo de destino tiene el método
public static T of(String)
-
El tipo de destino tiene el método
public static T valueOf(String)
-
El tipo objetivo tiene un constructor público con un parámetro
String
-
El tipo de destino tiene el método
public static T parse(CharSequence)
4.2 Acceder a las propiedades de configuración mediante programación
Solución
Inyecta la clase org.eclipse.microprofile.config.Config
en el objeto al que quieras acceder a las propiedades mediante programación.
La especificación de configuración de microperfiles de Eclipse te permite inyectar org.eclipse.microprofile.config.Config
para obtener propiedades mediante programación en lugar de inyectar directamente con ConfigProperty
.
Abre org.acme.quickstart.GreetingResource.java
e inyecta la clase Config
:
@Inject
Config
config
;
@GET
@Path
(
"/config"
)
@Produces
(
MediaType
.
TEXT_PLAIN
)
public
String
helloConfig
(
)
{
config
.
getPropertyNames
(
)
.
forEach
(
p
-
>
System
.
out
.
println
(
p
)
)
;
return
config
.
getValue
(
"greeting.message"
,
String
.
class
)
;
}
Utiliza la anotación
Inject
CDI para inyectar la instanciaAhora puedes acceder a la lista de propiedades
La propiedad debe convertirse al tipo final
Puedes acceder a la clase Config
sin utilizar el CDI llamando al método ConfigProvider.getConfig()
.
4.3 Sobrescribir valores de configuración externamente
Solución
Puedes sobrescribir cualquier propiedad en tiempo de ejecución estableciéndola como propiedad del sistema o variable de entorno.
Quarkus te permite sobrescribir cualquier propiedad de configuración estableciéndolacomo propiedad del sistema (-Dproperty.name=value
) y/o como variable de entorno (export PROPERTY_NAME=value
). Las propiedades del sistema tienen más prioridad que las variables de entorno.
Ejemplos de externalización de estas propiedades pueden ser la URL de una base de datos, el nombre de usuario o la contraseña, porque sólo se conocen en el entorno de destino. Pero debes saber que hay una contrapartida, porque cuantas más propiedades en tiempo de ejecución estén disponibles, menos trabajo previo en tiempo de compilación podrá hacer Quarkus.
Vamos a empaquetar la aplicación utilizada en la Receta 4.1 y anular la propiedad greeting.message
estableciendo una propiedad del sistema:
./mvnw clean package -DskipTests
java -Dgreeting.message=Aloha -jar target/getting-started-1.0-SNAPSHOT-runner.jar
En una nueva ventana de terminal, valida que la propiedad se ha anulado de Hello World
a Aloha
ejecutando:
curl localhost:8080/hello
Aloha
En el caso de las variables de entorno, se admiten tres convenciones de nomenclatura para un nombre de propiedad determinado. Esto se debe a que algunos sistemas operativos sólo permiten caracteres alfabéticos y guiones bajos (_
), pero no otros caracteres, como puntos (.
). Para admitir todos los casos posibles, se utilizan las siguientes reglas:
-
Coincidencia exacta (
greeting.message
). -
Sustituye los caracteres no alfanuméricos por guiones bajos (
greeting_message
). -
Sustituye los caracteres no alfanuméricos por guiones bajos y convierte el resto a mayúsculas (
GREETING_MESSAGE
).
Aquí tienes el archivo application.properties:
greeting.message
=
Hello World
Puedes anular su valor utilizando cualquiera de los siguientes nombres de variables de entorno, ya que todas ellas son equivalentes:
export greeting.message=Aloha
export greeting_message=Aloha
export GREETING_MESSAGE=Aloha
También hay un lugar especial donde puedes poner el archivo application. properties fuera de la propia aplicación, dentro de un directorio llamado config donde se ejecuta la aplicación. Cualquier propiedad de ejecución definida en ese archivo anulará la configuración por defecto.
Importante
config/application.properties también funciona en modo desarrollo, pero necesitas añadirlo en el directorio de salida de tu herramienta de construcción para que funcione (en el caso de Maven, el directorio de destino; en el caso de Gradle, el de construcción), por lo que debes ser consciente de la necesidad de volver a crearlo al ejecutar la tarea clean
.
Aparte de las variables de entorno y del archivo application.properties, también puedes colocar un archivo .env en el directorio de trabajo actual para anular los valores de configuración,siguiendo el formato de las variables de entorno (GREETING_MESSAGE=Aloha
).
4.4 Configurar con Perfiles
Solución
Quarkus admite la noción de perfiles de configuración, que te permiten tener varios valores de configuración para la misma propiedad en el mismo archivo y habilitar distintos valores para adaptarlos al entorno en el que estés ejecutando el servicio.
La sintaxis de los perfiles de configuración es %{profile}.config.key=value
.
Discute
Quarkus viene con tres perfiles incorporados.
- dev
-
Se activa cuando estás en modo de desarrollo (es decir,
quarkus:dev
). - prueba
-
Se activa al ejecutar pruebas.
- prod
-
El perfil por defecto cuando no se ejecuta en modo desarrollo o prueba; no necesitas establecerlo en application.properties, ya que se establece implícitamente.
Abre el archivo src/main/resources/application.properties y configúralo para que inicie Quarkus en el puerto 8181 en modo desarrollo:
%dev.quarkus.http.port
=
8181
Tras este cambio, inicia el servicio para comprobar de nuevo que el puerto de escucha es el 8181 en lugar del predeterminado (8080):
./mvnw compile quarkus:dev
INFO [io.qua.dep.QuarkusAugmentor] (main) Beginning quarkus augmentation
INFO [io.qua.dep.QuarkusAugmentor] (main) Quarkus augmentation completed
in 671ms
INFO [io.quarkus] (main) Quarkus 1.4.1 started in 1.385s. Listening on:
http://0.0.0.0:8181
INFO [io.quarkus] (main) Profile dev activated. Live Coding activated.
INFO [io.quarkus] (main) Installed features:
[cdi, hibernate-validator, resteasy]
Observa que ahora la dirección de escucha eshttp://0.0.0.0:8181 en lugar de la predeterminada.
Finalmente, retrocede al puerto 8080, elimina la línea %dev.quarkus.http.port=8181
en application.properties para alinearlo con el puerto que se utiliza en el resto del libro.
4.5 Cambiar la configuración del registrador
Solución
Quarkus utiliza un modelo de configuración unificado en el que todas las propiedades de configuración se colocan en el mismo archivo. En el caso de Quarkus, este archivo es application.properties, y en él puedes configurar muchos aspectos del registro.
Por ejemplo, si quieres cambiar el nivel de registro, sólo tienes que poner quarkus.log.level
al nivel mínimo de registro.
Abre src/main/resources/application.properties y añade el siguiente contenido:
quarkus.log.level
=
DEBUG
Ahora inicia la aplicación para ver que se imprimen muchos mensajes de registro nuevos en la consola:
./mvnw compile quarkus:dev
...
[INFO] --- quarkus-maven-plugin:0.22.0:dev (default-cli) @ getting-started ---
Listening for transport dt_socket at address: 5005
DEBUG [org.jbo.logging] (main) Logging Provider: \
org.jboss.logging.JBossLogManagerProvider
INFO [io.qua.dep.QuarkusAugmentor] (main) Beginning quarkus augmentation
DEBUG [io.qua.run.con.ConverterSupport] (main) Populate SmallRye config builder
with converter for class java.net.InetSocketAddress of priority 200
DEBUG [io.qua.run.con.ConverterSupport] (main) Populate SmallRye config builder
with converter for class org.wildfly.common.net.CidrAddress of priority 200
Nota
Hemos tenido que abarcar varias líneas para dar formato al libro; hemos utilizado la barra invertida para indicarlo.
También puedes activar el almacenamiento de registros en un archivo mediante la propiedad quarkus.log.file.enable
. La salida se escribe por defecto en un archivo llamado quarkus.log:
quarkus.log.file.enable
=
true
Nota
Mientras estés en desarrollo y trabajando desde el directorio fuente, tu archivo de registro estará en el directorio destino.
4.6 Añadir Registros de Aplicación
Solución
La mayoría de las veces, tus aplicaciones necesitan escribir sus propios mensajes de registro y no depender únicamente de los registros por defecto proporcionados por Quarkus. Las aplicaciones pueden utilizar cualquiera de las API admitidas para el registro, y los registros se fusionarán.
Quarkus admite estas bibliotecas de registro:
-
JDK java.util.logging
-
Registro JBoss
-
SLF4J
-
Registro de Apache Commons
Veamos cómo utilizar JBoss Logging
para registrar contenidos. Abre org.acme.quickstart.GreetingResource.java
y registra un mensaje cuando se llame a un punto final especial:
private
static
org
.
jboss
.
logging
.
Logger
logger
=
org
.
jboss
.
logging
.
Logger
.
getLogger
(
GreetingResource
.
class
)
;
@GET
@Path
(
"/log"
)
@Produces
(
MediaType
.
TEXT_PLAIN
)
public
String
helloLog
(
)
{
logger
.
info
(
"I said Hello"
)
;
return
"hello"
;
}
Ahora inicia la aplicación:
./mvnw compile quarkus:dev
En una nueva terminal, haz una petición a /hello/log
:
curl http://localhost:8080/hello/log
Si inspeccionas el terminal en el que iniciaste Quarkus, verás el siguiente logline:
INFO [org.acm.qui.GreetingResource] (executor-thread-1) I said Hello
Debate
El registro se realiza por categorías. Una configuración que se aplica a una categoría también se aplica a todas las subcategorías de esa categoría, a menos que haya una configuración de subcategoría coincidente más específica.
Las categorías están representadas por la ubicación de la clase (es decir, el paquete, o subpaquetes,donde están definidas). Por ejemplo, si quieres establecer el registro de seguridad de Undertowen el nivel de rastreo, tienes que establecer la propiedadquarkus.log.category."io.undertow.request.security".level=TRACE
en application.properties.
Siguiendo el ejemplo anterior, restrinjamos las líneas de registro de las clases que residen en org.acme.quickstart
(y subclases) para que el nivel mínimo de registro sea WARNING
:
quarkus.log.category."org.acme.quickstart".level
=
WARNING
Si repites la solicitud ahttp://localhost:8080/hello/log, ya no se escribirá el logline.
4.7 Registro avanzado
Solución
Cuando se trabaja con arquitecturas de microservicios y Kubernetes, el registro es algo importante a tener en cuenta, porque cada servicio se registra individualmente; pero como desarrollador u operador, puede que quieras tener todos los registros centralizados en un lugar para poder consumirlos en conjunto.
El registro de Quarkus también admite salida JSON y GELF.
Estos registros pueden escribirse en formato JSON, en lugar de texto plano, para que los procese la máquina, registrando la extensión logging-json
:
./mvnw quarkus:add-extension -Dextensions="logging-json"
Utiliza la extensión GELF para producir registros en formato GELF y enviarlos utilizando TCP o UDP.
Elformato de registro Graylog extendido (GELF) lo entienden tres de los sistemas de registro más centralizados que se utilizan hoy en día :
-
Graylog (MongoDB, Elasticsearch, Graylog)
-
ELK (Elasticsearch, Logstash, Kibana)
-
EFK (Elasticsearch, Fluentd, Kibana)
Para empezar a registrar en formato GELF, sólo tienes que añadir laextensión logging-gelf
:
./mvnw quarkus:add-extension -Dextensions="logging-gelf"
El código de registro no cambia, por lo que se utilizan las mismas interfaces:
private
static
org
.
jboss
.
logging
.
Logger
logger
=
org
.
jboss
.
logging
.
Logger
.
getLogger
(
GreetingResource
.
class
)
;
@GET
@Path
(
"/log"
)
@Produces
(
MediaType
.
TEXT_PLAIN
)
public
String
helloLog
(
)
{
logger
.
info
(
"I said Hello"
)
;
return
"hello"
;
}
El controlador GELF debe configurarse en application.properties:
quarkus.log.handler.gelf.enabled
=
true
quarkus.log.handler.gelf.host
=
localhost
quarkus.log.handler.gelf.port
=
12201
Activa la extensión
Establece el host al que se envían los mensajes de registro
Establece el puerto del punto final
Importante
Si utilizas Logstash (ELK), tienes que activar el complemento de entrada que entiende el formato GELF:
input { gelf { port => 12201 } } output { stdout {} elasticsearch { hosts => ["http://elasticsearch:9200"] } }
Importante
Si utilizas Fluentd (EFK), tienes que activar el plug-in de entrada que entiende el formato GELF:
<source> type gelf tag example.gelf bind 0.0.0.0 port 12201 </source> <match example.gelf> @type elasticsearch host elasticsearch port 9200 logstash_format true </match>
Debate
El registro de Quarkus también admite el formato syslog por defecto, sin necesidad de añadir ninguna extensión. El formato syslog puede utilizarse en Fluentd como alternativa al formato GELF en Quarkus:
quarkus.log.syslog.enable
=
true
quarkus.log.syslog.endpoint
=
localhost:5140
quarkus.log.syslog.protocol
=
udp
quarkus.log.syslog.app-name
=
quarkus
quarkus.log.syslog.hostname
=
quarkus-test
Importante
Necesitas activar el complemento de entrada que entiende el formato syslog en Fluentd:
<source> @type syslog port 5140 bind 0.0.0.0 message_format rfc5424 tag system </source> <match **> @type elasticsearch host elasticsearch port 9200 logstash_format true </match>
Si utilizas Kubernetes, la forma más sencilla de registrar es acceder a la consola e instalar en el clúster un gestor central de registros que recoja todas las líneas de registro.
4.8 Configurar con perfiles personalizados
Solución
Hasta ahora, has visto que Quarkus viene con perfiles incorporados para que puedas establecer distintos valores de configuración para una misma propiedad y habilitarlos según el entorno. Pero con Quarkus, también puedes establecer tus propios perfiles.
Lo único que tienes que hacer es especificar qué perfil quieres activar utilizando la propiedad del sistema quarkus.profile
o la variable de entorno QUARKUS_PROFILE
. Si ambas están activadas, la propiedad del sistema tiene prioridad sobre lavariable de entorno.
Entonces, lo único que tienes que hacer es crear la propiedad con el nombre del perfil y establecer el perfil actual con ese nombre. Vamos a crear un nuevo perfil de montaje que sobrescriba el puerto de escucha de Quarkus.
Abre el archivo src/main/resources/application.properties y establece que Quarkus se inicie en el puerto 8182 cuando el perfil staging
esté activado:
%staging.quarkus.http.port
=
8182
A continuación, inicia la aplicación con el perfil staging
activado:
./mvnw -Dquarkus.profile=staging compile quarkus:dev
INFO [io.qua.dep.QuarkusAugmentor] (main) Beginning quarkus augmentation
INFO [io.qua.dep.QuarkusAugmentor] (main) Quarkus augmentation completed
in 640ms
INFO [io.quarkus] (main) Quarkus 0.23.2 started in 1.300s. Listening on:
http://0.0.0.0:8182
INFO [io.quarkus] (main) Profile staging activated. Live Coding activated.
INFO [io.quarkus] (main) Installed features: [cdi, hibernate-validator,
resteasy]
En este caso, se utiliza el método de la propiedad del sistema, pero también podrías establecerlo utilizando la variable de entorno QUARKUS_PROFILE
.
Debate
Si quieres establecer el perfil de ejecución en las pruebas, sólo tienes que establecer la propiedad del sistema quarkus.test.profile
al perfil dado en tu script de construcción, por ejemplo, en Maven:
<groupId>
org.apache.maven.plugins</groupId>
<artifactId>
maven-surefire-plugin</artifactId>
<version>
${surefire-plugin.version}</version>
<configuration>
<systemPropertyVariables>
<quarkus.test.profile>
foo</quarkus.test.profile>
<buildDirectory>
${project.build.directory}</buildDirectory>
</systemPropertyVariables>
</configuration>
o, en Gradle:
test
{
useJUnitPlatform
()
systemProperty
"quarkus.test.profile"
,
"foo"
}
También puedes cambiar el perfil de producción por defecto. El perfil incorporado en Quarkus es prod
, de modo que cuando ejecutas tu aplicación sin ningún perfil, éste es el que se toma por defecto. Pero puedes cambiarlo en tiempo de compilación para que, sin especificar ningún perfil, tu perfil sea el que se tome por defecto cuando se ejecute la aplicación.
Lo único que tienes que hacer es construir la aplicación utilizando la propiedad del sistema quarkus.profile
con el valor del perfil que quieras establecer como predeterminado:
./mvnw package -Pnative -Dquarkus.profile=prod-kubernetes`
./target/getting-started-1.0-runner
4.9 Crear fuentes personalizadas
Solución
Quarkus utiliza la especificación Eclipse MicroProfile Configuration para implementar toda la lógica relativa a la configuración. La especificación ofrece la interfazorg.eclipse.microprofile.config.spi.ConfigSource
Java SPI para implementar una formapersonalizada de cargar las propiedades de configuración en lugar de/aparte de laproporcionada por defecto por Quarkus.
Por ejemplo, podrías cargar propiedades de configuración desde una base de datos, un archivo XML o una API REST.
Vamos a crear una sencilla fuente de configuración en memoria que obtenga las propiedades de configuración de Map
pobladas en tiempo de instanciación. Crea una nueva clase llamada org.acme.quickstart.InMemoryConfigSource.java
:
package
org
.
acme
.
quickstart
;
import
java.util.HashMap
;
import
java.util.Map
;
import
org.eclipse.microprofile.config.spi.ConfigSource
;
public
class
InMemoryConfigSource
implements
ConfigSource
{
private
Map
<
String
,
String
>
prop
=
new
HashMap
<
>
(
)
;
public
InMemoryConfigSource
(
)
{
prop
.
put
(
"greeting.color"
,
"red"
)
;
}
@Override
public
int
getOrdinal
(
)
{
return
500
;
}
@Override
public
Map
<
String
,
String
>
getProperties
(
)
{
return
prop
;
}
@Override
public
String
getValue
(
String
propertyName
)
{
return
prop
.
get
(
propertyName
)
;
}
@Override
public
String
getName
(
)
{
return
"MemoryConfigSource"
;
}
}
Rellena el mapa con una propiedad
Se utiliza para determinar la importancia de los valores; el ordinal más alto tiene prioridad sobre el ordinal de menor prioridad
Obtiene todas las propiedades como
Map
; en este caso es directoObtiene el valor de una sola propiedad
Devuelve el nombre de esta fuente de configuración
A continuación, tienes que registrarlo como un SPI Java. Crea la carpeta services en src/main/resources/META-INF. Después, crea un archivo dentro de services llamado org.eclipse.microprofile.config.spi.ConfigSource con el siguiente contenido:
org.acme.quickstart.InMemoryConfigSource
Por último, puedes modificar la clase org.acme.quickstart.GreetingResource.java
para inyectar esta propiedad:
@ConfigProperty
(
name
=
"greeting.color"
)
String
color
;
@GET
@Path
(
"/color"
)
@Produces
(
MediaType
.
TEXT_PLAIN
)
public
String
color
(
)
{
return
color
;
}
Y en una ventana de terminal haz una petición a /hello/color
para ver que el mensaje de salida es el valor configurado en la fuente personalizada:
curl http://localhost:8080/hello/color
red
Debate
Cada ConfigSource
tiene un ordinal especificado, que se utiliza para establecer la importancia de los valores tomados del ConfigSource
en el caso de múltiples fuentes de configuración definidas para la misma aplicación. Un ConfigSource
de ordinal superior se utiliza sobre un ConfigSource
con un valor inferior. Utilizando como referencia los valores predeterminados de la siguiente lista, se utilizará una propiedad del sistema sobre todo, y se utilizará el archivo application. properties del directorio src/main/resources si no se encuentra ningún otro ConfigSources
:
-
Propiedades del sistema a 400
-
Variables de entorno a 300
-
application.properties en el directorio config a 260
-
application.properties en el proyecto a 250
4.10 Crear conversores personalizados
Solución
Puedes convertir una propiedad de String
a cualquier tipo de objeto implementando el SPI de Java org.eclipse.microprofile.config.spi.Converter
.
Quarkus utiliza la especificación Eclipse MicroProfile Configuration para implementar toda la lógica relativa a la configuración. La especificación ofrece la interfaz org.eclipse.microprofile.config.spi.Converter
Java SPI para implementar la conversión de los valores de configuración a un tipo personalizado.
Por ejemplo, podrías transformar un valor porcentual (por ejemplo, 15%) en un tipo Percentage
, envolviendo el porcentaje como tipo double
.
Crea una nueva clase POJO org.acme.quickstart.Percentage.java
:
package
org
.
acme
.
quickstart
;
public
class
Percentage
{
private
double
percentage
;
public
Percentage
(
double
percentage
)
{
this
.
percentage
=
percentage
;
}
public
double
getPercentage
()
{
return
percentage
;
}
}
Y luego crea una clase org.acme.quickstart.PercentageConverter.java
que convierta la representación String
en Percentage
:
package
org
.
acme
.
quickstart
;
import
javax.annotation.Priority
;
import
org.eclipse.microprofile.config.spi.Converter
;
@Priority
(
300
)
public
class
PercentageConverter
implements
Converter
<
Percentage
>
{
@Override
public
Percentage
convert
(
String
value
)
{
String
numeric
=
value
.
substring
(
0
,
value
.
length
(
)
-
1
)
;
return
new
Percentage
(
Double
.
parseDouble
(
numeric
)
/
100
)
;
}
}
Establece la prioridad; en este caso concreto puede ser opcional
Tipo genérico que establece el tipo a convertir
A continuación, tienes que registrarlo como un SPI de Java. Crea la carpeta services en src/main/resources/META-INF. Después, crea un archivo dentro de la carpeta services llamadoorg.eclipse.microprofile.config.spi.Converter con el siguiente contenido:
org.acme.quickstart.PercentageConverter
A continuación, puedes modificar la clase org.acme.quickstart.GreetingResource.java
para inyectar esta propiedad:
@ConfigProperty
(
name
=
"greeting.vat"
)
Percentage
vat
;
@GET
@Path
(
"/vat"
)
@Produces
(
MediaType
.
TEXT_PLAIN
)
public
String
vat
()
{
return
Double
.
toString
(
vat
.
getPercentage
());
}
Por último, tendrás que añadir una nueva propiedad en el archivo application.properties de tu directorio src/main/resources:
greeting.vat
=
21%
Y en una ventana de terminal, haz una petición a /hello/vat
para ver que el mensaje de salida es la cuba transformada como doble:
curl http://localhost:8080/hello/vat
0.21
Debate
Por defecto, si no se encuentra ninguna anotación @Priority
en un convertidor, se registra con una prioridad de 100. Los convertidores de Quarkus se registran con una prioridad de 200, por lo que si quieres sustituir un convertidor de Quarkus, debes utilizar un valor superior; si no necesitas sustituir un convertidor de Quarkus, el valor por defecto está perfectamente bien.
En la Receta 4.1 se muestra una lista de los convertidores del núcleo de Quarkus.
4.11 Agrupar valores de configuración
Solución
Puedes agrupar propiedades comunes (las que tienen el mismo prefijo) utilizando la anotación @io.quarkus.arc.config.ConfigProperties
.
Cuando crees propiedades de configuración ad hoc en tu aplicación, normalmente estas propiedades tendrán el mismo prefijo (es decir, greetings
). Para inyectar todas estas propiedades, puedes utilizar la anotación @ConfigProperty
(como se muestra en la Receta 4.1), opuedes utilizar la anotación io.quarkus.arc.config.ConfigProperties
para agruparpropiedades.
Utilizando el archivo application.properties:
greeting.message
=
Hello World
greeting.suffix
=
!!, How are you???
vamos a implementar una clase que mapee las propiedades de configuración en objetos Java utilizando la anotación io.quarkus.arc.config.ConfigProperties
. Crea una nueva clase org.acme.quickstart.GreetingConfiguration.java
:
package
org
.
acme
.
quickstart
;
import
java.util.List
;
import
java.util.Optional
;
import
javax.validation.constraints.Max
;
import
javax.validation.constraints.Min
;
import
io.quarkus.arc.config.ConfigProperties
;
@ConfigProperties
(
prefix
=
"greeting"
)
public
class
GreetingConfiguration
{
public
String
message
;
public
String
suffix
=
"!"
;
}
Establece esto como un POJO de configuración con un prefijo común
Mapea la propiedad
greeting.message
El valor por defecto de
greeting.suffix
en caso de que no se establezca la propiedad
Una de las cosas importantes que hay que observar en el código anterior es que el atributo prefix
no es obligatorio. Si no se establece, el prefijo que se utilizará vendrá determinado por el nombre de la clase (eliminando la parte del sufijo Configuration
). En este caso, el atributo prefix
podría autorresolverse a greeting
.
Entonces puedes inyectar este POJO de configuración para empezar a consumir los valores de configuración.
Puedes modificar la clase org.acme.quickstart.GreetingResource.java
para inyectar esta clase:
@Inject
GreetingConfiguration
greetingConfiguration
;
@GET
@Path
(
"/configurations"
)
@Produces
(
MediaType
.
TEXT_PLAIN
)
public
String
helloConfigurations
(
)
{
return
greetingConfiguration
.
message
+
greetingConfiguration
.
suffix
;
}
Y en una ventana de terminal haz una petición a /hello/configurations
para ver que los valores de configuración se rellenan dentro de Java, por ejemplo:
curl http://localhost:8080/hello/configurations
Hello World!!, How are you???
Como puedes ver ahora, no necesitas anotar cada campo utilizando @ConfigProperty
-sólo tienes que aprovechar la definición de la clase para obtener el nombre de la propiedad o el valor por defecto.
Debate
Además, Quarkus admite la configuración de objetos anidados, de modo que también puedes asignar subcategorías utilizando clases internas.
Supongamos que añadimos una nueva propiedad llamada greeting.output.recipients
enapplication.properties:
greeting.output.recipients
=
Ada,Alexandra
Podrías utilizar una clase interna para asignarla al objeto de configuración. Modifica la clase org.acme.quickstart.GreetingConfiguration.java
. A continuación, añade una nueva clase interna que represente la subcategoría output
y regístrala como campo:
public
OutputConfiguration
output
;
public
static
class
OutputConfiguration
{
public
List
<
String
>
recipients
;
}
A continuación, puedes acceder al campo greetingConfiguration.output.recipients
para obtener el valor.También puedes anotar los campos con anotaciones de validación de frijoles para validar en el momento del inicio que todos los valores de configuración son válidos. Si no lo son, la aplicación no se iniciará e indicará los errores de validación en el registro.
4.12 Validar los valores de configuración
Solución
Utiliza la especificación Bean Validation para validar que el valor de una propiedad es válido cuando se inyecta utilizando la anotación @ConfigProperty
en una clase.
La especificación de Validación de Frijoles te permite establecer restricciones en los objetos mediante anotaciones. Quarkus integra la especificación de Configuración de Microperfiles de Eclipse con la especificación de Validación de Frijoles, de modo que puedes utilizarlas conjuntamente para validar que un valor de configuración cumple determinados criterios. Esta verificación se ejecuta en el momento del arranque, y si hay alguna infracción, se muestra un mensaje de error en la consola y se aborta el proceso de arranque.
Lo primero que tienes que hacer es registrar la dependencia Quarkus Bean Validation. Puedes hacerlo manualmente editando tu pom.xml o ejecutando el siguiente comando de Maven desde el directorio raíz del proyecto:
./mvnw quarkus:add-extension -Dextensions="quarkus-hibernate-validator"
Después, tendrás que crear un objeto de configuración, sobre el que aprendiste en la receta anterior. En el siguiente ejemplo, se establece una restricción en la propiedad de configuración greeting.repeat
para que no se puedan establecer repeticiones fuera del rango 1-3 inclusive.
Para validar el rango de enteros, se utilizan las siguientes anotaciones de Validación de Frijoles: javax.validation.constraints.Max
y javax.validation.constraints.Min
. Abre org.acme.quickstart.GreetingConfiguration.java
y añade anotaciones de Validación de Frijoles:
@Min
(
1
)
@Max
(
3
)
public
Integer
repeat
;
Abre el archivo src/main/resources/application.properties y establece la propiedad de configuración greeting.repeat
en 7:
greeting.repeat
=
7
Inicia la aplicación y verás un mensaje de error notificando que un valor de configuración infringe una de las restricciones definidas:
./mvnw compile quarkus:dev
Debate
En este ejemplo, has visto una breve introducción a la especificación de Validación de Frijoles, así como algunas anotaciones que puedes utilizar para validar campos. Sin embargo, Hibernate Validation y la implementación de Bean Validation utilizada admiten más restricciones, como @Digits
, @Email
, @NotNull
, y @NotBlank
.
Get Libro de cocina Quarkus now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.