<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Daniel Arrais</title>
    <description>The latest articles on Forem by Daniel Arrais (@danielarrais).</description>
    <link>https://forem.com/danielarrais</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F601725%2F0892e045-d9a3-4c39-a837-ae53a079d037.jpeg</url>
      <title>Forem: Daniel Arrais</title>
      <link>https://forem.com/danielarrais</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/danielarrais"/>
    <language>en</language>
    <item>
      <title>Criando componentes do Rabbitmq de forma dinâmica no Spring Boot</title>
      <dc:creator>Daniel Arrais</dc:creator>
      <pubDate>Mon, 22 May 2023 11:59:57 +0000</pubDate>
      <link>https://forem.com/danielarrais/criando-componentes-do-rabbit-de-forma-dinamica-no-spring-boot-3hnm</link>
      <guid>https://forem.com/danielarrais/criando-componentes-do-rabbit-de-forma-dinamica-no-spring-boot-3hnm</guid>
      <description>&lt;p&gt;Esses dias me deparei com o seguinte desafio: listar no &lt;code&gt;properties&lt;/code&gt; de um projeto Spring Boot as filas que são utilizadas no projeto e criá-las no RabbitMQ de acordo com essa lista. Até então eu criava as filas uma a uma declarando uma &lt;code&gt;@Bean&lt;/code&gt; (&lt;strong&gt;Exemplo 1&lt;/strong&gt;) e assim toda vez que a aplicação é iniciada as devidas filas são criadas, caso  já não existam. O problema aqui é a necessidade de alterar código toda vez que for necessário criar uma nova fila.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exemplo 1&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Bean&lt;/span&gt;  
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Queue&lt;/span&gt; &lt;span class="nf"&gt;example1Queue&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;  
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"example1Queue created"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;  
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;QueueBuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;durable&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"example1Queue"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;  
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@Bean&lt;/span&gt;  
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Queue&lt;/span&gt; &lt;span class="nf"&gt;example2Queue&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;  
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"example2Queue created"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;  
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;QueueBuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;durable&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"example2Queue"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;  
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Criar uma &lt;code&gt;@Bean&lt;/code&gt; que retorna uma &lt;code&gt;Queue&lt;/code&gt; é o jeito básico de criar filas com o Spring, mas se precisamos de algo mais flexível e dinâmico precisamos outro meio... precisamos da classe &lt;strong&gt;&lt;code&gt;Declarables&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Declarables
&lt;/h2&gt;

&lt;p&gt;A ideia geral do desafio era obter flexibilidade e centralizar as informações das filas em uma lista no arquivo properties do projeto, sem ser necessário alterar código Java para configurar uma nova fila. Nesse contexto seria interessante poder criar várias filas de uma vez só e descobri que isso é possível, utilizando a classe &lt;a href="https://docs.spring.io/spring-amqp/api/org/springframework/amqp/core/Declarables.html"&gt;&lt;code&gt;Declarables&lt;/code&gt;&lt;/a&gt; . &lt;code&gt;Declarables&lt;/code&gt; é uma coleção que suporta implementações de &lt;code&gt;Declarable&lt;/code&gt;,  como &lt;code&gt;Bind&lt;/code&gt;, &lt;code&gt;Queue&lt;/code&gt; e &lt;code&gt;Exchange&lt;/code&gt; (e creio que outras). Para utilizá-la seguimos a mesma lógica do exemplo 1, declarando uma &lt;code&gt;@Bean&lt;/code&gt;, só que em vez de retornar um componente especifico, retornamos uma instância de &lt;code&gt;Declarables&lt;/code&gt; com tudo que precisamos criar. No &lt;strong&gt;exemplo 2&lt;/strong&gt; eu recrio o exemplo 1 usando &lt;code&gt;Declarables&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exemplo 2&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Bean&lt;/span&gt;  
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Declarables&lt;/span&gt; &lt;span class="nf"&gt;queues&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;  
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;buildQueues&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;  
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Declarables&lt;/span&gt; &lt;span class="nf"&gt;buildQueues&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;  
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Declarables&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;  
        &lt;span class="nc"&gt;QueueBuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;durable&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"example1Queue"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;  
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt;  
        &lt;span class="nc"&gt;QueueBuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;durable&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"example2Queue"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;  
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;  
    &lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vejam como é interessante, simples e nos abre possibilidades, como pegar uma lista de filas de um lugar qualquer, iterá-las e montar as filas. É isso que vamos fazer! Mas cuidado! Alerto que devemos utilizar responsabilidade. Por exemplo no projeto aqui da firma eu criei muitas coisas com ela, Queues, Binds e Exchanges, mas separadamente, para não virar bagunça. Flexibilidade deve ser adicionada com cuidado para não virar zorra e deixar o projeto impossível de manter.&lt;/p&gt;

