<?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: Thiago Matos</title>
    <description>The latest articles on Forem by Thiago Matos (@thiagoematos).</description>
    <link>https://forem.com/thiagoematos</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%2F1708024%2F1c0b14f9-28e5-4a21-969e-6279e0c7623a.jpg</url>
      <title>Forem: Thiago Matos</title>
      <link>https://forem.com/thiagoematos</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/thiagoematos"/>
    <language>en</language>
    <item>
      <title>🎯 Guia de Conhecimentos em Golang por Nível</title>
      <dc:creator>Thiago Matos</dc:creator>
      <pubDate>Fri, 23 Jan 2026 17:48:06 +0000</pubDate>
      <link>https://forem.com/thiagoematos/guia-de-conhecimentos-em-golang-por-nivel-5631</link>
      <guid>https://forem.com/thiagoematos/guia-de-conhecimentos-em-golang-por-nivel-5631</guid>
      <description>&lt;p&gt;Este documento serve como referência para entrevistas técnicas de desenvolvedores Go, organizando os conhecimentos esperados por nível de senioridade.&lt;/p&gt;




&lt;h2&gt;
  
  
  👶 Desenvolvedor Júnior
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Fundamentos da Linguagem
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sintaxe básica&lt;/strong&gt;: Variáveis, constantes, tipos de dados primitivos&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Estruturas de controle&lt;/strong&gt;: if/else, switch, for loops&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Funções&lt;/strong&gt;: Declaração, parâmetros, retorno múltiplo&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Arrays e Slices&lt;/strong&gt;: Diferenças e uso básico&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maps&lt;/strong&gt;: Criação, inserção, leitura e deleção&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structs&lt;/strong&gt;: Definição e uso básico&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ponteiros&lt;/strong&gt;: Conceito básico e quando usar &lt;code&gt;&amp;amp;&lt;/code&gt; e &lt;code&gt;*&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Packages&lt;/strong&gt;: Importação e uso de pacotes da stdlib&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error handling&lt;/strong&gt;: Tratamento básico de erros com &lt;code&gt;if err != nil&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Conceitos Básicos
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Exported vs Unexported&lt;/strong&gt;: Entender maiúsculas/minúsculas em identificadores&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero values&lt;/strong&gt;: Valores padrão dos tipos&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Type conversion&lt;/strong&gt;: Conversão entre tipos&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;String manipulation&lt;/strong&gt;: Operações básicas com strings&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;fmt package&lt;/strong&gt;: Printf, Sprintf, Println&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Ferramentas Essenciais
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;go run&lt;/strong&gt;: Executar programas Go&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;go build&lt;/strong&gt;: Compilar programas&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;go fmt&lt;/strong&gt;: Formatar código automaticamente&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;go mod init&lt;/strong&gt;: Inicializar módulo Go&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;go get&lt;/strong&gt;: Baixar dependências&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Bibliotecas Standard Library (Básicas)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;fmt&lt;/code&gt; - Formatação de I/O&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;strings&lt;/code&gt; - Manipulação de strings&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;strconv&lt;/code&gt; - Conversões string/números&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;os&lt;/code&gt; - Interação com sistema operacional&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;io&lt;/code&gt; - Interfaces básicas de I/O&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Perguntas Sugeridas para Júnior
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Explique a diferença entre array e slice&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Resposta esperada:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Array tem tamanho fixo definido em tempo de compilação &lt;code&gt;[5]int&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Slice é dinâmico, referência para um array subjacente &lt;code&gt;[]int&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Slice pode crescer com &lt;code&gt;append()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Arrays são valores, slices são referências&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. O que são zero values? Dê exemplos&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Resposta esperada:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Valor padrão quando variável é declarada sem inicialização&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;int/float&lt;/code&gt;: 0&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;string&lt;/code&gt;: "" (vazia)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;bool&lt;/code&gt;: false&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pointer/slice/map/channel&lt;/code&gt;: nil&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Como você declara uma variável em Go? Quais as diferentes formas?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Resposta esperada:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;          &lt;span class="c"&gt;// declaração completa&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;              &lt;span class="c"&gt;// tipo inferido&lt;/span&gt;
&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;                 &lt;span class="c"&gt;// declaração curta (apenas em funções)&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;               &lt;span class="c"&gt;// declarada com zero value&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. O que acontece se você não tratar um erro retornado por uma função?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Resposta esperada:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;O compilador não força tratamento de erro&lt;/li&gt;
&lt;li&gt;Variável &lt;code&gt;err&lt;/code&gt; fica ignorada (usar &lt;code&gt;_&lt;/code&gt; para explícito)&lt;/li&gt;
&lt;li&gt;Pode causar bugs silenciosos em runtime&lt;/li&gt;
&lt;li&gt;Boa prática: sempre verificar &lt;code&gt;if err != nil&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;5. Qual a diferença entre &lt;code&gt;make&lt;/code&gt; e &lt;code&gt;new&lt;/code&gt;?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Resposta esperada:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;new(T)&lt;/code&gt;: aloca memória zerada, retorna &lt;code&gt;*T&lt;/code&gt; (ponteiro)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;make(T)&lt;/code&gt;: inicializa slice/map/channel, retorna &lt;code&gt;T&lt;/code&gt; (não ponteiro)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;new&lt;/code&gt; para qualquer tipo, &lt;code&gt;make&lt;/code&gt; apenas para slice, map, channel&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;make&lt;/code&gt; pode especificar capacidade: &lt;code&gt;make([]int, 0, 10)&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;6. Como funciona o retorno múltiplo de funções?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Resposta esperada:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"divisão por zero"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Go permite retornar múltiplos valores&lt;/li&gt;
&lt;li&gt;Comum retornar &lt;code&gt;(resultado, error)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Pode usar retornos nomeados&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧑‍💻 Desenvolvedor Pleno
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Conhecimentos Avançados da Linguagem
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Interfaces&lt;/strong&gt;: Definição, implementação implícita, type assertion&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Goroutines&lt;/strong&gt;: Criação e conceitos de concorrência&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Channels&lt;/strong&gt;: Comunicação entre goroutines, buffered vs unbuffered&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Select statement&lt;/strong&gt;: Multiplexing de channels&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Defer&lt;/strong&gt;: Uso e ordem de execução&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Panic e Recover&lt;/strong&gt;: Quando e como usar&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Methods&lt;/strong&gt;: Receivers (value vs pointer)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Embedding&lt;/strong&gt;: Composição de structs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Type assertions e Type switches&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generics&lt;/strong&gt; (Go 1.18+): Sintaxe básica e uso&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Padrões e Boas Práticas
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Error handling&lt;/strong&gt;: Padrões idiomáticos, custom errors&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Context package&lt;/strong&gt;: Cancelamento e timeouts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dependency injection&lt;/strong&gt;: Injeção de dependências&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clean Architecture&lt;/strong&gt;: Separação de camadas&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SOLID principles&lt;/strong&gt; aplicados em Go&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Table-driven tests&lt;/strong&gt;: Padrão de testes em Go&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Naming conventions&lt;/strong&gt;: Convenções de nomenclatura&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Ferramentas e Ecosystem
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;go test&lt;/strong&gt;: Testes unitários e de integração&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;go mod&lt;/strong&gt;: Gerenciamento completo de dependências&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;go vet&lt;/strong&gt;: Análise estática de código&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;golangci-lint&lt;/strong&gt;: Linting avançado&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;go generate&lt;/strong&gt;: Geração de código&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Delve&lt;/strong&gt;: Debugger para Go&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;pprof&lt;/strong&gt;: Profiling de performance&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Bibliotecas Standard Library (Intermediárias)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;net/http&lt;/code&gt; - Servidor HTTP e cliente&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;encoding/json&lt;/code&gt; - Serialização JSON&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;database/sql&lt;/code&gt; - Interface de banco de dados&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;context&lt;/code&gt; - Controle de contexto e cancelamento&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sync&lt;/code&gt; - Primitivas de sincronização (Mutex, WaitGroup, Once)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;time&lt;/code&gt; - Manipulação de tempo&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;log&lt;/code&gt; - Logging básico&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;testing&lt;/code&gt; - Framework de testes&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Frameworks e Bibliotecas Populares
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Web Frameworks&lt;/strong&gt;: Gin, Echo, Fiber, Chi&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ORMs&lt;/strong&gt;: GORM, sqlx, ent&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validation&lt;/strong&gt;: go-playground/validator&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configuration&lt;/strong&gt;: Viper, envconfig&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testing&lt;/strong&gt;: testify, gomock&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Banco de Dados
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Uso de &lt;code&gt;database/sql&lt;/code&gt; com drivers (postgres, mysql)&lt;/li&gt;
&lt;li&gt;Preparação de statements&lt;/li&gt;
&lt;li&gt;Transações&lt;/li&gt;
&lt;li&gt;Connection pooling&lt;/li&gt;
&lt;li&gt;Migrations (golang-migrate, goose)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Perguntas Sugeridas para Pleno
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Explique como funcionam as goroutines e o scheduler do Go&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Resposta esperada:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Goroutines são threads leves gerenciadas pela runtime do Go&lt;/li&gt;
&lt;li&gt;Scheduler usa modelo M:N (M goroutines em N threads OS)&lt;/li&gt;
&lt;li&gt;Componentes: G (goroutine), M (thread OS), P (processador lógico)&lt;/li&gt;
&lt;li&gt;Work stealing: P rouba goroutines de outras filas quando ociosas&lt;/li&gt;
&lt;li&gt;Preemptivo desde Go 1.14&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Qual a diferença entre buffered e unbuffered channels?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Resposta esperada:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unbuffered &lt;code&gt;make(chan int)&lt;/code&gt;: send bloqueia até receive&lt;/li&gt;
&lt;li&gt;Buffered &lt;code&gt;make(chan int, 10)&lt;/code&gt;: send só bloqueia se buffer cheio&lt;/li&gt;
&lt;li&gt;Unbuffered garante sincronização&lt;/li&gt;
&lt;li&gt;Buffered permite assincronia limitada&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Quando você usaria um pointer receiver vs value receiver?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Resposta esperada:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pointer receiver: modificar estado, grandes structs, consistência&lt;/li&gt;
&lt;li&gt;Value receiver: imutabilidade, pequenas structs, tipos primitivos&lt;/li&gt;
&lt;li&gt;Regra: se algum método usa pointer, todos devem usar
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;SetName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;// pointer&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;GetName&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;// value ok&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Como você implementaria um rate limiter usando channels?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Resposta esperada:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;limiter&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Tick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Millisecond&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;limiter&lt;/span&gt;  &lt;span class="c"&gt;// bloqueia até próximo tick&lt;/span&gt;
    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ou usar &lt;code&gt;golang.org/x/time/rate&lt;/code&gt; com token bucket&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Explique o padrão de erro idiomático em Go e como criar custom errors&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Resposta esperada:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Padrão idiomático&lt;/span&gt;
&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"failed to do something: %w"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Custom error&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;ValidationError&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Field&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Message&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ValidationError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s: %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Usar &lt;code&gt;%w&lt;/code&gt; para wrapping (Go 1.13+)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;errors.Is()&lt;/code&gt; e &lt;code&gt;errors.As()&lt;/code&gt; para verificação&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;6. Como funciona o Context e quando você deve usá-lo?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Resposta esperada:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Propaga cancelamento, timeouts e valores entre goroutines&lt;/li&gt;
&lt;li&gt;Primeiro parâmetro de funções por convenção
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Usar para: requests HTTP, queries DB, operações longas&lt;/li&gt;
&lt;li&gt;Não usar para: passar dependências opcionais&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;7. Qual a diferença entre &lt;code&gt;sync.Mutex&lt;/code&gt; e &lt;code&gt;sync.RWMutex&lt;/code&gt;?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Resposta esperada:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Mutex&lt;/code&gt;: lock exclusivo (escrita ou leitura)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;RWMutex&lt;/code&gt;: múltiplos readers ou um writer&lt;/li&gt;
&lt;li&gt;RWMutex otimiza cenários read-heavy
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RLock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;   &lt;span class="c"&gt;// múltiplas goroutines podem ler&lt;/span&gt;
&lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RUnlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;    &lt;span class="c"&gt;// exclusivo para escrita&lt;/span&gt;
&lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;8. Como você estruturaria uma aplicação web em Go?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Resposta esperada:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/cmd/api       - entry point
/internal
  /handlers    - HTTP handlers
  /services    - business logic
  /repository  - data access
  /models      - domain models
/pkg           - código reutilizável
/migrations    - DB migrations
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Dependency injection&lt;/li&gt;
&lt;li&gt;Interface-based design&lt;/li&gt;
&lt;li&gt;Separação de camadas&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;9. Explique o que é race condition e como detectar em Go&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Resposta esperada:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Múltiplas goroutines acessando mesma memória, pelo menos uma escrevendo&lt;/li&gt;
&lt;li&gt;Comportamento não-determinístico&lt;/li&gt;
&lt;li&gt;Detectar: &lt;code&gt;go run -race main.go&lt;/code&gt; ou &lt;code&gt;go test -race&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Prevenir: channels, sync.Mutex, sync/atomic&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🎓 Desenvolvedor Sênior
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Expertise Técnica Profunda
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Runtime internals&lt;/strong&gt;: Garbage collector, scheduler, memory model&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance optimization&lt;/strong&gt;: Benchmarking, profiling, otimizações&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Concurrency patterns&lt;/strong&gt;: Worker pools, pipeline, fan-out/fan-in&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory management&lt;/strong&gt;: Stack vs heap allocation, escape analysis&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reflection&lt;/strong&gt;: Package reflect, quando usar e trade-offs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unsafe package&lt;/strong&gt;: Quando é apropriado e riscos&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Assembly&lt;/strong&gt;: Leitura básica de assembly output&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Build tags e conditional compilation&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CGo&lt;/strong&gt;: Integração com C, trade-offs de performance&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Arquitetura e Design
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Microservices&lt;/strong&gt;: Design, comunicação, patterns&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Domain-Driven Design&lt;/strong&gt; em Go&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hexagonal Architecture&lt;/strong&gt; / Ports &amp;amp; Adapters&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Event-driven architecture&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CQRS e Event Sourcing&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API Design&lt;/strong&gt;: REST, gRPC, GraphQL&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Distributed systems&lt;/strong&gt;: CAP theorem, eventual consistency&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Message queues&lt;/strong&gt;: RabbitMQ, Kafka, NATS&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Observabilidade e Reliability
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Structured logging&lt;/strong&gt;: zap, zerolog&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Metrics&lt;/strong&gt;: Prometheus, OpenTelemetry&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tracing&lt;/strong&gt;: Jaeger, OpenTelemetry&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitoring&lt;/strong&gt;: Grafana, alerting&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Circuit breakers e retry policies&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rate limiting e backpressure&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Load balancing&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Health checks e readiness probes&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  DevOps e Deployment
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Docker&lt;/strong&gt;: Criação de imagens otimizadas multi-stage&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kubernetes&lt;/strong&gt;: Deployment, Services, ConfigMaps, Secrets&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CI/CD&lt;/strong&gt;: GitLab CI, GitHub Actions, Jenkins&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Infrastructure as Code&lt;/strong&gt;: Terraform, CloudFormation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloud platforms&lt;/strong&gt;: AWS, GCP, Azure com Go SDKs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Service mesh&lt;/strong&gt;: Istio, Linkerd&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Segurança
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Authentication/Authorization&lt;/strong&gt;: JWT, OAuth2, OIDC&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cryptography&lt;/strong&gt;: TLS, encryption at rest&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Input validation e sanitization&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SQL injection prevention&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secrets management&lt;/strong&gt;: Vault, AWS Secrets Manager&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security best practices&lt;/strong&gt;: OWASP Top 10&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Testing Avançado
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Test coverage&lt;/strong&gt;: Estratégias para cobertura efetiva&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mocking&lt;/strong&gt;: gomock, testify/mock&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integration tests&lt;/strong&gt;: testcontainers-go&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;E2E tests&lt;/strong&gt;: Estratégias de teste end-to-end&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Contract testing&lt;/strong&gt;: Pact&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Load testing&lt;/strong&gt;: k6, vegeta&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chaos engineering&lt;/strong&gt;: Princípios e ferramentas&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Performance
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Profiling&lt;/strong&gt;: CPU, memory, goroutine, mutex profiling&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Benchmarking&lt;/strong&gt;: Microbenchmarks, análise de resultados&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimization&lt;/strong&gt;: Hot path optimization, algoritmos eficientes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory leaks&lt;/strong&gt;: Detecção e prevenção&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Caching strategies&lt;/strong&gt;: Redis, in-memory caching&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database optimization&lt;/strong&gt;: Indexing, query optimization&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Ferramentas Avançadas
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;go:generate&lt;/strong&gt;: Templates, protobuf, mocks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wire&lt;/strong&gt;: Dependency injection automática&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Buf&lt;/strong&gt;: Gerenciamento de Protocol Buffers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Task/Make&lt;/strong&gt;: Build automation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;govulncheck&lt;/strong&gt;: Verificação de vulnerabilidades&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;staticcheck&lt;/strong&gt;: Análise estática avançada&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Liderança Técnica
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Code review&lt;/strong&gt;: Habilidade de revisar código efetivamente&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mentoria&lt;/strong&gt;: Capacidade de ensinar e guiar júniores/plenos&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Architectural decisions&lt;/strong&gt;: Trade-offs e decisões de arquitetura&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Technical debt&lt;/strong&gt;: Identificação e gerenciamento&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RFC/ADR&lt;/strong&gt;: Documentação de decisões técnicas&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance budgets&lt;/strong&gt;: Definição e monitoramento&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Migration strategies&lt;/strong&gt;: Estratégias de migração de sistemas legados&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Comunidade e Ecosystem
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Go Proverbs&lt;/strong&gt;: Conhecimento dos princípios da linguagem&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Go proposals&lt;/strong&gt;: Acompanhamento de novas features&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open source&lt;/strong&gt;: Contribuição em projetos Go&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tendências&lt;/strong&gt;: Conhecimento das últimas tendências em Go&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Go conferences&lt;/strong&gt;: Acompanhamento de talks e keynotes&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Bibliotecas e Frameworks Avançados
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;gRPC&lt;/strong&gt;: Implementação completa de serviços&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Protocol Buffers&lt;/strong&gt;: Definição de schemas&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GraphQL&lt;/strong&gt;: go-graphql, gqlgen&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Temporal/Cadence&lt;/strong&gt;: Workflow orchestration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NATS&lt;/strong&gt;: Messaging system&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;etcd&lt;/strong&gt;: Service discovery e configuration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consul&lt;/strong&gt;: Service mesh e discovery&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Perguntas Sugeridas para Sênior
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Explique como funciona o garbage collector do Go e suas otimizações&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Resposta esperada:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GC concurrent tri-color mark-and-sweep&lt;/li&gt;
&lt;li&gt;STW (Stop-The-World) minimizado (&amp;lt;1ms em Go 1.5+)&lt;/li&gt;
&lt;li&gt;Write barriers durante marking phase&lt;/li&gt;
&lt;li&gt;Tuneable com &lt;code&gt;GOGC&lt;/code&gt; (padrão 100 = 100% overhead)&lt;/li&gt;
&lt;li&gt;Otimizações: escape analysis move alocações para stack&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Como você identificaria e resolveria um memory leak em produção?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Resposta esperada:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;pprof&lt;/code&gt; para heap profile: &lt;code&gt;go tool pprof http://localhost:6060/debug/pprof/heap&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Comparar snapshots: &lt;code&gt;base&lt;/code&gt; vs current&lt;/li&gt;
&lt;li&gt;Monitorar goroutine leaks: &lt;code&gt;/debug/pprof/goroutine&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Procurar: maps sem cleanup, goroutines sem término, channels não fechados&lt;/li&gt;
&lt;li&gt;Solução: defer cleanup, context cancelation, timeouts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Descreva a implementação de um worker pool otimizado usando goroutines&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Resposta esperada:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;workerPool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jobs&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="n"&gt;Job&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="k"&gt;chan&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;workers&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;wg&lt;/span&gt; &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WaitGroup&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;workers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;job&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;jobs&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nb"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Número de workers = &lt;code&gt;runtime.NumCPU()&lt;/code&gt; ou baseado em I/O&lt;/li&gt;
&lt;li&gt;Buffered channels para evitar blocking&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. Quando você usaria reflection e quais são os trade-offs?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Resposta esperada:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Casos: serialização (JSON), ORMs, dependency injection, testes&lt;/li&gt;
&lt;li&gt;Trade-offs: performance (-10x a -100x), type safety perdida, complexidade&lt;/li&gt;
&lt;li&gt;Evitar em hot paths&lt;/li&gt;
&lt;li&gt;Alternativas: code generation, generics (Go 1.18+)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;5. Como funciona escape analysis e como isso afeta performance?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Resposta esperada:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Determina se variável vai para stack ou heap&lt;/li&gt;
&lt;li&gt;Stack: rápido, sem GC overhead&lt;/li&gt;
&lt;li&gt;Heap: escapa se: retornada, armazenada em estrutura global, muito grande&lt;/li&gt;
&lt;li&gt;Ver decisões: &lt;code&gt;go build -gcflags='-m'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Otimizar: retornar values em vez de pointers quando possível&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;6. Explique diferentes estratégias de graceful shutdown em serviços Go&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Resposta esperada:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;quit&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;quit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;syscall&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SIGINT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;syscall&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SIGTERM&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;quit&lt;/span&gt;

