<?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>DEV Community: Thiago Emidio</title>
    <description>The latest articles on DEV Community by Thiago Emidio (@thiagoemidiocorrea).</description>
    <link>https://dev.to/thiagoemidiocorrea</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%2F308611%2F6bfa0beb-b955-4540-9e20-571702c56365.jpg</url>
      <title>DEV Community: Thiago Emidio</title>
      <link>https://dev.to/thiagoemidiocorrea</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/thiagoemidiocorrea"/>
    <language>en</language>
    <item>
      <title>Um pouco de Java17</title>
      <dc:creator>Thiago Emidio</dc:creator>
      <pubDate>Sun, 20 Oct 2024 20:01:25 +0000</pubDate>
      <link>https://dev.to/thiagoemidiocorrea/um-pouco-de-java17-49b</link>
      <guid>https://dev.to/thiagoemidiocorrea/um-pouco-de-java17-49b</guid>
      <description>&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Sealed Classes&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sealed Classes foram introduzidas no Java 17 como parte das melhorias relacionadas à programação orientada a objetos, permitindo uma maior restrição a herança de classes. Essa funcionalidade oferece mais controle sobre quais classes podem estender ou implementar uma classe ou interface, ajudando a manter o código mais seguro.&lt;/p&gt;

&lt;p&gt;Vamos criar um tutorial passo a passo sobre como usar Sealed Classes em Java 17.&lt;/p&gt;

&lt;p&gt;Primeiramente vamos criar uma classe chamada Banco e vamos adicionar a ela o modificador “sealed”, que controla como outras classes ou interfaces podem estender ou implementar a classe ou interface.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Frztdoru737tdbubkw13l.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Frztdoru737tdbubkw13l.jpeg" alt="Image description" width="800" height="167"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fazendo isso, podemos ver que temos um erro indicando que a classe Banco com modificador “sealed” precisa ter subclasses.&lt;/p&gt;

&lt;p&gt;Para resolver este problema, vamos criar uma classe chamada Cliente e adicionando a cláusula “permits” a classe Banco.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fl0kmao1p9ywv45k5dwaw.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fl0kmao1p9ywv45k5dwaw.jpeg" alt="Image description" width="800" height="154"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fazendo isso podemos ver que termos o seguinte erro.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&amp;gt; Invalid permits clause: ‘Cliente’ must directly extend ‘Banco’&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;É isso mesmo que você está pensando, para resolver este problema precisamos extender a classe Banco diretamente na classe Cliente.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fshzp1cieen95071s07jc.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fshzp1cieen95071s07jc.jpeg" alt="Image description" width="762" height="226"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Isso resolve nosso problema e com isso ja conseguimos utilizar nossa Sealed Classe, legal não e mesmo ?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&amp;gt; OBS: O conceito de sealed também pode ser aplicado a interfaces em Java 17. Assim como em classes, uma interface selada pode restringir quais outras interfaces ou classes podem implementá-la.&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Conclusão:&lt;br&gt;
Sealed Classes oferecem uma forma poderosa de restringir e controlar herança em Java. Com isso, você pode evitar que classes sejam estendidas por engano, melhorando a legibilidade e a segurança do código.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>java</category>
      <category>java17</category>
      <category>certification</category>
    </item>
    <item>
      <title>Monitoramento e visualização de métricas com Docker Compose, Prometheus e Grafana.</title>
      <dc:creator>Thiago Emidio</dc:creator>
      <pubDate>Fri, 31 May 2024 10:07:57 +0000</pubDate>
      <link>https://dev.to/thiagoemidiocorrea/monitoramento-e-visualizacao-de-metricas-com-docker-compose-prometheus-e-grafana-2b3k</link>
      <guid>https://dev.to/thiagoemidiocorrea/monitoramento-e-visualizacao-de-metricas-com-docker-compose-prometheus-e-grafana-2b3k</guid>
      <description>&lt;p&gt;&lt;a href="https://media.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%2Fpulqr7pwcnimxqkaobk2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fpulqr7pwcnimxqkaobk2.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Prometheus e Grafana são duas ferramentas utilizadas no monitoramento e visualização de métricas de aplicações, porem têm propósitos e funcionalidades diferentes. Durante este tutorial, vamos ver quais a diferenças e como utilizadas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prometheus:&lt;/strong&gt;&lt;br&gt;