&lt;p&gt;Agora que sabemos utilizar a classe &lt;code&gt;Declarables&lt;/code&gt; vamos guardar nossa lista de filas no properties do projeto.&lt;/p&gt;

&lt;h2&gt;
  
  
  Criando a lista de filas no arquivo properties
&lt;/h2&gt;

&lt;p&gt;Agora vamos guardar as filas no arquivo properties (usando yaml) do projeto para podermos recuperar elas na nossa Bean e criá-las. Para isso eu pensei na estrutura do &lt;strong&gt;exemplo 3&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exemplo 3&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nl"&gt;queues:&lt;/span&gt;  
    &lt;span class="nl"&gt;example1Queue:&lt;/span&gt;  
        &lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="n"&gt;example1Queue&lt;/span&gt;  
        &lt;span class="nl"&gt;tll:&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;
    &lt;span class="nl"&gt;example2Queue:&lt;/span&gt;  
        &lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="n"&gt;example2Queue&lt;/span&gt;
        &lt;span class="nl"&gt;tll:&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Usei a estrutura de keys e valores mas também poderíamos usar uma lista de strings (&lt;strong&gt;exemplo 4&lt;/strong&gt;) com os nomes das filas ou uma lista de objetos sem chave (&lt;strong&gt;exemplo 5&lt;/strong&gt;). Adotei a estrutura do &lt;strong&gt;exemplo 3&lt;/strong&gt; para nos permitir referenciar as filas em outros locais, como nas anotações &lt;code&gt;@RabbitListener&lt;/code&gt; (exemplo: &lt;code&gt;@RabbitListener(queues = "${queues.example1Queue.name}")&lt;/code&gt;).  A estrutura que sugeri (e a do &lt;strong&gt;exemplo 5&lt;/strong&gt;) também permite adicionar outras propriedades pertinente as filas, como o &lt;strong&gt;ttl&lt;/strong&gt; .&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exemplo 4&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nl"&gt;queues:&lt;/span&gt;  &lt;span class="n"&gt;example1Queue&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;example2Queue&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Exemplo 5&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nl"&gt;queues:&lt;/span&gt; 
    &lt;span class="o"&gt;-&lt;/span&gt; 
        &lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="n"&gt;example1Queue&lt;/span&gt;  
        &lt;span class="nl"&gt;tll:&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt;
        &lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="n"&gt;example2Queue&lt;/span&gt;
        &lt;span class="nl"&gt;tll:&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora que temos nossas filas registradas no properties devemos mapear elas para uma classe para podermos recuperar as informações onde precisamos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recuperando as configurações da filas
&lt;/h2&gt;

