Configurando sua aplicação Java com Quarkus @ConfigProperty
Tags: quarkus, java, ptbr, braziliandevs
Published: 2020-08-21 11:34:55

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](https://quarkus.io/guides/config) 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.

```java
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.

```java
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:

```properties
config=Configuração simples
C*O~M_caracteres-especiais!á=Usando caracteres especiais
inteiro=2
```

Agora vamos ver o que cada linha faz

1. 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**. 

2. 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**.

3. Uma das coisas mais legais de injetar a configuração é que ela já é transformada para o tipo de dado que nós queremos.

4. Os nomes de configuração podem conter ponto (.), hífen (-), *underscore* (_) entre outros caracteres especiais.

5. É 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.

![Conselho do he-man](https://dev-to-uploads.s3.amazonaws.com/i/vi5bywq6l4awlarqj9ju.jpg)


Agora é só executar esse programa usando o comando:

```bash
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:

![Configurações](https://dev-to-uploads.s3.amazonaws.com/i/1imafc3m22me71hg782t.png)

#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](https://github.com/eclipse/microprofile-config/blob/master/spec/src/main/asciidoc/configsources.asciidoc#custom-configsources).

Para os nomes de variável de ambiente, o quarkus segue as mesmas regras do [microprofile](https://github.com/eclipse/microprofile-config/blob/master/spec/src/main/asciidoc/configsources.asciidoc#default-configsources).

#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:

1. Propriedades do sistema
2. Variáveis de ambiente
3. O arquivo .env
4. O arquivo application.properties
5. 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 

```shell
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.

![Não me diga](https://dev-to-uploads.s3.amazonaws.com/i/wk7uaa1mas6n6lokjjxl.jpg)

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: 

```properties
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.

![Config alterada](https://dev-to-uploads.s3.amazonaws.com/i/n0j449ic1xybtlcdul1u.png)

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](https://quarkus.io/guides/config).

Ah, e o código de hoje pode ser encontrado no [github](https://github.com/lucasscharf/blog-posts-code/tree/master/config).