&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;srv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Shutdown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Drain connection pools, finalizar goroutines, flush buffers&lt;/li&gt;
&lt;li&gt;Health check retorna unhealthy imediatamente&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;7. Como você implementaria um sistema distribuído de rate limiting?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Resposta esperada:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sliding window com Redis: &lt;code&gt;INCR key&lt;/code&gt;, &lt;code&gt;EXPIRE key ttl&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Token bucket distribuído: Redis sorted sets&lt;/li&gt;
&lt;li&gt;Algoritmos: leaky bucket, sliding window counter&lt;/li&gt;
&lt;li&gt;Considerar: latência rede, consistência eventual, fallback local&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;8. Descreva sua abordagem para migrar um monolito para microservices em Go&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Resposta esperada:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Estratégia strangler fig pattern&lt;/li&gt;
&lt;li&gt;Identificar bounded contexts (DDD)&lt;/li&gt;
&lt;li&gt;Extrair serviços por domínio, não por camada&lt;/li&gt;
&lt;li&gt;API Gateway para roteamento&lt;/li&gt;
&lt;li&gt;Event-driven communication (NATS/Kafka)&lt;/li&gt;
&lt;li&gt;Database per service gradualmente&lt;/li&gt;
&lt;li&gt;Feature flags para rollback&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;9. Como você garantiria zero-downtime deployment?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Resposta esperada:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Blue-green deployment ou rolling update&lt;/li&gt;
&lt;li&gt;Health checks (readiness/liveness probes)&lt;/li&gt;
&lt;li&gt;Graceful shutdown&lt;/li&gt;
&lt;li&gt;Database migrations backward compatible&lt;/li&gt;
&lt;li&gt;Feature toggles&lt;/li&gt;
&lt;li&gt;Load balancer draining&lt;/li&gt;
&lt;li&gt;Monitoring e rollback automático&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;10. Explique o memory model do Go e como prevenir race conditions sutis&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Resposta esperada:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Happens-before relationship&lt;/li&gt;
&lt;li&gt;Channel operations garantem sincronização&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sync/atomic&lt;/code&gt; para operações atômicas&lt;/li&gt;
&lt;li&gt;Evitar: unsynchronized shared memory&lt;/li&gt;
&lt;li&gt;Usar &lt;code&gt;-race&lt;/code&gt; detector sempre&lt;/li&gt;
&lt;li&gt;Patterns: channels, mutexes, sync.Once&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;11. Como você otimizaria uma aplicação Go que está com alto uso de CPU?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Resposta esperada:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CPU profiling: &lt;code&gt;go tool pprof http://localhost:6060/debug/pprof/profile?seconds=30&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Identificar hot paths (top functions)&lt;/li&gt;
&lt;li&gt;Otimizações: algoritmos (O(n²) → O(n log n)), pools (&lt;code&gt;sync.Pool&lt;/code&gt;), reduce allocations&lt;/li&gt;
&lt;li&gt;Benchmarks antes/depois: &lt;code&gt;go test -bench=. -benchmem&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Considerar: caching, lazy evaluation, concurrency&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;12. Descreve como implementaria observabilidade completa em um sistema distribuído&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Resposta esperada:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Logging&lt;/strong&gt;: structured logs (zap/zerolog), correlation IDs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Metrics&lt;/strong&gt;: Prometheus (RED/USE method), custom business metrics&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tracing&lt;/strong&gt;: OpenTelemetry, propagação de trace context&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dashboards&lt;/strong&gt;: Grafana com SLI/SLO&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alerting&lt;/strong&gt;: baseado em SLOs, runbooks&lt;/li&gt;
&lt;li&gt;Instrumentação automática vs manual&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;13. Quais são os trade-offs entre diferentes patterns de error handling em Go?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Resposta esperada:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;if err != nil&lt;/code&gt;: verboso mas explícito&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;panic/recover&lt;/code&gt;: apenas para erros irrecuperáveis&lt;/li&gt;
&lt;li&gt;Sentinel errors vs error types vs wrapped errors&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;errors.Is/As&lt;/code&gt; vs type assertion&lt;/li&gt;
&lt;li&gt;Error wrapping: contexto vs stack trace&lt;/li&gt;
&lt;li&gt;Considerações: performance, debugabilidade, API clarity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;14. Como você faria profiling de uma aplicação em produção sem impactar performance?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Resposta esperada:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ativar pprof endpoints com autenticação&lt;/li&gt;
&lt;li&gt;Sample rate baixo (30s, não continuous)&lt;/li&gt;
&lt;li&gt;Apenas em subset de instâncias&lt;/li&gt;
&lt;li&gt;Off-peak hours se possível&lt;/li&gt;
&lt;li&gt;Usar &lt;code&gt;-seconds=30&lt;/code&gt; para limitar duração&lt;/li&gt;
&lt;li&gt;Continuous profiling tools: Google Cloud Profiler, Datadog&lt;/li&gt;
&lt;li&gt;Overhead &amp;lt; 5% aceitável&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;15. Explique sua estratégia para testing em uma arquitetura de microservices&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Resposta esperada:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Unit tests&lt;/strong&gt;: lógica de negócio isolada, mocks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integration tests&lt;/strong&gt;: testcontainers-go para dependencies&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Contract tests&lt;/strong&gt;: Pact entre consumers/providers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;E2E tests&lt;/strong&gt;: cenários críticos, ambiente staging&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chaos testing&lt;/strong&gt;: simular falhas (latency, network partition)&lt;/li&gt;
&lt;li&gt;Test pyramid: muito unit, médio integration, pouco E2E&lt;/li&gt;
&lt;li&gt;CI/CD com coverage mínimo (80%+)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🎯 Guia de Nivelamento Interativo
&lt;/h2&gt;

&lt;p&gt;Esta seção ajuda você a identificar o nível do desenvolvedor quando você não tem certeza. Use o fluxograma abaixo para fazer perguntas progressivas e deduzir o nível baseado nas respostas.&lt;/p&gt;

&lt;h3&gt;
  
  
  Como Usar
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Comece com a &lt;strong&gt;Pergunta Inicial&lt;/strong&gt; (P1)&lt;/li&gt;
&lt;li&gt;Avalie a resposta do candidato&lt;/li&gt;
&lt;li&gt;Siga o fluxo baseado na qualidade da resposta&lt;/li&gt;
&lt;li&gt;Faça perguntas de confirmação&lt;/li&gt;
&lt;li&gt;Chegue a uma conclusão sobre o nível&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Fluxograma de Nivelamento
&lt;/h3&gt;

&lt;h4&gt;
  
  
  P1: Explique a diferença entre slice e array em Go
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Nível Resposta&lt;/th&gt;
&lt;th&gt;Indicadores&lt;/th&gt;
&lt;th&gt;Dedução&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;❌ Inadequada&lt;/td&gt;
&lt;td&gt;Não sabe, confunde conceitos, diz que são iguais&lt;/td&gt;
&lt;td&gt;Abaixo de Júnior&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✓ Básica&lt;/td&gt;
&lt;td&gt;"Array fixo, slice dinâmico", menciona &lt;code&gt;append()&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Júnior potencial → P2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✓✓ Completa&lt;/td&gt;
&lt;td&gt;Implementação interna, slice como referência, capacity vs length, performance&lt;/td&gt;
&lt;td&gt;Pleno+ → P3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  P2: Como você trataria erros em Go?
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Nível Resposta&lt;/th&gt;
&lt;th&gt;Indicadores&lt;/th&gt;
&lt;th&gt;Dedução&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;❌ Inadequada&lt;/td&gt;
&lt;td&gt;Apenas &lt;code&gt;if err != nil&lt;/code&gt; sem contexto adicional&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Júnior&lt;/strong&gt; confirmado&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✓ Intermediária&lt;/td&gt;
&lt;td&gt;Wrap errors com &lt;code&gt;%w&lt;/code&gt;, contexto nas mensagens&lt;/td&gt;
&lt;td&gt;Pleno potencial → P4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✓✓ Avançada&lt;/td&gt;
&lt;td&gt;Custom errors, &lt;code&gt;errors.Is/As&lt;/code&gt;, patterns idiomáticos&lt;/td&gt;
&lt;td&gt;Pleno+ → P5&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  P3: Explique como funcionam as goroutines e o scheduler do Go
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Nível Resposta&lt;/th&gt;
&lt;th&gt;Indicadores&lt;/th&gt;
&lt;th&gt;Dedução&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;❌ Inadequada&lt;/td&gt;
&lt;td&gt;"São threads leves" sem mais detalhes&lt;/td&gt;
&lt;td&gt;Pleno potencial → P4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✓ Intermediária&lt;/td&gt;
&lt;td&gt;M:N threading, G-M-P model, conceitos corretos&lt;/td&gt;
&lt;td&gt;Pleno+ → P5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✓✓ Avançada&lt;/td&gt;
&lt;td&gt;Work stealing, preemption, detalhes de implementação&lt;/td&gt;
&lt;td&gt;Sênior potencial → P6&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  P4: Quando você usaria um pointer receiver vs value receiver?
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Nível Resposta&lt;/th&gt;
&lt;th&gt;Indicadores&lt;/th&gt;
&lt;th&gt;Dedução&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;❌ Inadequada&lt;/td&gt;
&lt;td&gt;Não sabe quando usar&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Júnior&lt;/strong&gt; confirmado&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✓ Intermediária&lt;/td&gt;
&lt;td&gt;Mutação vs imutabilidade, performance básica&lt;/td&gt;
&lt;td&gt;Pleno potencial → P7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✓✓ Avançada&lt;/td&gt;
&lt;td&gt;Escape analysis, consistency rules, trade-offs&lt;/td&gt;
&lt;td&gt;Pleno+ → P8&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  P5: Como você implementaria um rate limiter usando channels?
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Nível Resposta&lt;/th&gt;
&lt;th&gt;Indicadores&lt;/th&gt;
&lt;th&gt;Dedução&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;❌ Inadequada&lt;/td&gt;
&lt;td&gt;Não consegue ou implementação errada&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Pleno&lt;/strong&gt; confirmado&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✓ Intermediária&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;time.Tick&lt;/code&gt; ou buffered channel básico&lt;/td&gt;
&lt;td&gt;Pleno+ → P8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✓✓ Avançada&lt;/td&gt;
&lt;td&gt;Token bucket, bibliotecas &lt;code&gt;x/time/rate&lt;/code&gt;, distribuído&lt;/td&gt;
&lt;td&gt;Sênior potencial → P9&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  P6: Como você identificaria e resolveria um memory leak em produção?
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Nível Resposta&lt;/th&gt;
&lt;th&gt;Indicadores&lt;/th&gt;
&lt;th&gt;Dedução&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;❌ Inadequada&lt;/td&gt;
&lt;td&gt;Não sabe ferramentas ou processo&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Pleno&lt;/strong&gt; confirmado&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✓ Intermediária&lt;/td&gt;
&lt;td&gt;Menciona pprof, processo básico de investigação&lt;/td&gt;
&lt;td&gt;Sênior potencial → P9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✓✓ Avançada&lt;/td&gt;
&lt;td&gt;pprof detalhado, goroutine leaks, continuous profiling&lt;/td&gt;
&lt;td&gt;Sênior potencial → P10&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  P7: O que é race condition e como detectar em Go?
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Nível Resposta&lt;/th&gt;
&lt;th&gt;Indicadores&lt;/th&gt;
&lt;th&gt;Dedução&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;❌ Inadequada&lt;/td&gt;
&lt;td&gt;Conceito vago ou incorreto&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Júnior&lt;/strong&gt; confirmado&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✓ Boa&lt;/td&gt;
&lt;td&gt;Explica bem, menciona &lt;code&gt;-race&lt;/code&gt;, sync primitives&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Pleno&lt;/strong&gt; confirmado&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  P8: Como você estruturaria uma aplicação web em Go?
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Nível Resposta&lt;/th&gt;
&lt;th&gt;Indicadores&lt;/th&gt;
&lt;th&gt;Dedução&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;❌ Inadequada&lt;/td&gt;
&lt;td&gt;Tudo em um arquivo ou sem separação clara&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Pleno&lt;/strong&gt; confirmado&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✓ Intermediária&lt;/td&gt;
&lt;td&gt;Handler/Service/Repository básico&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Pleno&lt;/strong&gt; confirmado&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✓✓ Avançada&lt;/td&gt;
&lt;td&gt;Hexagonal/Clean arch, DI, interfaces bem definidas&lt;/td&gt;
&lt;td&gt;Sênior potencial → P11&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  P9: Descreva sua abordagem para migrar um monolito para microservices em Go
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Nível Resposta&lt;/th&gt;
&lt;th&gt;Indicadores&lt;/th&gt;
&lt;th&gt;Dedução&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;❌ Inadequada&lt;/td&gt;
&lt;td&gt;Sem experiência ou estratégia&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Pleno&lt;/strong&gt; confirmado&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✓ Intermediária&lt;/td&gt;
&lt;td&gt;Strangler pattern, bounded contexts&lt;/td&gt;
&lt;td&gt;Sênior potencial → P12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✓✓ Avançada&lt;/td&gt;
&lt;td&gt;DDD completo, event-driven, database per service&lt;/td&gt;
&lt;td&gt;Sênior potencial → P13&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  P10: Como você faria profiling de uma aplicação em produção sem impactar performance?
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Nível Resposta&lt;/th&gt;
&lt;th&gt;Indicadores&lt;/th&gt;
&lt;th&gt;Dedução&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;❌ Inadequada&lt;/td&gt;
&lt;td&gt;Não considerou impacto&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Pleno&lt;/strong&gt; confirmado&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✓ Intermediária&lt;/td&gt;
&lt;td&gt;Sample rate, subset de instâncias&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Sênior&lt;/strong&gt; confirmado&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✓✓ Avançada&lt;/td&gt;
&lt;td&gt;Continuous profiling, overhead budget, ferramentas enterprise&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Sênior&lt;/strong&gt; confirmado&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  P11: Quais são os trade-offs entre diferentes patterns de error handling em Go?
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Nível Resposta&lt;/th&gt;
&lt;th&gt;Indicadores&lt;/th&gt;
&lt;th&gt;Dedução&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;❌ Inadequada&lt;/td&gt;
&lt;td&gt;Conhece apenas if err != nil&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Pleno&lt;/strong&gt; confirmado&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✓ Intermediária&lt;/td&gt;
&lt;td&gt;Sentinel vs wrapped, trade-offs básicos&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Sênior&lt;/strong&gt; confirmado&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✓✓ Avançada&lt;/td&gt;
&lt;td&gt;Performance, debugabilidade, API design&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Sênior&lt;/strong&gt; confirmado&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  P12: Como você garantiria zero-downtime deployment?
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Nível Resposta&lt;/th&gt;
&lt;th&gt;Indicadores&lt;/th&gt;
&lt;th&gt;Dedução&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;❌ Inadequada&lt;/td&gt;
&lt;td&gt;Não sabe estratégias&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Pleno&lt;/strong&gt; confirmado&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✓ Intermediária&lt;/td&gt;
&lt;td&gt;Blue-green ou rolling, health checks&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Sênior&lt;/strong&gt; confirmado&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✓✓ Avançada&lt;/td&gt;
&lt;td&gt;Graceful shutdown completo, migrations compatíveis&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Sênior&lt;/strong&gt; confirmado&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  P13: Como você implementaria observabilidade completa em um sistema distribuído?
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Nível Resposta&lt;/th&gt;
&lt;th&gt;Indicadores&lt;/th&gt;
&lt;th&gt;Dedução&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;❌ Inadequada&lt;/td&gt;
&lt;td&gt;Apenas logging isolado&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Pleno&lt;/strong&gt; confirmado&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✓ Intermediária&lt;/td&gt;
&lt;td&gt;Logs + Metrics + Tracing, ferramentas&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Sênior&lt;/strong&gt; confirmado&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✓✓ Avançada&lt;/td&gt;
&lt;td&gt;OpenTelemetry, correlation IDs, SLI/SLO, runbooks&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Sênior&lt;/strong&gt; confirmado&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  💡 Dicas de Uso
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Flexibilidade&lt;/strong&gt;: Você não precisa seguir todas as perguntas se já tiver certeza do nível&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Adaptação&lt;/strong&gt;: Ajuste perguntas baseado no contexto da vaga&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Observação&lt;/strong&gt;: Preste atenção não só no que dizem, mas em COMO explicam&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Profundidade&lt;/strong&gt;: Faça follow-ups para confirmar entendimento real vs decorado&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prática&lt;/strong&gt;: Candidatos podem saber teoria mas não ter prática (ou vice-versa)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ⚠️ Sinais de Alerta
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Red Flags para qualquer nível&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Respostas decoradas sem entendimento&lt;/li&gt;
&lt;li&gt;Não admite quando não sabe&lt;/li&gt;
&lt;li&gt;Defensivo ao receber perguntas mais difíceis&lt;/li&gt;
&lt;li&gt;Não consegue explicar com exemplos práticos&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Green Flags&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Admite quando não sabe algo específico&lt;/li&gt;
&lt;li&gt;Relaciona conceitos entre si&lt;/li&gt;
&lt;li&gt;Dá exemplos de experiências reais&lt;/li&gt;
&lt;li&gt;Faz perguntas de volta para clarificar contexto&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  📊 Conhecimentos por Categoria
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Categorização Visual
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Júnior  ▓▓▓▓▓▓▓▓░░░░░░░░░░░░  Sintaxe e Fundamentos
Pleno   ▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░░░░░  Padrões e Ferramentas
Sênior  ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓  Arquitetura e Liderança
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  💡 Dicas para Entrevistas
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Para Avaliar Júnior
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Foque em fundamentos: sintaxe, tipos de dados, estruturas básicas&lt;/li&gt;
&lt;li&gt;Peça para resolver problemas simples de algoritmos&lt;/li&gt;
&lt;li&gt;Avalie a capacidade de ler e entender código&lt;/li&gt;
&lt;li&gt;Teste conhecimento de error handling básico&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Para Avaliar Pleno
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Apresente cenários reais de desenvolvimento&lt;/li&gt;
&lt;li&gt;Peça para desenhar arquitetura de uma API REST&lt;/li&gt;
&lt;li&gt;Avalie conhecimento de testes e boas práticas&lt;/li&gt;
&lt;li&gt;Discuta trade-offs de diferentes abordagens&lt;/li&gt;
&lt;li&gt;Código review de um snippet com problemas&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Para Avaliar Sênior
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Discussões de arquitetura em alto nível&lt;/li&gt;
&lt;li&gt;Resolução de problemas de produção (debugging, performance)&lt;/li&gt;
&lt;li&gt;Decisões técnicas com justificativas baseadas em trade-offs&lt;/li&gt;
&lt;li&gt;Capacidade de mentoria e liderança técnica&lt;/li&gt;
&lt;li&gt;Conhecimento de design distribuído e escalabilidade&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔗 Recursos Recomendados
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Livros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Júnior&lt;/strong&gt;: "The Go Programming Language" (Donovan &amp;amp; Kernighan)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pleno&lt;/strong&gt;: "Concurrency in Go" (Katherine Cox-Buday)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sênior&lt;/strong&gt;: "Distributed Services with Go" (Travis Jeffery)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Websites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://gobyexample.com/" rel="noopener noreferrer"&gt;Go by Example&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://go.dev/doc/effective_go" rel="noopener noreferrer"&gt;Effective Go&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://go.dev/blog/" rel="noopener noreferrer"&gt;Go Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/avelino/awesome-go" rel="noopener noreferrer"&gt;Awesome Go&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Practice
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://exercism.org/tracks/go" rel="noopener noreferrer"&gt;Exercism Go Track&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://leetcode.com/" rel="noopener noreferrer"&gt;LeetCode&lt;/a&gt; com soluções em Go&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gophercises.com/" rel="noopener noreferrer"&gt;Gophercises&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>go</category>
      <category>entrevista</category>
      <category>nivelamento</category>
      <category>senioridade</category>
    </item>
    <item>
      <title>🚀 Criar Endpoint POST /invoices</title>
      <dc:creator>Thiago Matos</dc:creator>
      <pubDate>Mon, 29 Dec 2025 22:23:00 +0000</pubDate>
      <link>https://forem.com/thiagoematos/criar-endpoint-post-invoices-27ai</link>
      <guid>https://forem.com/thiagoematos/criar-endpoint-post-invoices-27ai</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Para:&lt;/strong&gt; Desenvolvedor Júnior Iniciante&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Objetivo:&lt;/strong&gt; Criar um endpoint REST para cadastrar faturas&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Tempo estimado:&lt;/strong&gt; 3-4 horas&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Nível de dificuldade:&lt;/strong&gt; ⭐⭐⭐ Intermediário&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  📋 Pré-requisitos