&lt;p&gt;Para recuperar os valores da lista de filas vamos criar a classe &lt;code&gt;QueuesProperties&lt;/code&gt; (&lt;strong&gt;exemplo 6&lt;/strong&gt;). Nela temos uma classe que representa a &lt;code&gt;Queue&lt;/code&gt; e temos um &lt;code&gt;Map&lt;/code&gt; de &lt;code&gt;Queue&lt;/code&gt;. A classe &lt;code&gt;Queue&lt;/code&gt; tem os atributos &lt;code&gt;name&lt;/code&gt; e &lt;code&gt;tll&lt;/code&gt;. Na propriedade &lt;strong&gt;queues&lt;/strong&gt; eu tentei utilizar &lt;strong&gt;lista&lt;/strong&gt; mas não deu certo, então criei um &lt;code&gt;getQueues()&lt;/code&gt; que retorna uma lista.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exemplo 6&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Data&lt;/span&gt; 
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;QueuesProperties&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;  
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Queue&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;queues&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;  

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Collection&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Queue&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getQueues&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;  
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;CollectionUtils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isEmpty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;queues&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;  
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;queues&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;values&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;  
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Data&lt;/span&gt;   
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Queue&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;   
        &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;  
        &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;tll&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;  
    &lt;span class="o"&gt;}&lt;/span&gt; 
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Depois de montarmos nosso Pojo para armazenas as filas, devemos dizer ao Spring que essa classe representa propriedades, para podemos utilizar a injeção de dependências. Para isso utilizamos as anotações  &lt;code&gt;@Component&lt;/code&gt;  e &lt;code&gt;@ConfigurationProperties("propertie")&lt;/code&gt;  (&lt;strong&gt;exemplo 7&lt;/strong&gt;). Na &lt;code&gt;@ConfigurationProperties&lt;/code&gt; teríamos que informar o prefixo da nossa propriedade, mas como ela está no topo da hierarquia, não precisamos.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exemplo 7&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Data&lt;/span&gt; 
&lt;span class="nd"&gt;@Component&lt;/span&gt;    
&lt;span class="nd"&gt;@ConfigurationProperties&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;QueuesProperties&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;  
    &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Também podemos validar nossas anotações utilizando o Spring Validation e impedir que a aplicação seja executada caso esteja faltando alguma informação. Sabemos por exemplo que o atributo &lt;code&gt;name&lt;/code&gt; da &lt;code&gt;Queue&lt;/code&gt; deve ser obrigatório, então podemos anotar ele com &lt;code&gt;@NotBlank&lt;/code&gt; e anotamos as classes com &lt;code&gt;@Validated&lt;/code&gt;, para que o Spring entenda que deve validar elas (&lt;strong&gt;exemplo 8&lt;/strong&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exemplo 8&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="nd"&gt;@Data&lt;/span&gt;  
&lt;span class="nd"&gt;@Validated&lt;/span&gt;  
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Queue&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;  
    &lt;span class="nd"&gt;@NotBlank&lt;/span&gt;  
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;  
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;tll&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;  
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Feito tudo isso, nossa classe completa ficou assim:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exemplo 9&lt;/strong&gt; (&lt;a href="https://github.com/danielarrais/multiple-queues-rabbit/blob/main/src/main/java/dev/danielarrais/multiplequeuesrabbit/broker/setup/QueuesProperties.java"&gt;QueuesProperties.java&lt;/a&gt;)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Data&lt;/span&gt;  
&lt;span class="nd"&gt;@Validated&lt;/span&gt;  
&lt;span class="nd"&gt;@Component&lt;/span&gt;    
&lt;span class="nd"&gt;@ConfigurationProperties&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;QueuesProperties&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;  

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Queue&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;queues&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;  

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Collection&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Queue&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getQueues&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;  
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;CollectionUtils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isEmpty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;queues&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;  
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;queues&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;values&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;  
    &lt;span class="o"&gt;}&lt;/span&gt;  

    &lt;span class="nd"&gt;@Data&lt;/span&gt;  
    &lt;span class="nd"&gt;@Validated&lt;/span&gt;  
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Queue&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;  
        &lt;span class="nd"&gt;@NotBlank&lt;/span&gt;  
        &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;  
        &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;tll&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;  
    &lt;span class="o"&gt;}&lt;/span&gt;  
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora podemos injetar nossa classe de propriedades usando injeção de dependência do Spring em qualquer classe que tenha suporte.&lt;/p&gt;

&lt;h2&gt;
  
  
  Criando nossas filas
&lt;/h2&gt;

&lt;p&gt;Para criar nossas filas vamos criar uma classe anotada com &lt;code&gt;@Component&lt;/code&gt; chamada &lt;code&gt;QueuesInitializer&lt;/code&gt;, onde declararemos nossa &lt;code&gt;@Bean&lt;/code&gt; de criação de filas. Nela injetaremos nossas propriedades utilizando uma variável final (é necessário criar um construtor para que o Spring possa instanciá-la, para isso eu uso a anotação &lt;code&gt;@RequiredArgsConstructor&lt;/code&gt; do &lt;code&gt;Lombok&lt;/code&gt;).  &lt;/p&gt;

&lt;p&gt;Depois declaramos a nossa &lt;code&gt;@Bean&lt;/code&gt; que retorna uma &lt;code&gt;Declarables&lt;/code&gt; com nossas filas construídas. Como mostra o exemplo 10:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exemplo 10&lt;/strong&gt; (&lt;a href="https://github.com/danielarrais/multiple-queues-rabbit/blob/main/src/main/java/dev/danielarrais/multiplequeuesrabbit/broker/setup/QueuesInitializer.java"&gt;QueuesInitializer.java&lt;/a&gt;)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Component&lt;/span&gt;  
&lt;span class="nd"&gt;@RequiredArgsConstructor&lt;/span&gt;  
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;QueuesInitializer&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;  

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;QueuesProperties&lt;/span&gt; &lt;span class="n"&gt;queuesProperties&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;  

    &lt;span class="nd"&gt;@Bean&lt;/span&gt;  
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Declarables&lt;/span&gt; &lt;span class="nf"&gt;queues&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;  
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;buildQueues&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;  
    &lt;span class="o"&gt;}&lt;/span&gt;  

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Declarables&lt;/span&gt; &lt;span class="nf"&gt;buildQueues&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;  
        &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Queue&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;queues&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;queuesProperties&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getQueues&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;queue&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;  
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;QueueBuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;durable&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;  
                               &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ttl&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getTll&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;  
                               &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;  
        &lt;span class="o"&gt;}).&lt;/span&gt;&lt;span class="na"&gt;collect&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Collectors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toList&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;  

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Declarables&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;queues&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;  
    &lt;span class="o"&gt;}&lt;/span&gt;  

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pronto, é isso, simples e fácil.&lt;/p&gt;