O Prometheus é uma ferramenta de monitoramento e sistema de alerta. Ele é projetado para coletar e armazenar métricas de sistemas e aplicações.&lt;/p&gt;

&lt;p&gt;O Prometheus possui um sistema de alertas embutido, onde você pode definir regras de alerta que serão analisadas, e se uma condição for atendida, o Prometheus enviará alertas para várias integrações, como e-mail, Slack por exemplo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Grafana:&lt;/strong&gt;&lt;br&gt;
O Grafana é uma plataforma de visualização de métricas. Ele é usado para criar dashboards interativos e gráficos a partir de várias fontes de dados como o Prometheus, InfluxDB, Graphite, Elasticsearch.&lt;/p&gt;

&lt;p&gt;Para começar a monitorar uma aplicação Spring Boot com Prometheus e Grafana, vamos configurar um ambiente usando Docker Compose. Primeiro, precisamos criar um arquivo &lt;em&gt;docker-compose.yml&lt;/em&gt; com os serviços do Prometheus e Grafana.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    volumes:
      - "./src/main/resources/prometheus.yml:/etc/prometheus/prometheus.yml"
    command:
      - "--config.file=/etc/prometheus/prometheus.yml"
    ports:
      - "9090:9090"

  grafana:
    image: grafana/grafana:9.5.15
    container_name: grafana
    restart: unless-stopped
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_USER=admin
      - GF_SECURITY_ADMIN_PASSWORD=admin
      - GF_USERS_ALLOW_SIGN_UP=false
    volumes:
      - ./grafana/provisioning:/etc/grafana/provisioning
    depends_on:
      - prometheus
    healthcheck:
      test: [ "CMD", "nc", "-z", "localhost", "3000" ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Vamos, precisar também configurar o arquivo prometheus.ym do Prometheus, ele e o responsável por coletar o onde configuramos os alvos de scraping, ou seja, os endpoints que o Prometheus irá coletar métricas.&lt;/p&gt;

&lt;p&gt;Para o Grafana, precisamos configurar um painel para visualizar as métricas coletadas pelo Prometheus.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# my global config
global:
  scrape_interval:     15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
  evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
  # scrape_timeout is set to the global default (10s).


# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
  # The job name is added as a label `job=&amp;lt;job_name&amp;gt;` to any timeseries scraped from this config.
  - job_name: 'prometheus'

    # metrics_path defaults to '/metrics'
    # scheme defaults to 'http'.
    static_configs:
      - targets: ['127.0.0.1:9090']

    - job_name: 'spring-boot-actuator'
    scrape_interval: 5s # Define a frequência com que o Prometheus deve coletar métricas
    metrics_path: '/actuator/prometheus' # O caminho onde as métricas do Micrometer são expostas
    static_configs:
      - targets: ['host.docker.internal:8080'] # O endpoint da sua aplicação Spring Boot
        labels:
          application: book-api

  - job_name: 'grafana'
    metrics_path: '/'
    scrape_interval: 5s
    static_configs:
      - targets: ['127.0.0.1:3000']
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;OBS: Na minha tag targets, eu configurei o host da minha aplicação desta da seguinte forma host.docker.internal, isso por que minha aplicação esta rodando em um container docker.&lt;/p&gt;

&lt;p&gt;Vamos configurar o &lt;em&gt;application.yml&lt;/em&gt; da nossa aplicação.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;management:
  endpoints:
    web:
      base-path: /actuator
      exposure:
        include: "*"
  endpoint:
    prometheus:
        enabled: true
    metrics:
        enabled: true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Vamos também adicionar duas dependências no nosso POM.xml.&lt;br&gt;
A dependencia do actuator e a dependencia do prometheus.&lt;/p&gt;

&lt;p&gt;A dependência &lt;em&gt;spring-boot-starter-actuator&lt;/em&gt; é uma dependência que fornece recursos de monitoramento e gerenciamento.&lt;/p&gt;

&lt;p&gt;A dependência &lt;em&gt;micrometer-registry-prometheus&lt;/em&gt; é utilizada para integrar o Spring Boot Actuator com o Micrometer e o Prometheus.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;dependency&amp;gt;
   &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
   &amp;lt;artifactId&amp;gt;spring-boot-starter-actuator&amp;lt;/artifactId&amp;gt;
&amp;lt;/dependency&amp;gt;

&amp;lt;dependency&amp;gt;
   &amp;lt;groupId&amp;gt;io.micrometer&amp;lt;/groupId&amp;gt;
   &amp;lt;artifactId&amp;gt;micrometer-registry-prometheus&amp;lt;/artifactId&amp;gt;
&amp;lt;/dependency&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Feito isso vamos executar o comando docker-compose up -d e veremos os containers iniciados.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fbcq9p0gb61rp8djvvy0w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fbcq9p0gb61rp8djvvy0w.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Acessando a url do Prometheus &lt;a href="http://localhost:9090" rel="noopener noreferrer"&gt;http://localhost:9090&lt;/a&gt;, podemos ver que os serviços estão com o status “UP”, ou seja, estão saudáveis e funcionando.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fuw2t9ye8o2mh1qpiqcho.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fuw2t9ye8o2mh1qpiqcho.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Agora, vamos configurar os gráficos de monitoramento do Grafana. Acesse a url &lt;a href="http://localhost:3000/connections/connect-data" rel="noopener noreferrer"&gt;http://localhost:3000/connections/connect-data&lt;/a&gt;, e pesquise por Prometheus&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fp0gbt9qui9o4uwm0qpmg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fp0gbt9qui9o4uwm0qpmg.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Clique na opção “Create a Prometheus data source”, preencha o campo URL com a url do Prometheus, no caso como meu Prometheus esta em um container Docker precisamos pegar o IP do nosso container.&lt;/p&gt;

&lt;p&gt;Execute o seguinte comando docker inspect &lt;/p&gt;

&lt;p&gt;Na seção Networks &amp;gt; IPAddress: “192.168.240.3”, feito isso adicione do campo URL e clique em salvar.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fhnrpsevag8nsz8uruplh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fhnrpsevag8nsz8uruplh.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Agora vamos configurar os gráficos de monitoramento do Grafana.&lt;/p&gt;

&lt;p&gt;Acesse a url &lt;a href="http://localhost:3000/dashboards" rel="noopener noreferrer"&gt;http://localhost:3000/dashboards&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Acesse a opção New &amp;gt; Import e adicione a url &lt;a href="http://grafana.com/grafana/dashboards/4701" rel="noopener noreferrer"&gt;http://grafana.com/grafana/dashboards/4701&lt;/a&gt;, essa URL e um gráfico disponibilizado no próprio site do Grafana, mas você pode escolher outros tipos de gráfico conforme a sua necessidade. Feito isso clique em load.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F2a9q4c71y24yran07n2x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F2a9q4c71y24yran07n2x.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Depois disso, selecione Prometheus no campo de datasource e clique em Import.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fto0h73mn4z3pw467ixrm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fto0h73mn4z3pw467ixrm.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Em seguida, podemos ver o gráfico com os dados do coletados pelo nosso Prometheus. Lindo não é mesmo ?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Flfeiyily7x1tjb1ddwrs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Flfeiyily7x1tjb1ddwrs.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusão:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;O monitoramento de uma aplicação é uma maneira de garantir que sua aplicação esteja funcionando de forma confiável e eficiente. Ao coletar e visualizar métricas importantes, você pode identificar problemas de desempenho, capacidade e disponibilidade antes que eles afetem os usuários finais. Estas ferramentas oferecem uma solução poderosa e flexível para monitorar e manter a saúde de suas aplicações em produção.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Entendendo o Amazon DynamoDB</title>
      <dc:creator>Thiago Emidio</dc:creator>
      <pubDate>Wed, 22 May 2024 18:15:18 +0000</pubDate>
      <link>https://dev.to/thiagoemidiocorrea/entendendo-o-amazon-dynamodb-mi2</link>
      <guid>https://dev.to/thiagoemidiocorrea/entendendo-o-amazon-dynamodb-mi2</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbcihmwdwvkc59x0waat6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbcihmwdwvkc59x0waat6.png" alt="Image description" width="773" height="430"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;O Amazon DynamoDB é um serviço de banco de dados NoSQL totalmente gerenciado, oferecido pela Amazon Web Services (AWS). Ele é projetado para lidar com grandes quantidades de tráfego de dados, proporcionando uma latência consistente.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tabelas, Itens e Atributos:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzbzgd95sgqw3orie5l27.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzbzgd95sgqw3orie5l27.png" alt="Image description" width="401" height="511"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Tabelas: O DynamoDB armazena dados em tabelas, que são coleções de itens.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Itens: Cada tabela contém zero ou mais itens. Um item é uma coleção de atributos.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Atributos: Cada atributo tem um nome e um valor. O valor pode ser um escalar (string, número, binário), um conjunto (conjunto de strings, números ou binários), ou um mapa (estrutura de dados aninhada).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Chaves Primárias:&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;Chave de Partição (Hash Key):&lt;/em&gt;&lt;br&gt;
Uma chave de partição é usada para distribuir itens entre partições de armazenamento e e obrigatória para todas as tabelas.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Chave de Partição e Chave de Classificação (Range Key):&lt;/em&gt;&lt;br&gt;
Além da chave de partição, uma chave de classificação é usada para ordenar os itens com a mesma chave de partição. É opcional.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx98al23bd4o7qvgxj8k8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx98al23bd4o7qvgxj8k8.png" alt="Image description" width="640" height="238"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Particionamento e Escalabilidade&lt;/strong&gt;&lt;br&gt;
DynamoDB distribui automaticamente dados entre várias partições físicas para gerenciar a carga de leitura e escrita, e também armazenar grandes volumes de dados. Cada partição é responsável por um subconjunto dos dados da tabela.&lt;/p&gt;

&lt;p&gt;A chave de partição (hash key) é usada para determinar em qual partição física um item específico será armazenado. Isso garante uma distribuição uniforme dos dados.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuzrvgss1h0sn2r2z693f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuzrvgss1h0sn2r2z693f.png" alt="Image description" width="800" height="345"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Conforme os dados da sua tabela aumentam, o DynamoDB automaticamente adiciona mais partições.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9mcgflpqdw0d2vprsdl7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9mcgflpqdw0d2vprsdl7.png" alt="Image description" width="800" height="483"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Replicação e Disponibilidade:&lt;/strong&gt;&lt;br&gt;
As Global Tables permitem replicar dados entre várias regiões da AWS. Ao criar uma tabela global, o DynamoDB cria réplicas da tabela original em cada região especificada.&lt;/p&gt;

&lt;p&gt;DynamoDB Streams captura todas as alterações de dados na tabela (inserções, atualizações, exclusões). Os eventos nas streams são ordenados, garantindo que as mudanças sejam aplicadas na mesma ordem em todas as réplicas, o que ajuda a manter a consistência dos dados.&lt;/p&gt;

&lt;p&gt;Quando um item é atualizado em uma região, o DynamoDB propaga essa alteração para todas as outras réplicas de maneira assíncrona.&lt;/p&gt;

&lt;p&gt;Se houver conflitos de escrita (por exemplo, quando o mesmo item é atualizado simultaneamente em diferentes regiões), o DynamoDB resolve esses conflitos usando uma abordagem de “Last Writer Wins”, onde a atualização mais recente (com base no timestamp) prevalece.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7twk918axjlqnx8kh8ez.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7twk918axjlqnx8kh8ez.png" alt="Image description" width="720" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusão&lt;/strong&gt;&lt;br&gt;
O DynamoDB fornece um mecanismo robusto para replicação e consistência de dados em múltiplas regiões AWS. Através do uso de streams e políticas de resolução de conflitos, ele mantém os dados sincronizados e atualizados, prevenindo a maioria dos problemas de dados desatualizados.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.CoreComponents.html"&gt;https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.CoreComponents.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.alexdebrie.com/posts/dynamodb-partitions/"&gt;https://www.alexdebrie.com/posts/dynamodb-partitions/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://stackoverflow.com/questions/27329461/what-is-hash-and-range-primary-key"&gt;https://stackoverflow.com/questions/27329461/what-is-hash-and-range-primary-key&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Introdução às Coroutines em Kotlin: Simplificando Operações Assíncronas</title>
      <dc:creator>Thiago Emidio</dc:creator>
      <pubDate>Wed, 31 Jan 2024 19:28:02 +0000</pubDate>
      <link>https://dev.to/thiagoemidiocorrea/introducao-as-coroutines-em-kotlin-simplificando-operacoes-assincronas-51m5</link>
      <guid>https://dev.to/thiagoemidiocorrea/introducao-as-coroutines-em-kotlin-simplificando-operacoes-assincronas-51m5</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcw98jgyx01dwbzxjokd1.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcw98jgyx01dwbzxjokd1.gif" alt="Image description" width="997" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Coroutines em Kotlin oferecem uma maneira eficiente de lidar com operações assíncronas, tornando o código mais legível e fácil de manter. Elas são uma alternativa leve às tradicionais callbacks ou às primitivas de concorrência, permitindo que você escreva código assíncrono de maneira sequencial. Neste tutorial, exploraremos uma introdução básica às coroutines em Kotlin, apresentaremos um exemplo prático e concluiremos com insights sobre seu uso e benefícios.&lt;/p&gt;

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

&lt;p&gt;Vamos criar um exemplo prático usando coroutines para gerar números de pedido de maneira assíncrona. Primeiro, definiremos uma função generate que simula uma operação assíncrona para obter um número de pedido:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import kotlinx.coroutines.*

suspend fun generate(): String {
    val currentLocale: java.util.Locale = java.util.Locale.getDefault()
    val countryCode: String = currentLocale.country
    val order = generateSequence(1) { it + 1 }
        .take(1)
        .distinct()
        .sorted()
        .toSet()

    val number = order.stream().findFirst().get()
    val orderNumber = countryCode + number
    println("Order number: $orderNumber")
    return orderNumber
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora, usaremos runBlocking para criar um escopo de coroutine bloqueante e chamar a função generate de maneira síncrona:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import kotlinx.coroutines.runBlocking

fun main() {
    runBlocking {
        println("Start of execution ")
        val orderNumber: String = generate()
        println("Coroutine completed with order number: $orderNumber")
    }

    println("Main program continues while the coroutine is running.")
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Conclusão:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Como podemos ver, as coroutines em Kotlin oferecem uma abordagem simples e poderosa para lidar com operações assíncronas. Elas simplificam o código, tornando-o mais compreensível e evitando o callback hell associado a abordagens tradicionais. A utilização de runBlocking para simplificar o uso de coroutines em funções main ou em scripts pode ser adequada em certos contextos, mas em aplicações mais complexas, é recomendável o uso de escopos de coroutine mais específicos. Ao integrar coroutines em seus projetos Kotlin, você pode aproveitar os benefícios da concorrência sem sacrificar a legibilidade do código.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://kotlinlang.org/docs/coroutines-overview.html"&gt;https://kotlinlang.org/docs/coroutines-overview.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.baeldung.com/kotlin/coroutines"&gt;https://www.baeldung.com/kotlin/coroutines&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Criando um bucket S3 na AWS usando Terraform.</title>
      <dc:creator>Thiago Emidio</dc:creator>
      <pubDate>Thu, 13 Jul 2023 17:55:57 +0000</pubDate>
      <link>https://dev.to/thiagoemidiocorrea/criando-um-bucket-s3-na-aws-usando-terraform-po1</link>
      <guid>https://dev.to/thiagoemidiocorrea/criando-um-bucket-s3-na-aws-usando-terraform-po1</guid>
      <description>&lt;p&gt;Neste tutorial, você aprenderá como criar um bucket S3 na AWS usando o Terraform. O Terraform é uma ferramenta de infraestrutura como código (IaC) que permite definir e provisionar recursos de infraestrutura de forma automatizada.&lt;/p&gt;

&lt;p&gt;Pré-requisitos&lt;br&gt;
Antes de começar, certifique-se de ter o seguinte:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Uma conta na AWS com as credenciais de acesso configuradas.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;O Terraform instalado na sua máquina. Você pode baixá-lo em no site oficial do &lt;a href="https://developer.hashicorp.com/terraform/downloads"&gt;Terraform&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Passo 1: Configurando o projeto&lt;/strong&gt;&lt;br&gt;
Crie um diretório para o seu projeto e acesse-o no terminal.&lt;/p&gt;

&lt;p&gt;Dentro do diretório do projeto, crie três arquivos: main.tf, variables.tf e providers.tf.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;O arquivo main.tf conterá a configuração do bucket S3 e os recursos relacionados.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;O arquivo variables.tf conterá as variáveis que você deseja configurar para o seu bucket.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;O arquivo providers.tf conterá as configurações do provedor da AWS.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Passo 2: Configurando o arquivo main.tf&lt;/strong&gt;&lt;br&gt;
Abra o arquivo main.tf e adicione o seguinte código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_s3_bucket" "my_bucket" {
  bucket = var.bucket_name

  tags = {
    Name        = "my-bucket-test-tutorial"
    Environment = var.environment
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;O recurso aws_s3_bucket define um bucket na AWS. O nome do bucket é definido usando a variável var.bucket_name.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As tags são usadas para adicionar metadados ao bucket, como nome e ambiente. As tags são definidas no bloco tags usando pares chave-valor.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Passo 3: Configurando o arquivo variables.tf&lt;/strong&gt;&lt;br&gt;
Abra o arquivo variables.tf e adicione o seguinte código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;variable "bucket_name" {
  type        = string
  description = "Nome do bucket da AWS"
}

variable "environment" {
  type        = string
  description = "Ambiente do bucket da AWS"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As variáveis &lt;em&gt;bucket_name&lt;/em&gt; e &lt;em&gt;environment&lt;/em&gt; são definidas para permitir a personalização do nome do bucket e do ambiente. O tipo das variáveis é definido como string e uma descrição é fornecida para facilitar o entendimento.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Passo 4: Configurando o arquivo providers.tf&lt;/strong&gt;&lt;br&gt;
Abra o arquivo providers.tf e adicione o seguinte código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;provider "aws" {
  region = "us-east-1"
  access_key = var.aws_access_key
  secret_access_key = var.aws_secret_access_key
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;O provedor aws é configurado com a região da AWS que você deseja usar. No exemplo acima, a região é definida como us-east-1. Certifique-se de substituir esse valor pela região desejada.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As chaves de acesso da AWS são definidas usando as variáveis var.aws_access_key e var.aws_secret_access_key. Certifique-se de fornecer esses valores corretamente. Você pode definir essas variáveis em um arquivo terraform.tfvars ou passá-las por linha de comando.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Passo 5: Executando o Terraform&lt;/strong&gt;&lt;br&gt;
Abra o terminal e navegue até o diretório do projeto.&lt;/p&gt;

&lt;p&gt;Execute o comando &lt;em&gt;terraform init&lt;/em&gt; para inicializar o diretório do projeto e baixar os provedores necessários.&lt;br&gt;
Execute o comando terraform plan para visualizar as alterações planejadas pelo Terraform.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff8no4vrl8eq3urjbzhe9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff8no4vrl8eq3urjbzhe9.png" alt="Image description" width="800" height="511"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
Execute o comando &lt;em&gt;terraform apply&lt;/em&gt; para criar o bucket na AWS com base nas configurações fornecidas. No final, voce sera perguntando se gostaria de continuar com esta ação, apenas digite “Yes”.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuct2spco47923okj1x6v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuct2spco47923okj1x6v.png" alt="Image description" width="800" height="582"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
Após alguns instantes, o Terraform criará o bucket na AWS. Você verá uma mensagem indicando o sucesso da operação.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa087fdzqme2nezbnv95l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa087fdzqme2nezbnv95l.png" alt="Image description" width="800" height="72"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Agora você já pode acessar sua conta da AWS e ver seu bucket criado.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F37z67qhs4965y35i3cmg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F37z67qhs4965y35i3cmg.png" alt="Image description" width="800" height="25"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Conclusão&lt;br&gt;
Parabéns! Você criou um bucket na AWS usando o Terraform. Agora você pode usar esse bucket para armazenar objetos e aproveitar outros recursos do S3.&lt;/p&gt;

&lt;p&gt;Enjoy :)&lt;/p&gt;

</description>
      <category>aws</category>
      <category>s3</category>
      <category>cloud</category>
      <category>terraform</category>
    </item>
    <item>
      <title>Enviando mensagens de texto com o Twilio utilizando Java e Spring Boot: Um guia passo a passo.</title>
      <dc:creator>Thiago Emidio</dc:creator>
      <pubDate>Thu, 15 Jun 2023 17:01:36 +0000</pubDate>
      <link>https://dev.to/thiagoemidiocorrea/enviando-mensagens-de-texto-com-o-twilio-utilizando-java-e-spring-boot-um-guia-passo-a-passo-4g32</link>
      <guid>https://dev.to/thiagoemidiocorrea/enviando-mensagens-de-texto-com-o-twilio-utilizando-java-e-spring-boot-um-guia-passo-a-passo-4g32</guid>
      <description>&lt;p&gt;&lt;strong&gt;O que é o Twilio:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;O Twilio é uma plataforma de comunicação em nuvem que permite a integração de serviços de mensagens, voz e vídeo em aplicativos. Neste artigo, exploraremos como enviar mensagens de texto usando o Twilio em conjunto com o framework Spring Boot em Java. Você aprenderá como adicionar a biblioteca do Twilio no seu projeto Spring Boot e enviar mensagens de texto programaticamente.&lt;/p&gt;

&lt;p&gt;Caso nao tenha um conta, acesse o site do Twilio para criar sua conta.&lt;/p&gt;

&lt;p&gt;O Twilio ira liberar um número de telefone e credenciais para a utilização do serviços.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Adicionando dependencia do Twilio.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A primeira coisa que devemos fazer e configurar a biblioteca do Twilio no projeto. Adicione a dependência do Twilio SDK ao seu projeto Spring Boot. Isso pode ser feito através do Maven ou do Gradle, dependendo do seu gerenciador de dependências preferido. A dependência fornecerá as classes e métodos necessários para interagir com a API do Twilio. Lembre-se de importar as classes relevantes no seu código&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;com.twilio.sdk&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;twilio&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;8.17.0&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Configuração das credenciais do Twilio&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No arquivo application.properties ou application.yml do Spring Boot, adicione as seguintes propriedades:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;twilio.accountSid=YOUR_ACCOUNT_SID
twilio.authToken=YOUR_AUTH_TOKEN
twilio.phoneNumber=YOUR_PHONE_NUMBER
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Substitua YOUR_ACCOUNT_SID, YOUR_AUTH_TOKEN e YOUR_PHONE_NUMBER pelas suas credenciais e número de telefone que o Twilio forneceu.&lt;/p&gt;

&lt;p&gt;Abaixo temos o objeto que vamos usar na nossa Request.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class SMSRequest {
    private String to;       // Número de telefone de destino
    private String message;  // Mensagem de texto a ser enviada

    // Getters e setters

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Crie um controlador Spring para enviar mensagens de texto.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class SMSController {

    private final TwilioService twilioService;

    @Autowired
    public SMSController(TwilioService twilioService) {
        this.twilioService = twilioService;
    }

    @PostMapping("/send-sms")
    public void sendSMS(@RequestBody SMSRequest request) {
        twilioService.sendSMS(request.getTo(), request.getMessage());
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Na camada de serviço é onde tudo ira acontecer, iremos realizar a chamada para o serviço do Twilio passando nossas credenciais que criamos no site do &lt;a href="https://www.twilio.com/en-us"&gt;Twilio&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Repare que no objeto SMSRequest temos a variável “To” que sera usada para armazenar o numero de telefone que queremos enviar a mensagem de texto.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import com.twilio.Twilio;
import com.twilio.rest.api.v2010.account.Message;
import com.twilio.type.PhoneNumber;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

@Service
public class TwilioService {

    @Value("${twilio.accountSid}")
    private String accountSid;

    @Value("${twilio.authToken}")
    private String authToken;

    @Value("${twilio.phoneNumber}")
    private String phoneNumber;

    public void sendSMS(String to, String message) {
        Twilio.init(accountSid, authToken);

        Message.creator(
                new PhoneNumber(to),
                new PhoneNumber(phoneNumber),
                message
        ).create();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Testando o envio de mensagens.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Inicie o servidor Spring Boot e envie uma solicitação POST para a rota /send-sms, passando o número de telefone de destino e a mensagem no corpo da solicitação. Conforme o exemplo abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "to": "+15555555555",
    "message": "Olá! Esta é uma mensagem de teste do Twilio."
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Conclusão:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Neste artigo, exploramos como enviar mensagens de texto com o Twilio usando Java e o framework Spring Boot. Adicionamos a biblioteca Twilio ao projeto e enviamos mensagens de texto programaticamente. O Twilio oferece uma API robusta e fácil de usar, permitindo comunicação eficiente por meio de mensagens de texto. Espero que tenha ajudado!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Java 17 - Records</title>
      <dc:creator>Thiago Emidio</dc:creator>
      <pubDate>Wed, 14 Jun 2023 21:30:58 +0000</pubDate>
      <link>https://dev.to/thiagoemidiocorrea/java-17-records-4mik</link>
      <guid>https://dev.to/thiagoemidiocorrea/java-17-records-4mik</guid>
      <description>&lt;p&gt;&lt;a href="https://media.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%2Fdmvuoify71polz34j564.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fdmvuoify71polz34j564.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hoje vamos falar da feature Record. :)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A funcionalidade de record no Java 17 é uma nova adição à linguagem que simplifica a criação de classes de dados imutáveis. Ela combina várias características, como geração automática de campos, geração de construtores e implementações padrão de métodos comuns como equals(), hashCode() e toString(). Records são declarados usando a palavra-chave "record", seguida pelo nome e uma lista de componentes.&lt;/p&gt;

&lt;p&gt;Abaixo está um exemplo de declaração simples de um record:&lt;/p&gt;

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

record Pessoa(String nome, int idade) {
 // Corpo do record (opcional)
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;No exemplo acima, declaramos um record chamado "Pessoa" com dois componentes: um campo de string "nome" e um campo de inteiro "idade". O record gera automaticamente um construtor, getters para cada componente e implementações padrão de equals(), hashCode() e toString().&lt;br&gt;
Você pode criar uma instância de um record usando o construtor como qualquer outra classe:&lt;/p&gt;

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

Pessoa pessoa = new Pessoa("Thiago", 35);


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Records são imutáveis por padrão, o que significa que seus campos não podem ser modificados depois de inicializados. No entanto, você ainda pode atualizar uma instância de record criando um novo record com valores atualizados usando a palavra-chave "with":&lt;/p&gt;

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

Pessoa pessoaAtualizada = pessoa.withIdade(31);


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Nesse exemplo, uma nova instância de record chamada "pessoaAtualizada" é criada com o mesmo nome do record original, mas com a idade atualizada para 31. O método "withIdade()" é gerado automaticamente pelo record.&lt;br&gt;
Records também podem ser usados em declarações de switch:&lt;/p&gt;

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

public String obterDescricaoPessoa(Pessoa pessoa) {
 return switch (pessoa.idade()) {
 case 0 -&amp;gt; "Recém-nascido";
 case 18 -&amp;gt; "Adulto";
 default -&amp;gt; "Desconhecido";
 };
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Nesse exemplo, o método "obterDescricaoPessoa" recebe um record de pessoa como parâmetro e usa uma declaração de switch para retornar uma descrição com base na idade.&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;Conclusão: *&lt;/em&gt;&lt;br&gt;
No geral, a funcionalidade de record no Java 17 oferece uma forma conveniente de criar classes de dados imutáveis e com um código de fácil manutenção. Ela melhora a legibilidade do código e reduz o esforço necessário para criar e usar tais classes.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