&lt;/h2&gt;

&lt;p&gt;Antes de começar, certifique-se de que você completou:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Projeto &lt;code&gt;invoice-service&lt;/code&gt; criado e funcionando&lt;/li&gt;
&lt;li&gt;✅ IntelliJ IDEA configurado corretamente&lt;/li&gt;
&lt;li&gt;✅ Aplicação roda em &lt;code&gt;http://localhost:8080&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;✅ Estrutura de pacotes criada (&lt;code&gt;controller&lt;/code&gt;, &lt;code&gt;service&lt;/code&gt;, &lt;code&gt;model&lt;/code&gt;, &lt;code&gt;repository&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Se algo estiver pendente, volte ao guia &lt;a href="https://dev.to/thiagoematos/como-criar-um-novo-projeto-spring-boot-36pj"&gt;Como criar um novo projeto Spring Boot&lt;/a&gt;! 😊&lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 O que vamos construir?
&lt;/h2&gt;

&lt;p&gt;Hoje você vai criar sua &lt;strong&gt;primeira API REST&lt;/strong&gt; funcional! Especificamente:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Modelo de dados Invoice&lt;/strong&gt; - A estrutura que representa uma fatura&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Endpoint POST /invoices&lt;/strong&gt; - Para criar novas faturas&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validações&lt;/strong&gt; - Garantir que os dados estão corretos&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testes&lt;/strong&gt; - Verificar se tudo funciona usando Postman ou cURL&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Resultado final:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Enviar requisição&lt;/span&gt;
POST http://localhost:8080/invoices
&lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"customerId"&lt;/span&gt;: &lt;span class="s2"&gt;"CUST001"&lt;/span&gt;,
  &lt;span class="s2"&gt;"amount"&lt;/span&gt;: 150.50,
  &lt;span class="s2"&gt;"status"&lt;/span&gt;: &lt;span class="s2"&gt;"PENDING"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# Receber resposta 201 Created&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"id"&lt;/span&gt;: &lt;span class="s2"&gt;"550e8400-e29b-41d4-a716-446655440000"&lt;/span&gt;,
  &lt;span class="s2"&gt;"customerId"&lt;/span&gt;: &lt;span class="s2"&gt;"CUST001"&lt;/span&gt;,
  &lt;span class="s2"&gt;"amount"&lt;/span&gt;: 150.50,
  &lt;span class="s2"&gt;"status"&lt;/span&gt;: &lt;span class="s2"&gt;"PENDING"&lt;/span&gt;,
  &lt;span class="s2"&gt;"createdAt"&lt;/span&gt;: &lt;span class="s2"&gt;"2025-12-29T18:00:00"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Legal, né? Vamos lá! 🚀&lt;/p&gt;




&lt;h2&gt;
  
  
  📦 Parte 1: Criar o Modelo de Dados (Invoice)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  O que é um modelo de dados?
&lt;/h3&gt;

&lt;p&gt;É uma &lt;strong&gt;classe que representa um objeto do mundo real&lt;/strong&gt;. No nosso caso, uma fatura (invoice).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Analogia:&lt;/strong&gt; Pense em um formulário de papel. O modelo é como o template desse formulário, definindo quais campos existem (nome, CPF, valor, etc.).&lt;/p&gt;

&lt;h3&gt;
  
  
  Passo a Passo
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1.1 Criar a Data Class Invoice
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;No IntelliJ, navegue até: &lt;code&gt;src/main/kotlin/com/invoice/model/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Clique com botão direito na pasta &lt;code&gt;model&lt;/code&gt; → &lt;strong&gt;New → Kotlin Class/File&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Digite: &lt;code&gt;Invoice&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Selecione: &lt;strong&gt;Class&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  1.2 Implementar a Data Class
&lt;/h4&gt;

&lt;p&gt;Abra o arquivo &lt;code&gt;Invoice.kt&lt;/code&gt; e adicione o seguinte código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;com.invoice.model&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;jakarta.validation.constraints.NotBlank&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;jakarta.validation.constraints.NotNull&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;jakarta.validation.constraints.Positive&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.math.BigDecimal&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.time.LocalDateTime&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.UUID&lt;/span&gt;

&lt;span class="kd"&gt;data class&lt;/span&gt; &lt;span class="nc"&gt;Invoice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;UUID&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randomUUID&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;

    &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nc"&gt;NotBlank&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Customer ID é obrigatório"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;customerId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nc"&gt;NotNull&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Valor é obrigatório"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nc"&gt;Positive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Valor deve ser positivo"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;BigDecimal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nc"&gt;NotBlank&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Status é obrigatório"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;LocalDateTime&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LocalDateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  1.3 Entendendo o Código Linha por Linha
&lt;/h4&gt;

&lt;p&gt;Vamos explicar cada parte:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Imports:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;jakarta.validation.constraints.NotBlank&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;jakarta.validation.constraints.NotNull&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;jakarta.validation.constraints.Positive&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esses imports trazem as &lt;strong&gt;anotações de validação&lt;/strong&gt;. São como "regras" que garantem dados válidos.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Data Class:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;data class&lt;/span&gt; &lt;span class="nc"&gt;Invoice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;data class&lt;/code&gt; - Tipo especial do Kotlin que gera automaticamente:

&lt;ul&gt;
&lt;li&gt;Método &lt;code&gt;equals()&lt;/code&gt; - compara objetos&lt;/li&gt;
&lt;li&gt;Método &lt;code&gt;hashCode()&lt;/code&gt; - útil para coleções&lt;/li&gt;
&lt;li&gt;Método &lt;code&gt;toString()&lt;/code&gt; - mostra os valores&lt;/li&gt;
&lt;li&gt;Método &lt;code&gt;copy()&lt;/code&gt; - cria cópias com alterações&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Analogia:&lt;/strong&gt; É como um atalho que escreve muito código por você!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Propriedades:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;UUID&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randomUUID&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;val&lt;/code&gt; - Propriedade imutável (não pode ser alterada depois)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;id: String&lt;/code&gt; - Nome e tipo da propriedade&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;UUID.randomUUID().toString()&lt;/code&gt; - Gera um ID único automaticamente