&lt;h1&gt;
  
  
  Repositório
&lt;/h1&gt;

&lt;p&gt;Você pode encontrar o código apresentado neste &lt;a href="https://github.com/danielarrais/multiple-queues-rabbit"&gt;repositório&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>java</category>
      <category>springboot</category>
      <category>rabbitmq</category>
      <category>properties</category>
    </item>
    <item>
      <title>Zipar arquivos e pastas utilizando Java</title>
      <dc:creator>Daniel Arrais</dc:creator>
      <pubDate>Sun, 25 Apr 2021 01:38:55 +0000</pubDate>
      <link>https://forem.com/danielarrais/zipar-arquivos-pastas-usando-java-1emi</link>
      <guid>https://forem.com/danielarrais/zipar-arquivos-pastas-usando-java-1emi</guid>
      <description>&lt;p&gt;Zipar arquivos usando o Java é uma tarefas simples e não precisamos de bibliotecas de terceiros para isso. Para vermos&lt;br&gt;
esta simplicidade na prática começarei o artigo implementando a zipagem de um arquivo, que também será utilizado na&lt;br&gt;
zipagem de múltiplos arquivos e de pastas.&lt;/p&gt;
&lt;h2&gt;
  
  
  Zipar um arquivo
&lt;/h2&gt;

&lt;p&gt;O código necessário para zipar um arquivo é este:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;No código você pode notar que utilizei as classes &lt;code&gt;java.io.FileOutputStream&lt;/code&gt; , &lt;code&gt;java.io.FileInputStream&lt;/code&gt;,&lt;br&gt;
&lt;code&gt;java.util.zip.ZipOutputStream&lt;/code&gt; e a &lt;code&gt;java.util.zip.ZipEntry&lt;/code&gt;. Elas possuem alguns papéis, a &lt;code&gt;FileOutputStream&lt;/code&gt; é&lt;br&gt;
necessária para gravar bytes no disco e a &lt;code&gt;FileInputStream&lt;/code&gt; para ler; a &lt;code&gt;ZipOutputStream&lt;/code&gt; é uma &lt;code&gt;FileOutputStream&lt;/code&gt;&lt;br&gt;
especializada em criar e gravar arquivos zip's e dispõe de métodos que auxiliam tal tarefa; a &lt;code&gt;ZipEntry&lt;/code&gt; é utilizada&lt;br&gt;
para adicionar arquivos dentro do ZIP, nela podemos adicionar informações sobre o arquivo, como o nome dele.&lt;/p&gt;

&lt;p&gt;Como você deve ter notado (espero rsrsrsrs), o código é simples e consegue zipar um único arquivo. Nele não há segredos:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Primeiro criamos uma instância de File passando a URL do arquivo a ser compactado;&lt;/li&gt;
&lt;li&gt;Instanciamos nossos Streams, a &lt;code&gt;FileOutputStream&lt;/code&gt; e a &lt;code&gt;ZipOutputStream&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Criamos o &lt;code&gt;FileInputStream&lt;/code&gt; que lerá nosso arquivo, que é passado no construtor;&lt;/li&gt;
&lt;li&gt;Criamos uma instância &lt;code&gt;ZipEntry&lt;/code&gt; passando o nome do arquivo no construtor e depois passamos ela para a
&lt;code&gt;ZipOutputStream&lt;/code&gt; por meio do método &lt;code&gt;putNextEntry&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Lemos os bytes do arquivo e gravamos eles, compactados, usando a nossa variável &lt;code&gt;zipOutputStream&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Por fim, fechamos os streams instanciados.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Pronto! Agora temos um código Java capaz de zipar um arquivo e você entende como ele funciona! Não pararemos por aqui e&lt;br&gt;
nos próximos tópicos você verá soluções para compactar múltiplos arquivos e pastas! Porém, sugiro que antes de continuar&lt;br&gt;
a leitura, tente melhorar o código proposto e implementarmos suas próprias soluções. Deixo apenas uma dica: na&lt;br&gt;
compactação de pastas a &lt;strong&gt;recursividade&lt;/strong&gt; pode ser uma aliada.&lt;/p&gt;
&lt;h2&gt;
  
  
  Zipar múltiplos arquivos
