Não tem jeito. Inevitavelmente um software precisa de algum tipo de configuração. Seja as credenciais de acesso ao banco de dados, o endereço de algum serviço externo, regras de log, etc...
No post de hoje, vamos ver como podemos configurar nossa aplicação usando o Quarkus e mais algumas coisas bem legais sobre isso.
O que faremos
Vamos criar um microsserviço que responde as requisições GET em um endpoint chamado /config com todas as configurações armazenadas. Também vamos ver o que são fontes de configuração, entender as prioridades de configuração e como o Quarkus lida com as configurações em ambiente de produção e teste.
Hora da ação
Primeiramente, vamos criar um projeto Quarkus. Para isso, basta usar o seguinte comando.
mvn io.quarkus:quarkus-maven-plugin:1.6.0.Final:create \
-DprojectGroupId=config \
-DprojectArtifactId=config \
-Dextensions="resteasy-jackson" \
-DclassName="config.ConfigResource" \
-Dpath="/config"
Esse comando já criará uma aplicação Quarkus com um arquivo chamado ConfigResource. Agora, basta adicionarmos o seguinte código nesse arquivo.
package config;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import java.util.Map;
import java.util.HashMap;
@Path("/config")
public class ConfigResource {
@ConfigProperty(name="config") // 1
String config;
@ConfigProperty(name="valorDefinido", defaultValue="Uma configuração") // 2
String valorDefinido;
@ConfigProperty(name="inteiro") // 3
Integer intConfig;
@ConfigProperty(name="C*O~M_caracteres-especiais!á") // 4
String caracteresEspeciais;
@GET
@Produces(MediaType.APPLICATION_JSON)
public Map<String, Object> getConfigs() { // 5
Map<String, Object> configs = new HashMap<>();
configs.put("Configuração: ", config);
configs.put("Valor definido: ", valorDefinido);
configs.put("Configuração inteira: ", intConfig);
configs.put("Caracteres especiais: ", caracteresEspeciais);
return configs;
}
}
Dentro do diretório resources/META-INF existe um arquivo chamado application.properties. Também é necessário alterar o arquivo para ficar assim:
config=Configuração simples
C*O~M_caracteres-especiais!á=Usando caracteres especiais
inteiro=2
Agora vamos ver o que cada linha faz
A anotação @ConfigProperty faz o Quarkus saber que aquela variável vai receber alguma configuração. O nome da configuração é dado pelo valor do atributo name.
Caso o servidor não tenha o valor de uma configuração, o serviço não terá um erro na hora de subir. Porém, algumas configurações podem ter valores padrão, esse valor padrão é definido pelo atributo defaultValue.
Uma das coisas mais legais de injetar a configuração é que ela já é transformada para o tipo de dado que nós queremos.
Os nomes de configuração podem conter ponto (.), hífen (-), underscore (_) entre outros caracteres especiais.
É o método que retorna todas as configurações utilizadas.
Já está quase tudo pronto para conseguirmos rodar a aplicação. Primeiro, vamos deletar os testes gerados.
Agora é só executar esse programa usando o comando:
mvn quarkus:dev
E acessar a url http://localhost:8080/config para vermos as configurações.
Se tudo deu certo, aparecerá uma imagem semelhante a essa abaixo:
Fontes de configuração
Nós vimos que dentro da anotação @ConfigProperty, nós colocamos a chave e que o valor dessa configuração vem de algum lugar (no caso do nosso exemplo, ele veio do arquivo aplication.properties). Mas de onde que é esse lugar que o valor da configuração vem?
Esse lugar pode ser as propriedades de sistema, as variáveis de ambiente, um arquivo especial chamado .env, o arquivo de application.properties ou qualquer outra fonte que o desenvolvedor fizer manualmente.
Para os nomes de variável de ambiente, o quarkus segue as mesmas regras do microprofile.
Precedência nas fontes de configuração
Se a mesma chave de configuração está presente em diferentes fontes de configuração, o sistema precisa escolher entre uma delas.
Ele faz isso seguindo a seguinte ordem:
- Propriedades do sistema
- Variáveis de ambiente
- O arquivo .env
- O arquivo application.properties
- O valor default colocado na anotação @ConfigProperty
Se o arquivo não estiver em nenhuma fonte de configuração, a aplicação não subirá e dará um erro
javax.enterprise.inject.spi.DeploymentException: No config value of type [<tipo de dado>] exists for: <nome da chave de configuração>
at io.quarkus.arc.runtime.ConfigRecorder.validateConfigProperties(ConfigRecorder.java:37)
Perfil de configuração
Com o Quarkus fica muito fácil trocar as configurações em diferentes situações. Isso é feito através de uma ferramenta bem legal chamada Perfil de configuração.
Dependendo do perfil que estiver sendo utilizado, as configurações utilizadas são diferentes. Isso permite colocar no mesmo arquivo de propriedade as diferentes configurações.
Por padrão, o Quarkus trabalha com 3 perfis diferentes: o de produção (prod), o de desenvolvimento (dev) e o de testes (test). O perfil de desenvolvimento é ativado quando usamos o comando mvn quarkus:dev e o de testes é ativado quando executamos os testes.
Para exemplificar isso, ainda com o servidor de pé vamos adicionar uma nova linha na no nosso application.properties. Com uma propriedade para ser executada com o perfil de desenvolvimento. Nosso arquivo deverá ficar assim:
config=Configuração simples
C*O~M_caracteres-especiais!á=Usando caracteres especiais
inteiro=2
#Nova propriedade colocada abaixo
%dev.inteiro=10
Após salvar essa alteração e ao acessar a nossa URL, teremos o seguinte resultado.
Como nós usamos o profixo "%dev", então esse novo valor é válido apenas durante o momento de debug. Se a aplicação não estivesse no modo debug então o valor da configuração usado seria outro (no caso o 2).
Considerações
Sou apaixonado por essa parte de configuração no Quarkus. O que eu mais gosto é que é tão ridiculamente fácil alterar uma propriedade no ambiente de produção (através das variáveis de ambiente).
Esse post acabou ficando um bem maior do que eu gostaria. Mesmo assim, tive que deixar de fora vários conteúdos bem interessantes. Para aqueles que tem alguma fluência em inglês, recomendo uma boa lida na documentação oficial.
Ah, e o código de hoje pode ser encontrado no github.
Top comments (0)