&lt;ul&gt;
&lt;li&gt;Exemplo: &lt;code&gt;"550e8400-e29b-41d4-a716-446655440000"&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nc"&gt;NotBlank&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Customer ID é obrigatório"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;customerId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;@field:NotBlank&lt;/code&gt; - Validação: não pode ser vazio ou só espaços&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;message = "..."&lt;/code&gt; - Mensagem de erro customizada&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;customerId: String&lt;/code&gt; - ID do cliente
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nc"&gt;NotNull&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Valor é obrigatório"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nc"&gt;Positive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Valor deve ser positivo"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;BigDecimal&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;BigDecimal&lt;/code&gt; - Tipo para valores monetários (mais preciso que &lt;code&gt;Double&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@NotNull&lt;/code&gt; - Não pode ser nulo&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@Positive&lt;/code&gt; - Deve ser maior que zero&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Por que BigDecimal?&lt;/strong&gt; Números decimais como &lt;code&gt;Double&lt;/code&gt; têm problemas de arredondamento. Para dinheiro, use sempre &lt;code&gt;BigDecimal&lt;/code&gt;!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;LocalDateTime&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LocalDateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;LocalDateTime&lt;/code&gt; - Data e hora sem timezone&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;LocalDateTime.now()&lt;/code&gt; - Pega data/hora atual automaticamente&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  1.4 Adicionar Dependência de Validação
&lt;/h4&gt;

&lt;p&gt;Para as validações funcionarem, precisamos adicionar a dependência no &lt;code&gt;build.gradle.kts&lt;/code&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Abra o arquivo &lt;code&gt;build.gradle.kts&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Localize a seção &lt;code&gt;dependencies&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Adicione esta linha:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;dependencies&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ... dependências existentes ...&lt;/span&gt;

    &lt;span class="c1"&gt;// Validação&lt;/span&gt;
    &lt;span class="nf"&gt;implementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"org.springframework.boot:spring-boot-starter-validation"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Clique no ícone 🐘 (elefante do Gradle) que aparece no canto superior direito&lt;/li&gt;
&lt;li&gt;Selecione &lt;strong&gt;Reload Gradle Project&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;⏱️ Aguarde alguns segundos enquanto o Gradle baixa a dependência.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  1.5 Testar a Data Class
&lt;/h4&gt;

&lt;p&gt;Vamos verificar se a classe compila corretamente:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Clique com botão direito no arquivo &lt;code&gt;Invoice.kt&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Selecione &lt;strong&gt;Build Module 'invoice-service.main'&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;✅ &lt;strong&gt;Se não aparecer erro, perfeito!&lt;/strong&gt; Sua data class está pronta.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎮 Parte 2: Criar o Controller
&lt;/h2&gt;

&lt;h3&gt;
  
  
  O que é um Controller?
&lt;/h3&gt;

&lt;p&gt;É a classe que &lt;strong&gt;recebe requisições HTTP&lt;/strong&gt; e as processa. É a "porta de entrada" da sua API.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Analogia:&lt;/strong&gt; É como o atendente de um restaurante que anota seu pedido e leva para a cozinha.&lt;/p&gt;

&lt;h3&gt;
  
  
  Passo a Passo
&lt;/h3&gt;

&lt;h4&gt;
  
  
  2.1 Criar a Classe InvoiceController
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Navegue até: &lt;code&gt;src/main/kotlin/com/invoice/controller/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Clique com botão direito → &lt;strong&gt;New → Kotlin Class/File&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Digite: &lt;code&gt;InvoiceController&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Selecione: &lt;strong&gt;Class&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  2.2 Implementar o Controller Básico
&lt;/h4&gt;

&lt;p&gt;Adicione o seguinte código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;com.invoice.controller&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.invoice.model.Invoice&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;jakarta.validation.Valid&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.http.HttpStatus&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.http.ResponseEntity&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.web.bind.annotation.*&lt;/span&gt;

&lt;span class="nd"&gt;@RestController&lt;/span&gt;
&lt;span class="nd"&gt;@RequestMapping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/invoices"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InvoiceController&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// Lista temporária para armazenar faturas (in-memory)&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;invoices&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mutableListOf&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Invoice&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;

    &lt;span class="nd"&gt;@PostMapping&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;createInvoice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@Valid&lt;/span&gt; &lt;span class="nd"&gt;@RequestBody&lt;/span&gt; &lt;span class="n"&gt;invoice&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Invoice&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;ResponseEntity&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Invoice&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Adiciona a fatura na lista&lt;/span&gt;
        &lt;span class="n"&gt;invoices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;invoice&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;// Retorna 201 Created com a fatura criada&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ResponseEntity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpStatus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CREATED&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;invoice&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2.3 Entendendo o Código Linha por Linha
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;1. Anotações da Classe:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@RestController&lt;/span&gt;
&lt;span class="nd"&gt;@RequestMapping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/invoices"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InvoiceController&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;@RestController&lt;/code&gt; - Diz ao Spring: "Esta classe é um controller REST"&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automaticamente converte objetos para JSON&lt;/li&gt;
&lt;li&gt;Processa requisições HTTP&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;@RequestMapping("/invoices")&lt;/code&gt; - Define o caminho base&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Todas as rotas deste controller começam com &lt;code&gt;/invoices&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Armazenamento Temporário:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;invoices&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mutableListOf&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Invoice&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;mutableListOf&amp;lt;Invoice&amp;gt;()&lt;/code&gt; - Lista mutável (pode adicionar/remover)&lt;/li&gt;
&lt;li&gt;Por enquanto, armazena só na memória (quando reiniciar a app, perde tudo)&lt;/li&gt;
&lt;li&gt;Na quarta-feira vamos adicionar banco de dados real!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Método createInvoice:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@PostMapping&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;createInvoice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@Valid&lt;/span&gt; &lt;span class="nd"&gt;@RequestBody&lt;/span&gt; &lt;span class="n"&gt;invoice&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Invoice&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;ResponseEntity&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Invoice&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Quebra completa:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;@PostMapping&lt;/code&gt; - Esta função responde a requisições HTTP POST&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Caminho completo: &lt;code&gt;POST /invoices&lt;/code&gt; (lembra do &lt;code&gt;@RequestMapping&lt;/code&gt;?)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;code&gt;fun createInvoice&lt;/code&gt; - Nome do método (pode ser qualquer nome)&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;@Valid&lt;/code&gt; - Valida o objeto usando as anotações que definimos (&lt;a class="mentioned-user" href="https://dev.to/notblank"&gt;@notblank&lt;/a&gt;, etc.)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Se validação falhar, retorna 400 Bad Request automaticamente&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;code&gt;@RequestBody&lt;/code&gt; - O Spring pega o JSON da requisição e converte para objeto Invoice&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;code&gt;invoice: Invoice&lt;/code&gt; - Parâmetro que recebe os dados&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;: ResponseEntity&amp;lt;Invoice&amp;gt;&lt;/code&gt; - Tipo de retorno&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ResponseEntity&lt;/code&gt; permite controlar status HTTP (201, 200, 404, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;Invoice&amp;gt;&lt;/code&gt; - O corpo da resposta será um objeto Invoice&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. Lógica do Método:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="n"&gt;invoices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;invoice&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Adiciona a fatura recebida na lista
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ResponseEntity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpStatus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CREATED&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;invoice&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ResponseEntity.status(HttpStatus.CREATED)&lt;/code&gt; - Define status 201 (Created)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.body(invoice)&lt;/code&gt; - Coloca a fatura no corpo da resposta&lt;/li&gt;
&lt;li&gt;Spring automaticamente converte para JSON&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Por que 201 e não 200?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;200 OK:&lt;/strong&gt; Requisição bem-sucedida (usado em GET, PUT)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;201 Created:&lt;/strong&gt; Recurso criado com sucesso (usado em POST)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;É uma boa prática usar o status HTTP correto!&lt;/p&gt;




&lt;h2&gt;
  
  
  🧪 Parte 3: Testar o Endpoint
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Opção A: Testar com cURL (Terminal)
&lt;/h3&gt;

&lt;p&gt;O cURL é uma ferramenta de linha de comando para fazer requisições HTTP.&lt;/p&gt;

&lt;h4&gt;
  
  
  3.1 Iniciar a Aplicação
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;No IntelliJ, abra &lt;code&gt;InvoiceServiceApplication.kt&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Clique no ▶️ verde ao lado de &lt;code&gt;fun main&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Aguarde aparecer: &lt;code&gt;Started InvoiceServiceApplication&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  3.2 Fazer a Requisição
&lt;/h4&gt;

&lt;p&gt;Abra um &lt;strong&gt;novo terminal&lt;/strong&gt; (fora do IntelliJ) e execute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://localhost:8080/invoices &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "customerId": "CUST001",
    "amount": 150.50,
    "status": "PENDING"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explicação do comando:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;curl&lt;/code&gt; - Ferramenta para fazer requisições HTTP&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-X POST&lt;/code&gt; - Método HTTP POST&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;http://localhost:8080/invoices&lt;/code&gt; - URL do endpoint&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-H "Content-Type: application/json"&lt;/code&gt; - Header dizendo que enviamos JSON&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-d '{...}'&lt;/code&gt; - Corpo da requisição (dados em JSON)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Resposta esperada:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"550e8400-e29b-41d4-a716-446655440000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"customerId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CUST001"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;150.50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PENDING"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"createdAt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2025-12-29T18:00:00"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ &lt;strong&gt;Se você viu isso, PARABÉNS!&lt;/strong&gt; Seu endpoint está funcionando! 🎉&lt;/p&gt;

&lt;h3&gt;
  
  
  Opção B: Testar com Postman (Recomendado)
&lt;/h3&gt;

&lt;p&gt;Postman é uma ferramenta visual mais amigável para testar APIs.&lt;/p&gt;

&lt;h4&gt;
  
  
  3.3 Instalar Postman
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Acesse: &lt;a href="https://www.postman.com/downloads/" rel="noopener noreferrer"&gt;https://www.postman.com/downloads/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Baixe e instale&lt;/li&gt;
&lt;li&gt;Crie uma conta gratuita (ou pule)&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  3.4 Criar a Requisição
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Abra o Postman&lt;/li&gt;
&lt;li&gt;Clique em &lt;strong&gt;New → HTTP Request&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Configure:&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Campo&lt;/th&gt;
&lt;th&gt;Valor&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Método&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;POST&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;URL&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;http://localhost:8080/invoices&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Vá na aba &lt;strong&gt;Body&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Selecione &lt;strong&gt;raw&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;No dropdown ao lado, selecione &lt;strong&gt;JSON&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Cole este JSON:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"customerId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CUST001"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;150.50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PENDING"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Clique em &lt;strong&gt;Send&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Resultado esperado:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Status: &lt;code&gt;201 Created&lt;/code&gt; (canto superior direito)&lt;/li&gt;
&lt;li&gt;Body: JSON com a fatura criada, incluindo &lt;code&gt;id&lt;/code&gt; e &lt;code&gt;createdAt&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  3.5 Testar Validações
&lt;/h4&gt;

&lt;p&gt;Vamos ver se as validações estão funcionando:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Teste 1: Enviar valor negativo&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"customerId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CUST001"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;-50.00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PENDING"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Resultado esperado:&lt;/strong&gt; &lt;code&gt;400 Bad Request&lt;/code&gt; com mensagem "Valor deve ser positivo"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Teste 2: Enviar customerId vazio&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"customerId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;100.00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PENDING"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Resultado esperado:&lt;/strong&gt; &lt;code&gt;400 Bad Request&lt;/code&gt; com mensagem "Customer ID é obrigatório"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Teste 3: Não enviar amount&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"customerId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CUST001"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PENDING"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Resultado esperado:&lt;/strong&gt; &lt;code&gt;400 Bad Request&lt;/code&gt; com mensagem "Valor é obrigatório"&lt;/p&gt;

&lt;p&gt;✅ Se todos os testes passaram, suas validações estão funcionando!&lt;/p&gt;




&lt;h2&gt;
  
  
  📊 Parte 4: Adicionar Logs para Debug
&lt;/h2&gt;

&lt;p&gt;Logs ajudam a entender o que está acontecendo na aplicação.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.1 Adicionar Logger no Controller
&lt;/h3&gt;

&lt;p&gt;Atualize seu &lt;code&gt;InvoiceController.kt&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;com.invoice.controller&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.invoice.model.Invoice&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;jakarta.validation.Valid&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.slf4j.LoggerFactory&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.http.HttpStatus&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.http.ResponseEntity&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.web.bind.annotation.*&lt;/span&gt;

&lt;span class="nd"&gt;@RestController&lt;/span&gt;
&lt;span class="nd"&gt;@RequestMapping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/invoices"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InvoiceController&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;logger&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LoggerFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;InvoiceController&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;invoices&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mutableListOf&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Invoice&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;

    &lt;span class="nd"&gt;@PostMapping&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;createInvoice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@Valid&lt;/span&gt; &lt;span class="nd"&gt;@RequestBody&lt;/span&gt; &lt;span class="n"&gt;invoice&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Invoice&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;ResponseEntity&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Invoice&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Recebida requisição para criar fatura: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;invoice&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;invoices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;invoice&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Fatura criada com sucesso. ID: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;invoice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ResponseEntity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpStatus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CREATED&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;invoice&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;O que mudou:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;private val logger = ...&lt;/code&gt; - Cria um objeto logger&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;logger.info("...")&lt;/code&gt; - Escreve mensagens no console&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4.2 Testar os Logs
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Reinicie a aplicação&lt;/li&gt;
&lt;li&gt;Faça uma requisição POST&lt;/li&gt;
&lt;li&gt;Observe o console do IntelliJ&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Você verá algo como:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;INFO  c.i.controller.InvoiceController - Recebida requisição para criar fatura: Invoice(id=550e8400..., customerId=CUST001, amount=150.50, status=PENDING, createdAt=2025-12-29T18:00:00)
INFO  c.i.controller.InvoiceController - Fatura criada com sucesso. ID: 550e8400-e29b-41d4-a716-446655440000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🎨 Parte 5: Melhorias Opcionais (Bônus)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  5.1 Criar um Enum para Status
&lt;/h3&gt;

&lt;p&gt;Ao invés de aceitar qualquer texto no status, vamos limitar aos valores válidos.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Crie o arquivo:&lt;/strong&gt; &lt;code&gt;src/main/kotlin/com/invoice/model/InvoiceStatus.kt&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;com.invoice.model&lt;/span&gt;

&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InvoiceStatus&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;PENDING&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nc"&gt;PAID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nc"&gt;CANCELLED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nc"&gt;OVERDUE&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Atualize a classe Invoice:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;data class&lt;/span&gt; &lt;span class="nc"&gt;Invoice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;UUID&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randomUUID&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;

    &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nc"&gt;NotBlank&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Customer ID é obrigatório"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;customerId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nc"&gt;NotNull&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Valor é obrigatório"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nc"&gt;Positive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Valor deve ser positivo"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;BigDecimal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nc"&gt;NotNull&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Status é obrigatório"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;InvoiceStatus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Mudou aqui!&lt;/span&gt;

    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;LocalDateTime&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LocalDateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora o JSON deve ser:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"customerId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CUST001"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;150.50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PENDING"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se enviar status inválido (ex: "INVALID"), retorna erro automaticamente!&lt;/p&gt;

&lt;h3&gt;
  
  
  5.2 Adicionar Endpoint GET para Listar Faturas
&lt;/h3&gt;

&lt;p&gt;Vamos adicionar um endpoint para ver todas as faturas criadas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@GetMapping&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;getAllInvoices&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;ResponseEntity&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Invoice&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Recebida requisição para listar todas as faturas"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ResponseEntity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;invoices&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Testar:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://localhost:8080/invoices
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ou no Postman: &lt;code&gt;GET http://localhost:8080/invoices&lt;/code&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ Critérios de Aceite - Checklist Final
&lt;/h2&gt;

&lt;p&gt;Marque cada item que você completou:&lt;/p&gt;

&lt;h3&gt;
  
  
  Criar Modelo Invoice
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Arquivo &lt;code&gt;Invoice.kt&lt;/code&gt; criado em &lt;code&gt;model/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;[ ] Data class com 5 campos: id, customerId, amount, status, createdAt&lt;/li&gt;
&lt;li&gt;[ ] Validações adicionadas: &lt;a class="mentioned-user" href="https://dev.to/notblank"&gt;@notblank&lt;/a&gt;, @NotNull, &lt;a class="mentioned-user" href="https://dev.to/positive"&gt;@positive&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;[ ] Dependência &lt;code&gt;spring-boot-starter-validation&lt;/code&gt; adicionada no build.gradle.kts&lt;/li&gt;
&lt;li&gt;[ ] Classe compila sem erros&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Criar InvoiceController
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Arquivo &lt;code&gt;InvoiceController.kt&lt;/code&gt; criado em &lt;code&gt;controller/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;[ ] Classe anotada com @RestController&lt;/li&gt;
&lt;li&gt;[ ] @RequestMapping("/invoices") configurado&lt;/li&gt;
&lt;li&gt;[ ] Lista in-memory criada (mutableListOf)&lt;/li&gt;
&lt;li&gt;[ ] Método createInvoice implementado&lt;/li&gt;
&lt;li&gt;[ ] Método anotado com @PostMapping&lt;/li&gt;
&lt;li&gt;[ ] Parâmetro com &lt;a class="mentioned-user" href="https://dev.to/valid"&gt;@valid&lt;/a&gt; e @RequestBody&lt;/li&gt;
&lt;li&gt;[ ] Retorna ResponseEntity com status 201&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Testar Endpoint
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Aplicação inicia sem erros&lt;/li&gt;
&lt;li&gt;[ ] Requisição POST retorna 201 Created&lt;/li&gt;
&lt;li&gt;[ ] Resposta contém id gerado automaticamente&lt;/li&gt;
&lt;li&gt;[ ] Resposta contém createdAt gerado automaticamente&lt;/li&gt;
&lt;li&gt;[ ] Validações funcionam (testes com dados inválidos retornam 400)&lt;/li&gt;
&lt;li&gt;[ ] Logs aparecem no console&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Bônus (Opcional)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Enum InvoiceStatus criado&lt;/li&gt;
&lt;li&gt;[ ] Status aceita apenas valores do enum&lt;/li&gt;
&lt;li&gt;[ ] Endpoint GET /invoices implementado&lt;/li&gt;
&lt;li&gt;[ ] GET retorna lista de faturas criadas&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🐛 Problemas Comuns e Soluções
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Erro: "Unresolved reference: NotBlank"
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Causa:&lt;/strong&gt; Dependência de validação não foi adicionada&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Solução:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Verifique se adicionou &lt;code&gt;spring-boot-starter-validation&lt;/code&gt; no &lt;code&gt;build.gradle.kts&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Clique no ícone Gradle para recarregar as dependências&lt;/li&gt;
&lt;li&gt;Aguarde o download completar&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Erro: 404 Not Found ao fazer POST
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Causa:&lt;/strong&gt; Aplicação não está rodando ou URL incorreta&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Solução:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Verifique se a aplicação está rodando (console deve mostrar "Started InvoiceServiceApplication")&lt;/li&gt;
&lt;li&gt;Confirme a URL: &lt;code&gt;http://localhost:8080/invoices&lt;/code&gt; (sem &lt;code&gt;/api&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Verifique o método: deve ser &lt;strong&gt;POST&lt;/strong&gt;, não GET&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Erro: 400 Bad Request sem mensagem clara
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Causa:&lt;/strong&gt; JSON malformado&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Solução:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use um validador JSON online: &lt;a href="https://jsonlint.com/" rel="noopener noreferrer"&gt;jsonlint.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Verifique vírgulas, aspas e chaves&lt;/li&gt;
&lt;li&gt;Exemplo correto:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"customerId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CUST001"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;150.50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PENDING"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Erro: "HttpMessageNotReadableException"
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Causa:&lt;/strong&gt; Tipo de dado incorreto no JSON&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Solução:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;amount&lt;/code&gt; deve ser número: &lt;code&gt;150.50&lt;/code&gt; (sem aspas)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;customerId&lt;/code&gt; e &lt;code&gt;status&lt;/code&gt; devem ser texto: &lt;code&gt;"CUST001"&lt;/code&gt; (com aspas)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Validações não funcionam (aceita dados inválidos)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Causa:&lt;/strong&gt; Esqueceu &lt;code&gt;@Valid&lt;/code&gt; no parâmetro&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Solução:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Verifique se o método tem:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;createInvoice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@Valid&lt;/span&gt; &lt;span class="nd"&gt;@RequestBody&lt;/span&gt; &lt;span class="n"&gt;invoice&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Invoice&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                  &lt;span class="p"&gt;^^^^^^&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Resposta retorna 200 ao invés de 201
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Causa:&lt;/strong&gt; Esqueceu de definir o status HTTP&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Solução:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Retorne com:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ResponseEntity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpStatus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CREATED&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;invoice&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Não use apenas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ResponseEntity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;invoice&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Retorna 200&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🎓 Conceitos Importantes para Entender
&lt;/h2&gt;

&lt;h3&gt;
  
  
  O que é REST?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;REST&lt;/strong&gt; (Representational State Transfer) é um estilo de arquitetura para APIs web.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Princípios básicos:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Recursos são identificados por URLs (&lt;code&gt;/invoices&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Usam métodos HTTP padrão (GET, POST, PUT, DELETE)&lt;/li&gt;
&lt;li&gt;São stateless (cada requisição é independente)&lt;/li&gt;
&lt;li&gt;Respostas geralmente em JSON&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Analogia:&lt;/strong&gt; É como organizar uma biblioteca:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cada livro tem uma identificação única (URL)&lt;/li&gt;
&lt;li&gt;Ações padronizadas: pegar (GET), adicionar (POST), atualizar (PUT), remover (DELETE)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  O que é JSON?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;JSON&lt;/strong&gt; (JavaScript Object Notation) é um formato de texto para trocar dados.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"nome"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"João"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"idade"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"ativo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Por que usamos JSON?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fácil de ler para humanos&lt;/li&gt;
&lt;li&gt;Fácil de processar para computadores&lt;/li&gt;
&lt;li&gt;Padrão da indústria para APIs&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  HTTP Status Codes Importantes
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Código&lt;/th&gt;
&lt;th&gt;Nome&lt;/th&gt;
&lt;th&gt;Quando usar&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;200&lt;/td&gt;
&lt;td&gt;OK&lt;/td&gt;
&lt;td&gt;Requisição bem-sucedida (GET, PUT)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;201&lt;/td&gt;
&lt;td&gt;Created&lt;/td&gt;
&lt;td&gt;Recurso criado com sucesso (POST)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;400&lt;/td&gt;
&lt;td&gt;Bad Request&lt;/td&gt;
&lt;td&gt;Dados inválidos enviados&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;404&lt;/td&gt;
&lt;td&gt;Not Found&lt;/td&gt;
&lt;td&gt;Recurso não encontrado&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;500&lt;/td&gt;
&lt;td&gt;Internal Server Error&lt;/td&gt;
&lt;td&gt;Erro no servidor&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  O que é Serialização/Desserialização?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Serialização:&lt;/strong&gt; Converter objeto Java/Kotlin → JSON&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Desserialização:&lt;/strong&gt; Converter JSON → objeto Java/Kotlin&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;O Spring faz isso automaticamente usando a biblioteca Jackson!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Objeto Kotlin&lt;/span&gt;
&lt;span class="nc"&gt;Invoice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"123"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;customerId&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"CUST001"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.)&lt;/span&gt;

     &lt;span class="err"&gt;↓&lt;/span&gt; &lt;span class="nc"&gt;Serialização&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;automática&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// JSON&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s"&gt;"123"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;"customerId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s"&gt;"CUST001"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  O que é Validation?
&lt;/h3&gt;

&lt;p&gt;Garantir que os dados recebidos estão corretos antes de processar.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sem validação:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"customerId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;-100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"XPTO"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso causaria problemas! Com validação, rejeitamos automaticamente.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 Próximos Passos
&lt;/h2&gt;

&lt;p&gt;Depois de completar esta atividade, você deve:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Commitar no Git&lt;/strong&gt; - Salve seu progresso!
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"feat: adiciona endpoint POST /invoices e modelo Invoice"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Testar mais cenários&lt;/strong&gt; - Experimente diferentes dados&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mostrar para o alguém&lt;/strong&gt; - Demonstre funcionando!&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  💡 Dicas
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Teste sempre que mudar algo!&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Não acumule mudanças. Faça pequenas alterações e teste cada uma.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Leia as mensagens de erro com atenção&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Elas geralmente dizem exatamente qual é o problema. Procure a última linha da stack trace.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use logs para debug&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Quando algo não funciona como esperado, adicione &lt;code&gt;logger.info()&lt;/code&gt; para ver o que está acontecendo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Não decore, entenda!&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
É melhor entender o conceito do que decorar código. Se entender, saberá adaptar para outros cenários.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Postman é seu amigo&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Salve suas requisições no Postman. Você vai reutilizá-las muito!&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🎉 Parabéns
&lt;/h2&gt;

&lt;p&gt;Se você chegou até aqui e seu endpoint está funcionando, você acabou de:&lt;/p&gt;

&lt;p&gt;✅ Criar seu primeiro modelo de dados com validações&lt;br&gt;&lt;br&gt;
✅ Implementar seu primeiro endpoint REST POST&lt;br&gt;&lt;br&gt;
✅ Entender serialização JSON&lt;br&gt;&lt;br&gt;
✅ Testar APIs usando Postman/cURL&lt;br&gt;&lt;br&gt;
✅ Adicionar logs para debug&lt;/p&gt;

&lt;p&gt;Você está oficialmente criando APIs profissionais! 🚀&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Isso é incrível para alguém que há pouco tempo era estagiário!&lt;/strong&gt; Você já está produzindo código que roda em produção em muitas empresas.&lt;/p&gt;

&lt;p&gt;Continue assim! Cada linha de código é um passo a mais na sua jornada. 💪&lt;/p&gt;

</description>
      <category>java</category>
      <category>springboot</category>
      <category>tutorial</category>
      <category>api</category>
    </item>
    <item>
      <title>🚀 Como criar um novo projeto Spring Boot</title>
      <dc:creator>Thiago Matos</dc:creator>
      <pubDate>Mon, 29 Dec 2025 18:40:40 +0000</pubDate>
      <link>https://forem.com/thiagoematos/como-criar-um-novo-projeto-spring-boot-36pj</link>
      <guid>https://forem.com/thiagoematos/como-criar-um-novo-projeto-spring-boot-36pj</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Para:&lt;/strong&gt; Desenvolvedor Júnior Iniciante&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Objetivo:&lt;/strong&gt; Criar o projeto Spring Boot + Kotlin do serviço de faturas&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Tempo estimado:&lt;/strong&gt; 2-3 horas&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Nível de dificuldade:&lt;/strong&gt; ⭐⭐ Iniciante-Intermediário&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  📋 Pré-requisitos
&lt;/h2&gt;

&lt;p&gt;Antes de começar, verifique se você tem instalado:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Java 17 ou superior&lt;/strong&gt; - Execute no terminal: &lt;code&gt;java -version&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IntelliJ IDEA&lt;/strong&gt; (Community) - &lt;a href="https://www.jetbrains.com/idea/download/" rel="noopener noreferrer"&gt;Download aqui&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Git&lt;/strong&gt; - Execute: &lt;code&gt;git --version&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Opcional: Instalar Gradle Localmente
&lt;/h3&gt;

&lt;p&gt;O projeto Spring Boot vem com &lt;strong&gt;Gradle Wrapper&lt;/strong&gt; (arquivos &lt;code&gt;gradlew&lt;/code&gt; e &lt;code&gt;gradlew.bat&lt;/code&gt;) que baixa automaticamente a versão correta do Gradle. Porém, em alguns ambientes corporativos, é preferível usar uma instalação local do Gradle.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Para instalar Gradle no Linux:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Usando SDKMAN (recomendado)&lt;/span&gt;
curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"https://get.sdkman.io"&lt;/span&gt; | bash
&lt;span class="nb"&gt;source&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.sdkman/bin/sdkman-init.sh"&lt;/span&gt;
sdk &lt;span class="nb"&gt;install &lt;/span&gt;gradle 8.5

&lt;span class="c"&gt;# Verificar instalação&lt;/span&gt;
gradle &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Para instalar no macOS:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;gradle
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Quando usar Gradle local vs Wrapper?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Wrapper (padrão):&lt;/strong&gt; Garante que todos usem a mesma versão, recomendado para iniciantes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gradle local:&lt;/strong&gt; Útil em ambientes corporativos com restrições de rede ou quando você trabalha em múltiplos projetos&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  ⚙️ Configurar IntelliJ IDEA (Importante!)
&lt;/h2&gt;

&lt;p&gt;Antes de importar o projeto, vamos configurar corretamente o IntelliJ para evitar problemas.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configuração 1: Verificar/Configurar JDK
&lt;/h3&gt;

&lt;p&gt;O IntelliJ precisa saber qual versão do Java usar.&lt;/p&gt;

&lt;h4&gt;
  
  
  Passo a Passo
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Abra o &lt;strong&gt;IntelliJ IDEA&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Antes de abrir qualquer projeto&lt;/strong&gt;, vá em:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;File → Project Structure&lt;/strong&gt; (ou pressione &lt;code&gt;Ctrl+Alt+Shift+S&lt;/code&gt; no Linux/Windows, &lt;code&gt;⌘+;&lt;/code&gt; no Mac)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Na janela que abrir, clique em &lt;strong&gt;Project&lt;/strong&gt; (lado esquerdo)&lt;/li&gt;
&lt;li&gt;Configure:&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Campo&lt;/th&gt;
&lt;th&gt;Valor&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SDK&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Java 17 (ou superior)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Language Level&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;SDK default&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Se não aparecer Java 17 na lista:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clique no dropdown do &lt;strong&gt;SDK&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Selecione &lt;strong&gt;Add SDK → Download JDK...&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Escolha:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Vendor:&lt;/strong&gt; Amazon Corretto, Eclipse Temurin ou Oracle OpenJDK&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Version:&lt;/strong&gt; 17&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Clique em &lt;strong&gt;Download&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Clique em &lt;strong&gt;OK&lt;/strong&gt; para salvar&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Verificação:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# No terminal, verifique qual Java está configurado&lt;/span&gt;
java &lt;span class="nt"&gt;-version&lt;/span&gt;

&lt;span class="c"&gt;# Deve mostrar algo como:&lt;/span&gt;
&lt;span class="c"&gt;# openjdk version "17.0.x"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Configuração 2: Escolher entre Gradle Wrapper ou Gradle Local
&lt;/h3&gt;

&lt;p&gt;Você pode escolher usar o Gradle que vem com o projeto (wrapper) ou uma instalação local.&lt;/p&gt;

&lt;h4&gt;
  
  
  Opção A: Usar Gradle Wrapper (Recomendado para Iniciantes)
&lt;/h4&gt;

&lt;p&gt;Esta é a configuração padrão. O IntelliJ usa os arquivos &lt;code&gt;gradlew&lt;/code&gt; e &lt;code&gt;gradlew.bat&lt;/code&gt; do projeto.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No IntelliJ:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;File → Settings&lt;/strong&gt; (ou &lt;code&gt;Ctrl+Alt+S&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Navegue até: &lt;strong&gt;Build, Execution, Deployment → Build Tools → Gradle&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Configure:&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Campo&lt;/th&gt;
&lt;th&gt;Valor&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Use Gradle from&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;'wrapper' task in Gradle build script&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Gradle JVM&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Project SDK (Java 17)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Build and run using&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Gradle (Recomendado)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Run tests using&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Gradle (Recomendado)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Vantagens:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Garante que todos da equipe usam a mesma versão do Gradle&lt;/li&gt;
&lt;li&gt;✅ Não precisa instalar nada manualmente&lt;/li&gt;
&lt;li&gt;✅ Versão especificada no arquivo &lt;code&gt;gradle/wrapper/gradle-wrapper.properties&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Desvantagens:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❌ Precisa baixar o Gradle na primeira vez (pode demorar)&lt;/li&gt;
&lt;li&gt;❌ Pode ter problemas se houver firewall/proxy bloqueando o download&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Opção B: Usar Gradle Instalado Localmente
&lt;/h4&gt;

&lt;p&gt;Se sua empresa tem restrições ou você já tem Gradle instalado.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No IntelliJ:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;File → Settings&lt;/strong&gt; (ou &lt;code&gt;Ctrl+Alt+S&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Navegue até: &lt;strong&gt;Build, Execution, Deployment → Build Tools → Gradle&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Configure:&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Campo&lt;/th&gt;
&lt;th&gt;Valor&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Use Gradle from&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Specified location&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Gradle home&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Caminho da instalação (ex: &lt;code&gt;/usr/local/gradle-8.5&lt;/code&gt; ou &lt;code&gt;/home/usuario/.sdkman/candidates/gradle/8.5&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Gradle JVM&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Project SDK (Java 17)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Para descobrir o caminho do Gradle:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;which gradle
&lt;span class="c"&gt;# Mostra algo como: /usr/local/bin/gradle&lt;/span&gt;

&lt;span class="c"&gt;# Para ver o diretório home do Gradle:&lt;/span&gt;
gradle &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;span class="c"&gt;# Mostra Gradle home: /usr/local/gradle-8.5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;No macOS (Homebrew):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# O caminho geralmente é:&lt;/span&gt;
/usr/local/Cellar/gradle/8.5/libexec
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Com SDKMAN:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# O caminho geralmente é:&lt;/span&gt;
~/.sdkman/candidates/gradle/current
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Vantagens:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Mais rápido (não precisa baixar)&lt;/li&gt;
&lt;li&gt;✅ Funciona offline&lt;/li&gt;
&lt;li&gt;✅ Útil quando você trabalha em vários projetos&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Desvantagens:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❌ Precisa manter o Gradle atualizado manualmente&lt;/li&gt;
&lt;li&gt;❌ Pode ter incompatibilidade se a versão local for diferente da esperada pelo projeto&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Configuração 3: Configurar Gradle JVM Corretamente
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;IMPORTANTE:&lt;/strong&gt; O Gradle precisa rodar usando a JVM correta!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No IntelliJ → Settings → Build Tools → Gradle:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gradle JVM:&lt;/strong&gt; Selecione o &lt;strong&gt;Java 17&lt;/strong&gt; que você configurou anteriormente

&lt;ul&gt;
&lt;li&gt;Opção comum: &lt;code&gt;Project SDK (java version "17")...&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Evite:&lt;/strong&gt; Usar JVMs antigas (Java 8, Java 11) ou muito novas se o projeto especifica Java 17&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Se o Gradle JVM não aparecer:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Clique no dropdown &lt;strong&gt;Gradle JVM&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Selecione &lt;strong&gt;Add JDK...&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Navegue até a pasta onde o Java 17 está instalado:

&lt;ul&gt;
&lt;li&gt;Linux (SDKMAN): &lt;code&gt;~/.sdkman/candidates/java/17.x.x-tem&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Linux (apt): &lt;code&gt;/usr/lib/jvm/java-17-openjdk-amd64&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;macOS (Homebrew): &lt;code&gt;/usr/local/Cellar/openjdk@17/17.x.x&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Windows: &lt;code&gt;C:\Program Files\Java\jdk-17&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Verificar Configurações
&lt;/h3&gt;

&lt;p&gt;Depois de configurar, verifique se está tudo certo:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Abra o &lt;strong&gt;Terminal&lt;/strong&gt; do IntelliJ (aba na parte inferior)&lt;/li&gt;
&lt;li&gt;Execute:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Se usar Gradle Wrapper:&lt;/span&gt;
./gradlew &lt;span class="nt"&gt;--version&lt;/span&gt;

&lt;span class="c"&gt;# Se usar Gradle local:&lt;/span&gt;
gradle &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Resultado esperado:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;------------------------------------------------------------
Gradle 8.5
------------------------------------------------------------

Build time:   2023-11-15 13:36:12 UTC
Revision:     1234567890

Kotlin:       1.9.10
Groovy:       3.0.17
Ant:          Apache Ant(TM) version 1.10.13
JVM:          17.0.9 (Amazon.com Inc. 17.0.9+8-LTS)
OS:           Linux 5.15.0-91-generic amd64
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ &lt;strong&gt;Ótimo!&lt;/strong&gt; O campo &lt;code&gt;JVM:&lt;/code&gt; deve mostrar Java 17 (ou superior).&lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 Parte 1: Configurar Spring Initializr
&lt;/h2&gt;

&lt;h3&gt;
  
  
  O que é Spring Initializr?
&lt;/h3&gt;

&lt;p&gt;É uma ferramenta web que gera automaticamente a estrutura inicial de um projeto Spring Boot. Pense nele como um "criador de projetos automático" que já configura tudo para você começar a programar rapidamente.&lt;/p&gt;

&lt;h3&gt;
  
  
  Passo a Passo
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1.1 Acessar o Spring Initializr
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Abra seu navegador&lt;/li&gt;
&lt;li&gt;Acesse: &lt;a href="https://start.spring.io/" rel="noopener noreferrer"&gt;https://start.spring.io/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Você verá uma página com vários campos de configuração&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  1.2 Configurar o Projeto
&lt;/h4&gt;

&lt;p&gt;Preencha os campos &lt;strong&gt;EXATAMENTE&lt;/strong&gt; como descrito abaixo:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Campo&lt;/th&gt;
&lt;th&gt;Valor&lt;/th&gt;
&lt;th&gt;Por que?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Project&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Gradle - Kotlin&lt;/td&gt;
&lt;td&gt;Ferramenta para gerenciar dependências&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Language&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Kotlin&lt;/td&gt;
&lt;td&gt;A linguagem que vamos usar&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Spring Boot&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;3.2.x (mais recente)&lt;/td&gt;
&lt;td&gt;Versão do framework&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Group&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;com.invoice&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Identificador da sua empresa/projeto&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Artifact&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;invoice-service&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Nome do seu projeto&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Name&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;invoice-service&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Nome da aplicação&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Invoice Processing Service&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Descrição curta&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Package name&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;com.invoice&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deixe o padrão&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Packaging&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Jar&lt;/td&gt;
&lt;td&gt;Formato do pacote final&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Java&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;17&lt;/td&gt;
&lt;td&gt;Versão do Java&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  1.3 Adicionar Dependências
&lt;/h4&gt;

&lt;p&gt;Na seção &lt;strong&gt;Dependencies&lt;/strong&gt; (lado direito), clique em "ADD DEPENDENCIES" e adicione:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Spring Web&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;O que faz: Permite criar APIs REST (endpoints HTTP)&lt;/li&gt;
&lt;li&gt;Por que precisa: Vamos criar endpoints para gerenciar faturas&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Spring DevTools&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;O que faz: Reinicia automaticamente a aplicação quando você salva o código&lt;/li&gt;
&lt;li&gt;Por que precisa: Agiliza o desenvolvimento, você não precisa parar e iniciar manualmente&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Spring Boot Actuator&lt;/strong&gt; (opcional, mas recomendado)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;O que faz: Fornece endpoints de monitoramento (/health, /metrics)&lt;/li&gt;
&lt;li&gt;Por que precisa: Útil para verificar se a aplicação está rodando&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  1.4 Gerar o Projeto
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Clique no botão &lt;strong&gt;GENERATE&lt;/strong&gt; (no final da página)&lt;/li&gt;
&lt;li&gt;Um arquivo &lt;code&gt;.zip&lt;/code&gt; será baixado automaticamente&lt;/li&gt;
&lt;li&gt;Salve em uma pasta que você lembre (ex: &lt;code&gt;~/Documentos/projetos/&lt;/code&gt;)&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  1.5 Descompactar o Projeto
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;No Linux:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/Documentos/projetos/
unzip invoice-service.zip
&lt;span class="nb"&gt;cd &lt;/span&gt;invoice-service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora você tem a estrutura básica do projeto! 🎉&lt;/p&gt;




&lt;h2&gt;
  
  
  🏗️ Parte 2: Criar Estrutura de Pacotes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  O que são pacotes?
&lt;/h3&gt;

&lt;p&gt;Pacotes são pastas que organizam o código. É como organizar documentos em gavetas: cada tipo de arquivo vai em uma gaveta específica.&lt;/p&gt;

&lt;h3&gt;
  
  
  Passo a Passo
&lt;/h3&gt;

&lt;h4&gt;
  
  
  2.1 Importar no IntelliJ IDEA
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Abra o &lt;strong&gt;IntelliJ IDEA&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Clique em &lt;strong&gt;File → Open&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Navegue até a pasta &lt;code&gt;invoice-service&lt;/code&gt; e selecione-a&lt;/li&gt;
&lt;li&gt;Clique em &lt;strong&gt;OK&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Aguarde o IntelliJ baixar as dependências (veja a barra de progresso no canto inferior)&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;⏱️ &lt;strong&gt;Dica:&lt;/strong&gt; Primeira vez pode demorar 5-10 minutos baixando bibliotecas. É normal!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  2.2 Entender a Estrutura Atual
&lt;/h4&gt;

&lt;p&gt;Depois de abrir, você verá algo assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;invoice-service/
├── src/
│   ├── main/
│   │   ├── kotlin/
│   │   │   └── com/
│   │   │       └── invoice/
│   │   │           └── InvoiceServiceApplication.kt
│   │   └── resources/
│   │       └── application.properties
│   └── test/
├── build.gradle.kts
└── settings.gradle.kts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;O que cada pasta significa:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;src/main/kotlin/&lt;/code&gt; - Onde fica seu código fonte&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/main/resources/&lt;/code&gt; - Arquivos de configuração&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/test/&lt;/code&gt; - Onde ficam os testes&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;build.gradle.kts&lt;/code&gt; - Configurações do projeto e dependências&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  2.3 Criar os Pacotes
&lt;/h4&gt;

&lt;p&gt;Vamos criar 4 pacotes para organizar nosso código seguindo o padrão de "arquitetura em camadas":&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;No IntelliJ, navegue até: &lt;code&gt;src/main/kotlin/com/invoice/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Clique com botão direito em &lt;code&gt;invoice&lt;/code&gt; → &lt;strong&gt;New → Package&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Digite: &lt;code&gt;controller&lt;/code&gt; e pressione Enter&lt;/li&gt;
&lt;li&gt;Repita os passos 2-3 para criar:

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;service&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;model&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;repository&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Resultado final:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/main/kotlin/com/invoice/
├── controller/      (endpoints da API)
├── service/         (lógica de negócio)
├── model/           (classes de dados)
├── repository/      (acesso a dados)
└── InvoiceServiceApplication.kt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Por que essa estrutura?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Controller:&lt;/strong&gt; Recebe as requisições HTTP (ex: POST /invoices)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Service:&lt;/strong&gt; Contém as regras de negócio (ex: calcular juros)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model:&lt;/strong&gt; Define estruturas de dados (ex: classe Invoice)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Repository:&lt;/strong&gt; Conversa com banco de dados&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Essa separação é chamada de &lt;strong&gt;Separation of Concerns&lt;/strong&gt; - cada camada tem uma responsabilidade específica!&lt;/p&gt;




&lt;h2&gt;
  
  
  🔐 Parte 3: Configurar Repositórios Privados (Artifactory)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Por que usar repositórios privados?
&lt;/h3&gt;

&lt;p&gt;Em ambientes corporativos, muitas empresas usam &lt;strong&gt;repositórios privados&lt;/strong&gt; (como Artifactory ou Nexus) para:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Armazenar bibliotecas internas&lt;/strong&gt; - Código compartilhado entre equipes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cache de dependências&lt;/strong&gt; - Mais rápido que baixar direto da internet&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Segurança&lt;/strong&gt; - Controlar quais bibliotecas podem ser usadas&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trabalhar offline&lt;/strong&gt; - Dependências já estão no repositório da empresa&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Analogia:&lt;/strong&gt; É como ter uma biblioteca da empresa ao invés de sempre ir à biblioteca pública.&lt;/p&gt;

&lt;h3&gt;
  
  
  Passo a Passo
&lt;/h3&gt;

&lt;h4&gt;
  
  
  3.1 Criar arquivo gradle.properties
&lt;/h4&gt;

&lt;p&gt;Este arquivo guarda configurações globais do Gradle, incluindo URLs de repositórios.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Na raiz do projeto, crie o arquivo &lt;code&gt;gradle.properties&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Adicione as seguintes configurações:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="c"&gt;# URL base do Artifactory da empresa
&lt;/span&gt;&lt;span class="py"&gt;artifactoryUrl&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;https://artifactory.suaempresa.com/artifactory&lt;/span&gt;

&lt;span class="c"&gt;# Repositórios específicos
&lt;/span&gt;&lt;span class="py"&gt;artifactoryReleaseRepo&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;libs-release&lt;/span&gt;
&lt;span class="py"&gt;artifactorySnapshotRepo&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;libs-snapshot&lt;/span&gt;
&lt;span class="py"&gt;artifactoryPluginRepo&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;plugins-release&lt;/span&gt;

&lt;span class="c"&gt;# Credenciais (NÃO commitar em produção!)
# Em produção, use variáveis de ambiente
&lt;/span&gt;&lt;span class="py"&gt;artifactoryUser&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;seu.usuario&lt;/span&gt;
&lt;span class="py"&gt;artifactoryPassword&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;sua.senha&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;IMPORTANTE:&lt;/strong&gt; Nunca commite senhas reais no Git! Em produção, use variáveis de ambiente ou ferramentas como Vault.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Explicação de cada propriedade:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;artifactoryUrl&lt;/code&gt; - URL base do servidor Artifactory da empresa&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;artifactoryReleaseRepo&lt;/code&gt; - Nome do repositório de versões estáveis&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;artifactorySnapshotRepo&lt;/code&gt; - Nome do repositório de versões em desenvolvimento&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;artifactoryPluginRepo&lt;/code&gt; - Nome do repositório de plugins Gradle&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;artifactoryUser&lt;/code&gt; / &lt;code&gt;artifactoryPassword&lt;/code&gt; - Suas credenciais de acesso&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  3.2 Usar Variáveis de Ambiente (Recomendado para Produção)
&lt;/h4&gt;

&lt;p&gt;Para não expor senhas, use variáveis de ambiente:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No Linux/Mac, adicione no &lt;code&gt;~/.bashrc&lt;/code&gt; ou &lt;code&gt;~/.zshrc&lt;/code&gt;:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ARTIFACTORY_USER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"seu.usuario"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ARTIFACTORY_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"sua.senha"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;No gradle.properties:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;artifactoryUrl&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;https://artifactory.suaempresa.com/artifactory&lt;/span&gt;
&lt;span class="py"&gt;artifactoryReleaseRepo&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;libs-release&lt;/span&gt;
&lt;span class="py"&gt;artifactorySnapshotRepo&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;libs-snapshot&lt;/span&gt;
&lt;span class="py"&gt;artifactoryPluginRepo&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;plugins-release&lt;/span&gt;

&lt;span class="c"&gt;# Credenciais virão de variáveis de ambiente
&lt;/span&gt;&lt;span class="py"&gt;artifactoryUser&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;${ARTIFACTORY_USER}&lt;/span&gt;
&lt;span class="py"&gt;artifactoryPassword&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;${ARTIFACTORY_PASSWORD}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  3.3 Configurar settings.gradle.kts
&lt;/h4&gt;

&lt;p&gt;O arquivo &lt;code&gt;settings.gradle.kts&lt;/code&gt; controla de onde o Gradle baixa &lt;strong&gt;plugins&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Abra o arquivo &lt;code&gt;settings.gradle.kts&lt;/code&gt; e substitua o conteúdo por:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;pluginManagement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;repositories&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// 1. MavenLocal - cache local da sua máquina&lt;/span&gt;
        &lt;span class="nf"&gt;mavenLocal&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="c1"&gt;// 2. Artifactory privado - repositório da empresa&lt;/span&gt;
        &lt;span class="nf"&gt;maven&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"${settings.extra["&lt;/span&gt;&lt;span class="n"&gt;artifactoryUrl&lt;/span&gt;&lt;span class="s"&gt;"]}/${settings.extra["&lt;/span&gt;&lt;span class="n"&gt;artifactoryPluginRepo&lt;/span&gt;&lt;span class="s"&gt;"]}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;credentials&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;extra&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"artifactoryUser"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;
                &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;extra&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"artifactoryPassword"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// 3. Gradle Plugin Portal - repositório público oficial&lt;/span&gt;
        &lt;span class="nf"&gt;gradlePluginPortal&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="c1"&gt;// 4. Maven Central - repositório público (fallback)&lt;/span&gt;
        &lt;span class="nf"&gt;mavenCentral&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;rootProject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"invoice-service"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explicação linha por linha:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;pluginManagement { }&lt;/code&gt;&lt;/strong&gt; - Seção que configura onde buscar plugins do Gradle&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;mavenLocal()&lt;/code&gt;&lt;/strong&gt; - Primeiro procura no cache local (&lt;code&gt;~/.m2/repository&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;maven { url = ... }&lt;/code&gt;&lt;/strong&gt; - Configura repositório privado (Artifactory)

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;${settings.extra["artifactoryUrl"]}&lt;/code&gt; - Lê a URL do &lt;code&gt;gradle.properties&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;credentials { }&lt;/code&gt; - Adiciona usuário e senha para autenticação&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;gradlePluginPortal()&lt;/code&gt;&lt;/strong&gt; - Repositório oficial de plugins do Gradle&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;mavenCentral()&lt;/code&gt;&lt;/strong&gt; - Repositório público (caso não encontre nos anteriores)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Ordem de busca:&lt;/strong&gt; mavenLocal → Artifactory → Gradle Plugin Portal → Maven Central&lt;/p&gt;

&lt;h4&gt;
  
  
  3.4 Configurar build.gradle.kts
&lt;/h4&gt;

&lt;p&gt;O arquivo &lt;code&gt;build.gradle.kts&lt;/code&gt; controla de onde o Gradle baixa &lt;strong&gt;dependências da aplicação&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Abra o arquivo &lt;code&gt;build.gradle.kts&lt;/code&gt; e localize a seção &lt;code&gt;repositories&lt;/code&gt;. Substitua por:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;repositories&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// 1. MavenLocal - cache local&lt;/span&gt;
    &lt;span class="nf"&gt;mavenLocal&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;// 2. Artifactory - releases (bibliotecas estáveis)&lt;/span&gt;
    &lt;span class="nf"&gt;maven&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"${project.findProperty("&lt;/span&gt;&lt;span class="n"&gt;artifactoryUrl&lt;/span&gt;&lt;span class="s"&gt;")}/${project.findProperty("&lt;/span&gt;&lt;span class="n"&gt;artifactoryReleaseRepo&lt;/span&gt;&lt;span class="s"&gt;")}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;credentials&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"artifactoryUser"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;
            &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"artifactoryPassword"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// 3. Artifactory - snapshots (bibliotecas em desenvolvimento)&lt;/span&gt;
    &lt;span class="nf"&gt;maven&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"${project.findProperty("&lt;/span&gt;&lt;span class="n"&gt;artifactoryUrl&lt;/span&gt;&lt;span class="s"&gt;")}/${project.findProperty("&lt;/span&gt;&lt;span class="n"&gt;artifactorySnapshotRepo&lt;/span&gt;&lt;span class="s"&gt;")}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;credentials&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"artifactoryUser"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;
            &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"artifactoryPassword"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// 4. Maven Central - repositório público (fallback)&lt;/span&gt;
    &lt;span class="nf"&gt;mavenCentral&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explicação:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;mavenLocal()&lt;/code&gt;&lt;/strong&gt; - Busca primeiro no cache local&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Primeiro &lt;code&gt;maven { }&lt;/code&gt;&lt;/strong&gt; - Repositório de releases (versões 1.0.0, 2.3.1, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Segundo &lt;code&gt;maven { }&lt;/code&gt;&lt;/strong&gt; - Repositório de snapshots (versões 1.0.0-SNAPSHOT)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;mavenCentral()&lt;/code&gt;&lt;/strong&gt; - Repositório público como fallback&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Diferença entre Release e Snapshot:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Release&lt;/th&gt;
&lt;th&gt;Snapshot&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Versão estável (1.0.0)&lt;/td&gt;
&lt;td&gt;Versão em desenvolvimento (1.0.0-SNAPSHOT)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Não muda depois de publicada&lt;/td&gt;
&lt;td&gt;Pode ser atualizada a qualquer momento&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Para produção&lt;/td&gt;
&lt;td&gt;Para testes internos&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Conceitos Importantes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;MavenLocal:&lt;/strong&gt; Um cache local de dependências no seu computador. O Gradle verifica aqui primeiro para evitar downloads repetidos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Artifactory (ou Nexus):&lt;/strong&gt; Repositórios privados usados por empresas para gerenciar suas próprias bibliotecas e fazer cache de dependências públicas.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gradle Plugin Portal:&lt;/strong&gt; O repositório oficial para plugins do Gradle.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maven Central:&lt;/strong&gt; O maior repositório público de bibliotecas Java/Kotlin. É o "fallback" caso a dependência não seja encontrada nos repositórios anteriores.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;settings.gradle.kts&lt;/code&gt; vs &lt;code&gt;build.gradle.kts&lt;/code&gt;:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;settings.gradle.kts&lt;/code&gt;: Configura de onde o Gradle baixa &lt;strong&gt;plugins&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;build.gradle.kts&lt;/code&gt;: Configura de onde o Gradle baixa &lt;strong&gt;dependências da aplicação&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;&lt;code&gt;--refresh-dependencies&lt;/code&gt;:&lt;/strong&gt; Um comando Gradle que força o download de todas as dependências novamente, ignorando o cache local. Útil para garantir que você está usando as versões mais recentes.&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  3.5 Exemplo Completo do build.gradle.kts
&lt;/h4&gt;

&lt;p&gt;Aqui está como deve ficar o arquivo completo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.jetbrains.kotlin.gradle.tasks.KotlinCompile&lt;/span&gt;

&lt;span class="nf"&gt;plugins&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"org.springframework.boot"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="s"&gt;"3.2.0"&lt;/span&gt;
    &lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"io.spring.dependency-management"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="s"&gt;"1.1.4"&lt;/span&gt;
    &lt;span class="nf"&gt;kotlin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"jvm"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="s"&gt;"1.9.20"&lt;/span&gt;
    &lt;span class="nf"&gt;kotlin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"plugin.spring"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="s"&gt;"1.9.20"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;group&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"com.invoice"&lt;/span&gt;
&lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.0.1-SNAPSHOT"&lt;/span&gt;

&lt;span class="nf"&gt;java&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;sourceCompatibility&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;JavaVersion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;VERSION_17&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;repositories&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// 1. MavenLocal&lt;/span&gt;
    &lt;span class="nf"&gt;mavenLocal&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;// 2. Artifactory - releases&lt;/span&gt;
    &lt;span class="nf"&gt;maven&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"${project.findProperty("&lt;/span&gt;&lt;span class="n"&gt;artifactoryUrl&lt;/span&gt;&lt;span class="s"&gt;")}/${project.findProperty("&lt;/span&gt;&lt;span class="n"&gt;artifactoryReleaseRepo&lt;/span&gt;&lt;span class="s"&gt;")}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;credentials&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"artifactoryUser"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;
            &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"artifactoryPassword"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// 3. Artifactory - snapshots&lt;/span&gt;
    &lt;span class="nf"&gt;maven&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"${project.findProperty("&lt;/span&gt;&lt;span class="n"&gt;artifactoryUrl&lt;/span&gt;&lt;span class="s"&gt;")}/${project.findProperty("&lt;/span&gt;&lt;span class="n"&gt;artifactorySnapshotRepo&lt;/span&gt;&lt;span class="s"&gt;")}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;credentials&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"artifactoryUser"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;
            &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"artifactoryPassword"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// 4. Maven Central&lt;/span&gt;
    &lt;span class="nf"&gt;mavenCentral&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;dependencies&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;implementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"org.springframework.boot:spring-boot-starter-web"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;implementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"com.fasterxml.jackson.module:jackson-module-kotlin"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;implementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"org.jetbrains.kotlin:kotlin-reflect"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;developmentOnly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"org.springframework.boot:spring-boot-devtools"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;testImplementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"org.springframework.boot:spring-boot-starter-test"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;withType&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;KotlinCompile&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;kotlinOptions&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;freeCompilerArgs&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="s"&gt;"-Xjsr305=strict"&lt;/span&gt;
        &lt;span class="n"&gt;jvmTarget&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"17"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;withType&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Test&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;useJUnitPlatform&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  3.6 Testar a Configuração
&lt;/h4&gt;

&lt;p&gt;Agora vamos verificar se está tudo funcionando!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No terminal, execute:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./gradlew clean build &lt;span class="nt"&gt;--refresh-dependencies&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;O que esse comando faz:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;clean&lt;/code&gt; - Remove arquivos compilados antigos&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;build&lt;/code&gt; - Compila o projeto&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--refresh-dependencies&lt;/code&gt; - Força o download das dependências novamente&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Resultado esperado:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BUILD SUCCESSFUL in 45s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se aparecer erros, veja a seção de troubleshooting mais abaixo.&lt;/p&gt;

&lt;h4&gt;
  
  
  3.7 Verificar de Onde as Dependências Foram Baixadas
&lt;/h4&gt;

&lt;p&gt;Para ver de qual repositório cada dependência veio:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./gradlew dependencies &lt;span class="nt"&gt;--configuration&lt;/span&gt; runtimeClasspath
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Você verá algo assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;com.fasterxml.jackson.module:jackson-module-kotlin:2.15.3
   -&amp;gt; Downloaded from: https://artifactory.suaempresa.com/artifactory/libs-release/...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ⚙️ Parte 4: Configurar application.yml
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Por que configurar?
&lt;/h3&gt;

&lt;p&gt;O arquivo de configuração define como sua aplicação se comporta: em que porta roda, nome da aplicação, configurações de banco, etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  Passo a Passo
&lt;/h3&gt;

&lt;h4&gt;
  
  
  3.1 Converter .properties para .yml
&lt;/h4&gt;

&lt;p&gt;O Spring Initializr cria um arquivo &lt;code&gt;application.properties&lt;/code&gt;, mas vamos usar &lt;code&gt;.yml&lt;/code&gt; que é mais organizado.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Localize: &lt;code&gt;src/main/resources/application.properties&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Clique com botão direito → &lt;strong&gt;Refactor → Rename&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Renomeie para: &lt;code&gt;application.yml&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  3.2 Adicionar Configurações Básicas
&lt;/h4&gt;

&lt;p&gt;Abra o arquivo &lt;code&gt;application.yml&lt;/code&gt; e adicione:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;

&lt;span class="na"&gt;spring&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;application&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;invoice-service&lt;/span&gt;

&lt;span class="na"&gt;logging&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;level&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;com.invoice&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;DEBUG&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;O que cada configuração faz:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;server.port: 8080&lt;/code&gt; - A aplicação rodará em &lt;a href="http://localhost:8080" rel="noopener noreferrer"&gt;http://localhost:8080&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;spring.application.name&lt;/code&gt; - Nome da aplicação (útil em logs)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;logging.level&lt;/code&gt; - Mostra logs detalhados do seu código (útil para debug)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🚀 Parte 5: Executar a Aplicação
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Momento da Verdade
&lt;/h3&gt;

&lt;p&gt;Vamos subir a aplicação pela primeira vez. 😊&lt;/p&gt;

&lt;h3&gt;
  
  
  Passo a Passo
&lt;/h3&gt;

&lt;h4&gt;
  
  
  4.1 Executar pelo IntelliJ
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Abra o arquivo &lt;code&gt;InvoiceServiceApplication.kt&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Você verá um código assim:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;com.invoice&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.boot.autoconfigure.SpringBootApplication&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.boot.runApplication&lt;/span&gt;

&lt;span class="nd"&gt;@SpringBootApplication&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InvoiceServiceApplication&lt;/span&gt;

&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;runApplication&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;InvoiceServiceApplication&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Clique no ícone ▶️ verde ao lado de &lt;code&gt;fun main&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Selecione &lt;strong&gt;Run 'InvoiceServiceApplication'&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  4.2 Verificar se Funcionou
&lt;/h4&gt;

&lt;p&gt;Observe o console (painel inferior do IntelliJ). Você deve ver:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v3.2.x)

...
Started InvoiceServiceApplication in 2.345 seconds
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ &lt;strong&gt;Se você viu isso, PARABÉNS!&lt;/strong&gt; Sua aplicação está rodando! 🎉&lt;/p&gt;

&lt;h4&gt;
  
  
  4.3 Testar no Navegador
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Abra seu navegador&lt;/li&gt;
&lt;li&gt;Acesse: &lt;a href="http://localhost:8080" rel="noopener noreferrer"&gt;http://localhost:8080&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Você verá uma página de erro "Whitelabel Error Page"&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Isso está CORRETO!&lt;/strong&gt; 😎&lt;/p&gt;

&lt;p&gt;A página de erro aparece porque ainda não criamos nenhum endpoint. O importante é que a aplicação está respondendo!&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ Critérios de Aceite - Checklist Final
&lt;/h2&gt;

&lt;p&gt;Marque cada item que você completou:&lt;/p&gt;

&lt;h3&gt;
  
  
  Configurar IntelliJ IDEA
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;[ ] IntelliJ IDEA instalado&lt;/li&gt;
&lt;li&gt;[ ] JDK 17 configurado no IntelliJ (Project Structure → SDK)&lt;/li&gt;
&lt;li&gt;[ ] Gradle configurado (Wrapper ou Local)&lt;/li&gt;
&lt;li&gt;[ ] Gradle JVM configurado para usar Java 17&lt;/li&gt;
&lt;li&gt;[ ] Comando &lt;code&gt;./gradlew --version&lt;/code&gt; ou &lt;code&gt;gradle --version&lt;/code&gt; executado com sucesso&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Configurar Spring Initializr
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Projeto gerado com Java 17+&lt;/li&gt;
&lt;li&gt;[ ] Linguagem: Kotlin&lt;/li&gt;
&lt;li&gt;[ ] Dependências: Spring Web e Spring DevTools&lt;/li&gt;
&lt;li&gt;[ ] Projeto baixado e descompactado&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Criar Estrutura de Pacotes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Projeto importado no IntelliJ&lt;/li&gt;
&lt;li&gt;[ ] Pacote &lt;code&gt;controller&lt;/code&gt; criado&lt;/li&gt;
&lt;li&gt;[ ] Pacote &lt;code&gt;service&lt;/code&gt; criado&lt;/li&gt;
&lt;li&gt;[ ] Pacote &lt;code&gt;model&lt;/code&gt; criado&lt;/li&gt;
&lt;li&gt;[ ] Pacote &lt;code&gt;repository&lt;/code&gt; criado&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Configurar Repositórios Privados (Artifactory)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Arquivo &lt;code&gt;gradle.properties&lt;/code&gt; criado na raiz do projeto&lt;/li&gt;
&lt;li&gt;[ ] URL do Artifactory configurada&lt;/li&gt;
&lt;li&gt;[ ] Credenciais configuradas (ou variáveis de ambiente)&lt;/li&gt;
&lt;li&gt;[ ] &lt;code&gt;settings.gradle.kts&lt;/code&gt; atualizado com repositórios de plugins&lt;/li&gt;
&lt;li&gt;[ ] &lt;code&gt;build.gradle.kts&lt;/code&gt; atualizado com repositórios de dependências&lt;/li&gt;
&lt;li&gt;[ ] Comando &lt;code&gt;./gradlew clean build&lt;/code&gt; executado com sucesso&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Configurar application.yml
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Arquivo &lt;code&gt;.properties&lt;/code&gt; renomeado para &lt;code&gt;.yml&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;[ ] Porta configurada: 8080&lt;/li&gt;
&lt;li&gt;[ ] Nome da aplicação definido&lt;/li&gt;
&lt;li&gt;[ ] Nível de log configurado&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Executar Aplicação
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Aplicação compila sem erros&lt;/li&gt;
&lt;li&gt;[ ] Console mostra "Started InvoiceServiceApplication"&lt;/li&gt;
&lt;li&gt;[ ] &lt;a href="http://localhost:8080" rel="noopener noreferrer"&gt;http://localhost:8080&lt;/a&gt; retorna página de erro do Spring (esperado!)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🐛 Problemas Comuns e Soluções
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Erro: "Java version mismatch"
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Causa:&lt;/strong&gt; Versão errada do Java configurada&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Solução:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;No IntelliJ: &lt;strong&gt;File → Project Structure → Project&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Configure &lt;strong&gt;SDK&lt;/strong&gt; para Java 17&lt;/li&gt;
&lt;li&gt;Em &lt;strong&gt;Language Level&lt;/strong&gt;, selecione &lt;strong&gt;17 - Sealed types, always-strict floating-point...&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Erro: "Port 8080 already in use"
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Causa:&lt;/strong&gt; Outra aplicação já está usando a porta 8080&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Solução:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;No terminal: &lt;code&gt;lsof -i :8080&lt;/code&gt; (veja qual processo está usando)&lt;/li&gt;
&lt;li&gt;Mate o processo ou mude a porta no &lt;code&gt;application.yml&lt;/code&gt; para &lt;code&gt;8081&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Dependências não baixam
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Causa:&lt;/strong&gt; Problema de rede ou cache do Gradle&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Solução:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;No terminal, dentro da pasta do projeto:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./gradlew clean build &lt;span class="nt"&gt;--refresh-dependencies&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  IntelliJ não reconhece código Kotlin
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Causa:&lt;/strong&gt; Plugin Kotlin não instalado&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Solução:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;File → Settings → Plugins&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Procure por "Kotlin"&lt;/li&gt;
&lt;li&gt;Clique em &lt;strong&gt;Install&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Reinicie o IntelliJ&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Erro: "Unsupported class file major version XX"
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Causa:&lt;/strong&gt; Versão do Java incompatível (código compilado com Java mais novo que o configurado)&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Solução:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Verifique qual Java o projeto precisa: abra &lt;code&gt;build.gradle.kts&lt;/code&gt; e procure &lt;code&gt;sourceCompatibility&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;No IntelliJ: &lt;strong&gt;File → Project Structure → Project&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Configure &lt;strong&gt;SDK&lt;/strong&gt; para a versão correta (Java 17+)&lt;/li&gt;
&lt;li&gt;No IntelliJ: &lt;strong&gt;File → Settings → Build Tools → Gradle&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Configure &lt;strong&gt;Gradle JVM&lt;/strong&gt; para a mesma versão&lt;/li&gt;
&lt;li&gt;Execute: &lt;code&gt;./gradlew clean build&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Erro: "Could not determine Java version"
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Causa:&lt;/strong&gt; Gradle JVM não configurado ou apontando para local inválido&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Solução:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;File → Settings → Build Tools → Gradle&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Em &lt;strong&gt;Gradle JVM&lt;/strong&gt;, selecione um JDK válido (Java 17+)&lt;/li&gt;
&lt;li&gt;Se não aparecer nenhum JDK:

&lt;ul&gt;
&lt;li&gt;Clique em &lt;strong&gt;Add JDK...&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Navegue até a pasta de instalação do Java&lt;/li&gt;
&lt;li&gt;No Linux: &lt;code&gt;/usr/lib/jvm/java-17-openjdk-amd64&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Clique em &lt;strong&gt;Apply&lt;/strong&gt; e depois &lt;strong&gt;OK&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Erro: "Gradle version X.X is required. Current version is Y.Y"
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Causa:&lt;/strong&gt; Versão do Gradle instalada não é compatível com o projeto&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Solução:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Se usando Gradle Local:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Instale a versão correta: &lt;code&gt;sdk install gradle 8.5&lt;/code&gt; (usando SDKMAN)&lt;/li&gt;
&lt;li&gt;Atualize o caminho no IntelliJ: &lt;strong&gt;Settings → Gradle → Gradle home&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Se usando Wrapper (recomendado):&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Settings → Gradle → Use Gradle from&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Selecione: &lt;code&gt;'wrapper' task in Gradle build script&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;O wrapper baixará automaticamente a versão correta&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Erro: "Could not resolve all dependencies" (Artifactory)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Causa:&lt;/strong&gt; Credenciais incorretas ou URL do Artifactory errada&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Solução:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Verifique se a URL no &lt;code&gt;gradle.properties&lt;/code&gt; está correta&lt;/li&gt;
&lt;li&gt;Teste acessar a URL no navegador: &lt;code&gt;https://artifactory.suaempresa.com/artifactory&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Confirme usuário e senha&lt;/li&gt;
&lt;li&gt;Se usar variáveis de ambiente, execute: &lt;code&gt;echo $ARTIFACTORY_USER&lt;/code&gt; para verificar&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Erro: "HTTP 401 Unauthorized" (Artifactory)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Causa:&lt;/strong&gt; Senha expirada ou usuário sem permissão&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Solução:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Verificar suas permissões no Artifactory&lt;/li&gt;
&lt;li&gt;Tente resetar sua senha no portal do Artifactory&lt;/li&gt;
&lt;li&gt;Verifique se não há espaços extras no &lt;code&gt;gradle.properties&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Erro: "UnknownHostException" (Artifactory)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Causa:&lt;/strong&gt; Você está fora da rede da empresa ou VPN desconectada&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Solução:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Conecte-se à VPN da empresa&lt;/li&gt;
&lt;li&gt;Verifique conexão: &lt;code&gt;ping artifactory.suaempresa.com&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Se estiver offline, comente temporariamente os repositórios privados e use só &lt;code&gt;mavenCentral()&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  🎓 Conceitos Importantes para Entender
&lt;/h2&gt;

&lt;h3&gt;
  
  
  O que é Spring Boot?
&lt;/h3&gt;

&lt;p&gt;É um framework (conjunto de ferramentas) que facilita criar aplicações Java/Kotlin. Ele já vem com muita coisa pronta, então você foca na lógica do seu negócio.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Analogia:&lt;/strong&gt; É como comprar um carro pronto ao invés de construir cada peça do zero.&lt;/p&gt;

&lt;h3&gt;
  
  
  O que é API REST?
&lt;/h3&gt;

&lt;p&gt;É uma forma de aplicações conversarem entre si usando HTTP (mesmo protocolo do navegador). Você cria "endpoints" (URLs) que recebem e envolvam dados.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exemplo:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;POST /invoices&lt;/code&gt; - Cria uma nova fatura&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GET /invoices/123&lt;/code&gt; - Busca a fatura de ID 123&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  O que é Gradle?
&lt;/h3&gt;

&lt;p&gt;É uma ferramenta que:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Baixa bibliotecas (dependências) que seu projeto precisa&lt;/li&gt;
&lt;li&gt;Compila seu código&lt;/li&gt;
&lt;li&gt;Empacota tudo em um arquivo &lt;code&gt;.jar&lt;/code&gt; executável&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Analogia:&lt;/strong&gt; É como um assistente que busca todas as ferramentas que você precisa e organiza tudo.&lt;/p&gt;

&lt;h3&gt;
  
  
  O que é Artifactory?
&lt;/h3&gt;

&lt;p&gt;É um &lt;strong&gt;gerenciador de repositórios de artefatos&lt;/strong&gt; usado em empresas. Funciona como um "armazém central" que:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Guarda bibliotecas internas&lt;/strong&gt; - Código criado pela sua empresa&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Faz cache de bibliotecas públicas&lt;/strong&gt; - Copia do Maven Central para a rede da empresa&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Controla versões&lt;/strong&gt; - Sabe exatamente qual versão de cada biblioteca está sendo usada&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Analogia:&lt;/strong&gt; É como um armazém da Amazon, mas só para código da sua empresa.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Outros nomes:&lt;/strong&gt; Nexus, Azure Artifacts, GitHub Packages (fazem a mesma coisa)&lt;/p&gt;

&lt;h3&gt;
  
  
  O que é Maven Local?
&lt;/h3&gt;

&lt;p&gt;É uma pasta no seu computador (&lt;code&gt;~/.m2/repository&lt;/code&gt;) que funciona como &lt;strong&gt;cache local&lt;/strong&gt; de bibliotecas já baixadas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Por que usar:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Evita baixar a mesma biblioteca várias vezes&lt;/li&gt;
&lt;li&gt;Funciona offline se a biblioteca já foi baixada antes&lt;/li&gt;
&lt;li&gt;Acelera o build (compilar sem internet)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Analogia:&lt;/strong&gt; É como ter uma cópia local de livros que você já pegou emprestado antes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Diferença: Plugins vs Dependências
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Plugins (&lt;code&gt;settings.gradle.kts&lt;/code&gt;)&lt;/th&gt;
&lt;th&gt;Dependências (&lt;code&gt;build.gradle.kts&lt;/code&gt;)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ferramentas que ajudam a &lt;strong&gt;construir&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Bibliotecas que o código &lt;strong&gt;usa&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Exemplos: plugin do Kotlin, Spring Boot&lt;/td&gt;
&lt;td&gt;Exemplos: Jackson, Spring Web&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Baixados durante configuração do Gradle&lt;/td&gt;
&lt;td&gt;Baixados durante compilação&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Configura como o projeto é compilado&lt;/td&gt;
&lt;td&gt;Código que roda na aplicação&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  💡 Dicas
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Não copie e cole código sem entender!&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Leia cada linha, tente compreender. Se não entender algo, pergunte!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Erros são normais&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Você vai ver MUITAS mensagens de erro. Aprenda a lê-las com calma. Geralmente a última linha diz o problema.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Documente suas dúvidas&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Anote o que não entendeu para perguntar depois. Isso mostra proatividade!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Commits frequentes&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Quando algo funcionar, salve no Git. É como criar pontos de restore de um jogo.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🎉 Parabéns
&lt;/h2&gt;

&lt;p&gt;Se você chegou até aqui e sua aplicação está rodando, você acabou de:&lt;/p&gt;

&lt;p&gt;✅ Criar seu primeiro projeto Spring Boot&lt;br&gt;&lt;br&gt;
✅ Entender estrutura de pacotes&lt;br&gt;&lt;br&gt;
✅ Configurar uma aplicação&lt;br&gt;&lt;br&gt;
✅ Executar um servidor web&lt;/p&gt;

&lt;p&gt;Isso é MUITA coisa para um dia de trabalho! 🚀&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lembre-se:&lt;/strong&gt; Todo desenvolvedor sênior já esteve no seu lugar. A diferença é que eles persistiram e continuaram aprendendo. Você está no caminho certo! 💪&lt;/p&gt;

</description>
      <category>java</category>
      <category>kotlin</category>
      <category>springboot</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Git: Update remote url in your local machine</title>
      <dc:creator>Thiago Matos</dc:creator>
      <pubDate>Sat, 17 Aug 2024 19:36:20 +0000</pubDate>
      <link>https://forem.com/thiagoematos/git-update-remote-url-in-your-local-machine-1k60</link>
      <guid>https://forem.com/thiagoematos/git-update-remote-url-in-your-local-machine-1k60</guid>
      <description>&lt;p&gt;&lt;strong&gt;Given&lt;/strong&gt;&lt;br&gt;
You've cloned a remote git repository, for example:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git@gitlab.com:project-name.git&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When&lt;/strong&gt;&lt;br&gt;
That repository changes its remote url to, for example:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git@gitlab.com:another-project-name.git&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Then&lt;/strong&gt;&lt;br&gt;
I must update the remote url in your local machine using this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git remote set-url origin git@gitlab.com:another-project-name.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then, confirm the change was applied:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git remote -v
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;If you are using IntelliJ Idea, then you can access:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Menu&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Git&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Manage Remotes...&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And make the update in this window:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn9tp26msi2z6xj3bngd1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn9tp26msi2z6xj3bngd1.png" alt="Window to update the git repository remote url" width="544" height="244"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>git</category>
      <category>cli</category>
      <category>intellij</category>
      <category>repository</category>
    </item>
    <item>
      <title>The Logging, The AOP and The Clean Code</title>
      <dc:creator>Thiago Matos</dc:creator>
      <pubDate>Fri, 09 Aug 2024 22:31:16 +0000</pubDate>
      <link>https://forem.com/thiagoematos/the-logging-the-aop-and-the-clean-code-4od1</link>
      <guid>https://forem.com/thiagoematos/the-logging-the-aop-and-the-clean-code-4od1</guid>
      <description>&lt;p&gt;Logging is an essential practice that helps developers &lt;strong&gt;understand the flow&lt;/strong&gt; of their applications and &lt;strong&gt;diagnose issues&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Understand the flow:&lt;/strong&gt; It shows you how your application is behaving over time, making it easier to understand and improve.&lt;br&gt;
&lt;strong&gt;Diagnose issues:&lt;/strong&gt; It keeps a record of what your application is doing.&lt;/p&gt;

&lt;p&gt;It is like having a &lt;strong&gt;notebook&lt;/strong&gt; where you write down every step to build a robot. After you build, if the robot makes a mistake, you can look back at your notes to see what went wrong and fix it.&lt;/p&gt;

&lt;p&gt;One clean-code way to implement logging in a Spring Boot application is through Aspect-Oriented Programming (AOP).&lt;/p&gt;
&lt;h2&gt;
  
  
  What is Aspect-Oriented Programming (AOP)?
&lt;/h2&gt;

&lt;p&gt;AOP is a programming paradigm that aims to &lt;strong&gt;increase modularity&lt;/strong&gt; by allowing the separation of aspects of a program that affect multiple components (&lt;strong&gt;cross-cutting concerns&lt;/strong&gt;). AOP allows you to encapsulate these concerns into reusable modules called "&lt;strong&gt;aspects&lt;/strong&gt;".&lt;/p&gt;

&lt;p&gt;Imagine you are responsible to log what the program is doing. Without AOP, you would have to write the same log pattern in many different places. This makes your code &lt;strong&gt;hard to manage&lt;/strong&gt;. With AOP, you would create a special module called aspect to handle the logs and then you would tell your program to use the aspect.This makes your code &lt;strong&gt;clean and organized&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this article, I will show a practical example of AOP, implementing a custom annotation to log method inputs and outputs at a class level. After that, you can use this annotation in many places of your code.&lt;/p&gt;
&lt;h2&gt;
  
  
  Learning AOP with an example
&lt;/h2&gt;

&lt;p&gt;First, let's see a class without AOP.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.stereotype.Service&lt;/span&gt;

&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ExampleWithoutAop&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;methodA&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;parameterA&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;parameterB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;
    &lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ExampleWithoutAop#methodA START - parameterA=$parameterA, parameterB=$parameterB"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"$parameterA $parameterB"&lt;/span&gt;
        &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ExampleWithoutAop#methodA END - result=$result"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;methodB&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;throwsException&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ExampleWithoutAop#methodB START - throwsException=$throwsException"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;throwsException&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;message&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"error message"&lt;/span&gt;
            &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ExampleWithoutAop#methodB ERROR - message=$message"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nc"&gt;RuntimeException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ExampleWithoutAop#methodB END"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add this runner in the main class of Spring Boot:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.boot.ApplicationRunner&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.boot.autoconfigure.SpringBootApplication&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.boot.runApplication&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.context.annotation.Bean&lt;/span&gt;

&lt;span class="nd"&gt;@SpringBootApplication&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DemoApplication&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Bean&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;runner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exampleWithoutAop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ExampleWithoutAop&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;ApplicationRunner&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ApplicationRunner&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;exampleWithoutAop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;methodA&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;exampleWithoutAop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;methodB&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;exampleWithoutAop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;methodB&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;runApplication&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;DemoApplication&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is the output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ExampleWithoutAop#methodA START - parameterA=Hello, parameterB=42
ExampleWithoutAop#methodA END - result=Hello 42
ExampleWithoutAop#methodB START - throwsException=false
ExampleWithoutAop#methodB END
ExampleWithoutAop#methodB START - throwsException=true
ExampleWithoutAop#methodB ERROR - message=error message
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Let's clean the code using AOP and Custom Annotation
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Step 1: Define the custom annotation
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Target&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AnnotationTarget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CLASS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@Retention&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AnnotationRetention&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;RUNTIME&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;annotation&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LogExecution&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Add the following dependency in your &lt;strong&gt;build.gradle.kts&lt;/strong&gt;:
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;implementation("org.springframework.boot:spring-boot-starter-aop")&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Enable the AOP for Spring Boot by adding this annotation in your &lt;strong&gt;DemoApplication&lt;/strong&gt; class:
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;@EnableAspectJAutoProxy&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Here is how your main class will look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.boot.autoconfigure.SpringBootApplication&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.context.annotation.EnableAspectJAutoProxy&lt;/span&gt;

&lt;span class="nd"&gt;@EnableAspectJAutoProxy&lt;/span&gt;
&lt;span class="nd"&gt;@SpringBootApplication&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DemoApplication&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4: Create the Aspect
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.aspectj.lang.ProceedingJoinPoint&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.aspectj.lang.annotation.Around&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.aspectj.lang.annotation.Aspect&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.aspectj.lang.annotation.Pointcut&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.aspectj.lang.reflect.MethodSignature&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.stereotype.Component&lt;/span&gt;

&lt;span class="c1"&gt;// Define this class as an Aspect&lt;/span&gt;
&lt;span class="nd"&gt;@Aspect&lt;/span&gt;
&lt;span class="c1"&gt;// Makes this class a Spring-managed bean,&lt;/span&gt;
&lt;span class="c1"&gt;// allowing Spring to discover and manage it&lt;/span&gt;
&lt;span class="nd"&gt;@Component&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LoggingAspect&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// An expression that selects the join points&lt;/span&gt;
    &lt;span class="c1"&gt;// where additional code (advice) will be applied.&lt;/span&gt;
    &lt;span class="c1"&gt;// It selects all methods&lt;/span&gt;
    &lt;span class="c1"&gt;// within classes annotated with @LogExecution.&lt;/span&gt;
    &lt;span class="nd"&gt;@Pointcut&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"within(@com.example.demo.LogExecution *)"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;logExecutionMethods&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="c1"&gt;// Define an "Around" Advice (additional code),&lt;/span&gt;
    &lt;span class="c1"&gt;// which surrounds (around) the execution of&lt;/span&gt;
    &lt;span class="c1"&gt;// the method selected by the Pointcut&lt;/span&gt;
    &lt;span class="nd"&gt;@Around&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"logExecutionMethods()"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;logMethodExecution&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;joinPoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ProceedingJoinPoint&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="c1"&gt;// Get the method signature from the join point&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;methodSignature&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;joinPoint&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;signature&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nc"&gt;MethodSignature&lt;/span&gt;

        &lt;span class="c1"&gt;// Get the name of the class where the method is located&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;className&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;methodSignature&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;declaringType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;simpleName&lt;/span&gt;

        &lt;span class="c1"&gt;// Get the name of the method&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;methodName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;methodSignature&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;

        &lt;span class="c1"&gt;// Get the names of the method's parameters&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;inputNames&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;methodSignature&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parameterNames&lt;/span&gt;

        &lt;span class="c1"&gt;// Get the values of the arguments passed to the method&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;inputValues&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;joinPoint&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;

        &lt;span class="c1"&gt;// Combine the parameter names and values into a formatted string&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;inputs&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;inputNames&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inputValues&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;joinToString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;", "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="s"&gt;"${it.first}=${it.second}"&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// Create a tag that combines the class name and method name&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;tag&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"$className#$methodName"&lt;/span&gt;

        &lt;span class="c1"&gt;// Print a log message indicating&lt;/span&gt;
        &lt;span class="c1"&gt;// the starting of the method execution,&lt;/span&gt;
        &lt;span class="c1"&gt;// including the input parameters&lt;/span&gt;
        &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"$tag START${log(inputs)}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;// Try to execute the original method&lt;/span&gt;
        &lt;span class="c1"&gt;// and store the output value&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;output&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;joinPoint&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;proceed&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Throwable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// If an exception occurs,&lt;/span&gt;
            &lt;span class="c1"&gt;// print an error message to the log&lt;/span&gt;
            &lt;span class="c1"&gt;// and rethrow the exception&lt;/span&gt;
            &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"$tag ERROR - message=${ex.message}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// Print a log message indicating&lt;/span&gt;
        &lt;span class="c1"&gt;// the ending of the method execution,&lt;/span&gt;
        &lt;span class="c1"&gt;// including the return value&lt;/span&gt;
        &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"$tag END${log(output)}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;// Return the output value of the original method&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Helper function to format&lt;/span&gt;
    &lt;span class="c1"&gt;// the input parameters for logging&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isEmpty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;
      &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="s"&gt;" - $inputs"&lt;/span&gt;

    &lt;span class="c1"&gt;// Helper function to format&lt;/span&gt;
    &lt;span class="c1"&gt;// the output value for logging&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;?)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
      &lt;span class="n"&gt;output&lt;/span&gt;
        &lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;let&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;" - result=$it"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;?:&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5: Replace &lt;em&gt;ExampleWithoutAop&lt;/em&gt; by its new version using AOP with custom annotation:
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.stereotype.Service&lt;/span&gt;

&lt;span class="nd"&gt;@LogExecution&lt;/span&gt;
&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ExampleWithAop&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;methodA&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;parameterA&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;parameterB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;
    &lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"$parameterA $parameterB"&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;methodB&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;throwsException&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;throwsException&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nc"&gt;RuntimeException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"error message"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Execute the Spring Boot application and see the same output. But now, notice that the code of ExampleService is much more clean allowing you to focus on your business rules.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;By creating a custom annotation and an aspect, we can easily log into any class of our application. This approach not only helps in debugging but also keeps our code clean and modular.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Benefits of Using AOP:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It allows &lt;strong&gt;separation&lt;/strong&gt; of cross-cutting concerns, like logging, from the main business logic;&lt;/li&gt;
&lt;li&gt;It allows &lt;strong&gt;reusing&lt;/strong&gt; across different parts of your application, reducing code duplication;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Single Responsibility Principle:&lt;/strong&gt; By separating logging and other cross-cutting concerns into aspects, each class has only one reason to change;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open/Closed Principle:&lt;/strong&gt; It allows you to add new behaviors (like logging) without modifying existing code, making your classes open for extension but closed for modification.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>log</category>
      <category>aop</category>
      <category>annotation</category>
      <category>springboot</category>
    </item>
    <item>
      <title>Running Tests in GitLab CI: From Zero to Pipeline</title>
      <dc:creator>Thiago Matos</dc:creator>
      <pubDate>Thu, 11 Jul 2024 22:26:06 +0000</pubDate>
      <link>https://forem.com/thiagoematos/running-tests-in-gitlab-ci-from-zero-to-pipeline-5ece</link>
      <guid>https://forem.com/thiagoematos/running-tests-in-gitlab-ci-from-zero-to-pipeline-5ece</guid>
      <description>&lt;p&gt;Continuous Integration (CI) is an essential practice in modern software development. It ensures that code changes are automatically tested, leading to faster and more reliable software releases. In this article, we'll walk through the process of setting up a Spring Boot project with Gradle, writing unit tests, and configuring GitLab CI to automate the testing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pre-requirements:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Linux (Ubuntu based) Operational System&lt;/li&gt;
&lt;li&gt;GitLab Account&lt;/li&gt;
&lt;li&gt;Tool to unzip a file&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Install SDKMAN and Java 21
&lt;/h2&gt;

&lt;p&gt;First, we need to install &lt;strong&gt;SDKMAN&lt;/strong&gt;, a tool for managing parallel versions of multiple Software Development Kits (SDKs), including Java.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -s "https://get.sdkman.io" | bash
source "$HOME/.sdkman/bin/sdkman-init.sh"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can close and open again your terminal to assure your installation is successful.&lt;/p&gt;

&lt;p&gt;Second, use sdkman to install &lt;strong&gt;Java 21&lt;/strong&gt;, the most stable version.&lt;br&gt;
The command below shows the available versions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sdk list java
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fftq5deseg4cdh2ce0mkc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fftq5deseg4cdh2ce0mkc.png" alt="List of available Java versions" width="728" height="536"&gt;&lt;/a&gt;&lt;br&gt;
You can choose one of your preferences. Use the Identifier column as reference to install the chosen version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sdk install java 21.0.2-open
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Third, confirm you've installed successfully&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;java --version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Install Git
&lt;/h2&gt;

&lt;p&gt;Next, install &lt;strong&gt;Git&lt;/strong&gt;, a version control system that we'll use to manage code changes of our project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt-get update
sudo apt-get install git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3 Install IntelliJ IDEA
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;IntelliJ IDEA&lt;/strong&gt; is a popular IDE(Integrated Development Environment) for Java development. Here is the command to install it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo snap install intellij-idea-community --classic
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4: Create a Spring Boot Project
&lt;/h2&gt;

&lt;p&gt;We'll use &lt;strong&gt;Spring Initializr&lt;/strong&gt; to create a new project for the most recent version.&lt;br&gt;
Access &lt;a href="https://start.spring.io/" rel="noopener noreferrer"&gt;https://start.spring.io/&lt;/a&gt; and configure the project as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Project: Gradle - Kotlin&lt;/li&gt;
&lt;li&gt;Language: Java&lt;/li&gt;
&lt;li&gt;Spring Boot: 3.3.1&lt;/li&gt;
&lt;li&gt;Packaging: jar&lt;/li&gt;
&lt;li&gt;Java: 21&lt;/li&gt;
&lt;li&gt;Dependencies: No dependency is necessary&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Click on the button &lt;strong&gt;GENERATE&lt;/strong&gt; to download the project as zip.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frqzk80nsdlw6k7lpjfl8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frqzk80nsdlw6k7lpjfl8.png" alt="Spring Initializr Configured" width="800" height="744"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 5: Import the Project into IntelliJ
&lt;/h2&gt;

&lt;p&gt;Unzip the downloaded file into a folder of your preference.&lt;br&gt;
Open IntelliJ IDEA and import the unzipped project. IntelliJ will automatically detect the Gradle configuration and set up the project accordingly.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 6: Make a TDD
&lt;/h2&gt;

&lt;p&gt;First, let's create a Test. Create a simple class and a corresponding unit test.&lt;/p&gt;

&lt;p&gt;Create a new class named &lt;strong&gt;Calculator&lt;/strong&gt; in the folder &lt;strong&gt;src/main/java/com/example/demo&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="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Calculator&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;b&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="mi"&gt;0&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;Use &lt;strong&gt;jUnit&lt;/strong&gt; lib (it already comes with the Spring Boot) to create its unit test in the folder &lt;strong&gt;src/test/java/com/example/demo&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="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.junit.jupiter.api.Test&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;static&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;assertj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;core&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;api&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Assertions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;assertThat&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CalculatorTest&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;testAdd&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;calculator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Calculator&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;calculator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;assertThat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;isEqualTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&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;Second, let the test fail.&lt;br&gt;
Press one of the &lt;strong&gt;Green Button&lt;/strong&gt;s to run the test.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1boywrkkebacm3j1w4jr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1boywrkkebacm3j1w4jr.png" alt="Press Green Button to run the test" width="229" height="178"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Check that the test fails.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftoov4hd82e4kyqbyzd18.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftoov4hd82e4kyqbyzd18.png" alt="Test failing" width="599" height="245"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Third, fix the test by writing the correct business rule:&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="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Calculator&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;b&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="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&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;And, at last, run the test again and see that now it is passing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F46ll8t32uvjjhrn34fxi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F46ll8t32uvjjhrn34fxi.png" alt="Test passing" width="499" height="163"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Create a Gitlab CI Configuration File
&lt;/h2&gt;

&lt;p&gt;Create a .gitlab-ci.yml file in the root of your project. This file will define the pipeline.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;stages&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;build&lt;/span&gt;

&lt;span class="na"&gt;Build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build&lt;/span&gt;
  &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gradle:8.8.0-alpine&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;gradle --build-cache clean build&lt;/span&gt;
  &lt;span class="na"&gt;artifacts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;when&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
    &lt;span class="na"&gt;expire_in&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1 days&lt;/span&gt;
    &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;build/libs/*.jar&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;build/test-results/test/*.xml&lt;/span&gt;
    &lt;span class="na"&gt;reports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;junit&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;build/test-results/test/*.xml&lt;/span&gt;
  &lt;span class="na"&gt;only&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;stages&lt;/strong&gt;: define a sequence of steps that the pipeline will execute. The pipeline runs stages in the order they are defined, and all jobs within the same stage run in parallel. Only after all jobs in a stage complete successfully does the pipeline proceed to the next stage.&lt;br&gt;
&lt;strong&gt;Build&lt;/strong&gt;: name of the &lt;strong&gt;job&lt;/strong&gt; to be executed for the stage.&lt;br&gt;
&lt;strong&gt;Image&lt;/strong&gt;: Docker Image that will be used to execute the job.&lt;br&gt;
&lt;strong&gt;script&lt;/strong&gt;: gradle command to generate the jar, run the tests and generate a report about the tests.&lt;br&gt;
&lt;strong&gt;artifacts&lt;/strong&gt;: Files that will survive when the job is done.&lt;br&gt;
&lt;strong&gt;only&lt;/strong&gt;: name of the git branch&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 8: Create a Project on GitLab
&lt;/h2&gt;

&lt;p&gt;Gitlab is a web-based DevOps lifecycle tool that provides a Git repository manager offering source code management, continuous integration, and continuous deployment capabilities.&lt;/p&gt;

&lt;p&gt;Go to &lt;strong&gt;GitLab&lt;/strong&gt; and create a new blank project and make it public or private based on your preference.&lt;br&gt;
&lt;a href="https://gitlab.com/projects/new#blank_project" rel="noopener noreferrer"&gt;https://gitlab.com/projects/new#blank_project&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8aqg8i5kvobpz9x2tqbs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8aqg8i5kvobpz9x2tqbs.png" alt="New empty gitlab project" width="713" height="531"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 9: Configure Git in Project
&lt;/h2&gt;

&lt;p&gt;Open the terminal, go to the directory where you unzipped your code and configure git on it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git init --initial-branch=main
git remote add origin https://gitlab.com/your-username/spring-boot-unit-test-ci.git
git add .
git commit -m "Initial commit"
git push --set-upstream origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 10: Check the pipeline running
&lt;/h2&gt;

&lt;p&gt;Go to &lt;a href="https://gitlab.com/your-username/spring-boot-unit-test-ci/-/pipelines" rel="noopener noreferrer"&gt;https://gitlab.com/your-username/spring-boot-unit-test-ci/-/pipelines&lt;/a&gt; and click on the first (and only existent) pipeline running.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fruagcxt69gcdwhz6qzh4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fruagcxt69gcdwhz6qzh4.png" alt="the first and only existent pipeline" width="800" height="224"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here you can see the pipeline running:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fubdmcayqw709cl51p18w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fubdmcayqw709cl51p18w.png" alt="The pipeline running" width="800" height="285"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After some time, the pipeline passes:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn871ycgiwf72lsyax59k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn871ycgiwf72lsyax59k.png" alt="The pipeline passed" width="800" height="285"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here you can see the test report:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftbx3pyghs5g6hwxr2ar3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftbx3pyghs5g6hwxr2ar3.png" alt=" " width="800" height="373"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;By following these steps, you've successfully set up a Spring Boot project with Gradle, written an unit test, and configured GitLab CI to automate the testing. You can now make a test fail intentionally and observe the pipeline breaking, then fix the test and see the pipeline pass again. This iterative process helps ensure that your code is always in a deployable state.&lt;/p&gt;

&lt;p&gt;Here is the link to the project:&lt;br&gt;
&lt;a href="https://gitlab.com/thiagoematos/spring-boot-unit-test-ci" rel="noopener noreferrer"&gt;https://gitlab.com/thiagoematos/spring-boot-unit-test-ci&lt;/a&gt;&lt;/p&gt;

</description>
      <category>gitlab</category>
      <category>cicd</category>
      <category>springboot</category>
      <category>unittest</category>
    </item>
    <item>
      <title>Introduction to Pact Flow</title>
      <dc:creator>Thiago Matos</dc:creator>
      <pubDate>Thu, 04 Jul 2024 18:18:49 +0000</pubDate>
      <link>https://forem.com/thiagoematos/introduction-to-pact-flow-32a9</link>
      <guid>https://forem.com/thiagoematos/introduction-to-pact-flow-32a9</guid>
      <description>&lt;h2&gt;
  
  
  Introduction to Contract Testing
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Definition and importance of contract testing:&lt;/strong&gt; Imagine that you and your friends are planning a party and each one has a task: one will bring the snacks, another the sweets, and another the drinks. To ensure that everything goes well, you make a list of what everyone should bring. "Contract testing" is like this list, but for computer programs that need to talk to each other. It checks that each part of the program is doing exactly what it promised, just like you check that each friend brought what they agreed to for the party. This is important because if someone forgets or brings something wrong, the party might not be as fun. Likewise, if a program doesn't do what it promises, other programs may stop working correctly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Differences between contract testing and other types of testing (unit, integration, end-to-end):&lt;/strong&gt; Imagine you have a Lego. "Unit testing" is like testing each piece of Lego separately to see if they are perfect. "Integration testing" is when you put a few pieces together and check if they fit well and work together. "End-to-end testing" is when you assemble the entire toy and see if it works the way you want, like a walking car. "Contract testing" is as if you had a manual that tells you exactly how each piece should fit together with the others. It checks whether each part of the toy follows the rules in the manual, ensuring that everything will work correctly when you assemble it. Each type of test is important to ensure your toy is perfect and fun to play with!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Benefits of contract testing in microservices architecture:&lt;/strong&gt; Imagine that you and your friends are building a Lego city, and each one is responsible for a part: one makes the houses, another the streets, and another the parks. For the city to function well, you need to ensure that the streets connect well with the houses and parks. "Contract testing" is like an agreement you make to ensure that each part of the city will fit perfectly with the others. This is super important because, if someone builds a street that doesn't connect to the houses, people won't be able to get home! In a microservices architecture, each part of the program is like one of those parts of the city, and contract testing helps ensure that they all work well together, even if they are done by different people or at different times. This makes the city, or the program, work properly and without problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits of PactFlow
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Improved Collaboration:&lt;/strong&gt; Enhances communication between development teams.&lt;br&gt;
&lt;strong&gt;Reduced Integration Issues:&lt;/strong&gt; Minimizes problems when integrating different services.&lt;br&gt;
&lt;strong&gt;Faster Development Cycles:&lt;/strong&gt; Speeds up the development process by catching issues early.&lt;br&gt;
&lt;strong&gt;Increased Confidence:&lt;/strong&gt; Provides assurance that services will work together as expected.&lt;br&gt;
PactFlow is like a helper that keeps an eye on these messages to ensure that everyone is complying with what was agreed.&lt;br&gt;
When someone says they are going to bring snacks, Pact checks whether that person actually brought the snacks at the party.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up the Environment
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;pom.xml&lt;/li&gt;
&lt;li&gt;create an account&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Consumer-Driven Contracts
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Writing consumer tests&lt;/strong&gt; with Pact is like making a party wish list, saying exactly what you hope your friends will bring. Imagine that you are organizing the party and want to make sure you get the snacks, sweets and drinks you ordered. Consumer will generate a contract in json format. You write a little code that describes what the response should look like. If the test passes, it means that the other program is fulfilling what was agreed. If it doesn't pass, you know you need to adjust something.&lt;br&gt;
&lt;strong&gt;Writing provider tests&lt;/strong&gt; with Pact is like ensuring you actually bring what you promised to the party. Imagine that you said that you are going to take a chocolate cake with strawberry frosting. To make sure you don't forget or take something wrong, you do a check before leaving home: "Do I have the chocolate cake? Yes. Does it have strawberry frosting? Yes." So, on provider we need to write a code to provider the response for contract.&lt;/p&gt;

</description>
      <category>pactflow</category>
      <category>springboot</category>
      <category>kotlin</category>
      <category>contracttesting</category>
    </item>
  </channel>
</rss>