&lt;/h2&gt;

&lt;p&gt;Antes de implementarmos a solução vamos encapsular o código anterior em um método com a seguinte&lt;br&gt;
assinatura: &lt;code&gt;void zipFile(File file, String zipName)&lt;/code&gt;. A principal mudança fica a cargo do recebimento do arquivo e do&lt;br&gt;
nome do zip como argumentos. Vamos encapsular também a parte do código que adiciona arquivos dentro do zip, ele terá a&lt;br&gt;
seguinte assinatura: &lt;code&gt;void addFileInZip(ZipOutputStream zipOutputStream, File file)&lt;/code&gt;. Após essa refatoração nosso&lt;br&gt;
primeiro código ficará como a seguir.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Agora que temos um método que adiciona um arquivo dentro do zip podemos criar o novo método que zipa vários. Nele temos&lt;br&gt;
que receber uma lista de arquivos e o nome do zip, essa lista deverá ser iterada e ter cada item adicionado ao zip,&lt;br&gt;
ficando assim:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  Zipar pastas
&lt;/h2&gt;

&lt;p&gt;A zipagem de uma pasta é um pouco mais complexa - bem pouco mesmo - pois precisamos vasculhá-la em busca dos arquivos&lt;br&gt;
para adicioná-los ao ZIP. Essa busca pode ser facilitada com uso de recursividade. Para isso vamos duplicar nosso&lt;br&gt;
método &lt;code&gt;addFileInZip&lt;/code&gt; adicionando mais um parâmetro chamado &lt;code&gt;parentPath&lt;/code&gt; em sua assinatura. A ideia aqui é chamarmos ele&lt;br&gt;
passando o arquivo/pasta e o nome do caminho deles, repetindo isso forma recursiva para cada arquivo ou pasta&lt;br&gt;
encontrada. O método deve trabalhar receber tanto pastas quanto arquivos. Para melhor entendimento a seguir temos a&lt;br&gt;
implementação do que foi comentado.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Para verificar o File passado é um arquivo ou uma pasta utilizei o método &lt;code&gt;isDirectory()&lt;/code&gt;. Se for uma pasta eu itero os&lt;br&gt;
arquivos dela - obtido por meio do método &lt;code&gt;listFiles()&lt;/code&gt;, chamando o método de forma recursiva e passando para ele o path&lt;br&gt;
do arquivo/pasta concatendado com &lt;code&gt;parentPath&lt;/code&gt;. A concatenação é necessária para que ao chegar em um arquivo, o path&lt;br&gt;
recebido seja completo. Caso seja um arquivo, ele adiciona o arquivo ao ZIP normalmente, concatenando a&lt;br&gt;
váriavel &lt;code&gt;parentPath&lt;/code&gt; ao seu nome para que seu path dentro do zip fique correto.&lt;/p&gt;

&lt;p&gt;E como você deve ter notado, agora o código do primeiro método &lt;code&gt;addFileInZip&lt;/code&gt; está duplicado. Para resolver isso você&lt;br&gt;
pode substituir todo o código do &lt;code&gt;addFileInZip&lt;/code&gt; original por uma chamada do novo, passando no terceiro paramêtro uma&lt;br&gt;
String vazia. Assim deixamos nosso código mais clean e manutenível.&lt;/p&gt;

&lt;p&gt;Com essa refatoração no &lt;code&gt;addFileInZip&lt;/code&gt; podemos perceber que não precisamos criar um método exclusivo para compactação&lt;br&gt;
de pasta, pois o &lt;code&gt;zipFile&lt;/code&gt; já vai ser capaz de tal tarefa. Porém, por questão de semântica, você pode renomêá-lo&lt;br&gt;
para &lt;code&gt;zipFileOrFolder&lt;/code&gt; ou criar um método chamado &lt;code&gt;zipFolder&lt;/code&gt; que chama o &lt;code&gt;zipFile&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;O resultado final pode ser visualizado abaixo:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


</description>
      <category>java</category>
      <category>zip</category>
    </item>
  </channel>
</rss>
