Search
87 itens encontrados para ""
- Primeiros passos com DBT - Data Build Tool
O DBT tem sido utilizado por muitas empresas na área de Dados e acredito que podemos extrair bons insights neste post sobre ele. Esse vai ser um post prático mostrando como o DBT funciona e espero que vocês gostem. O que é DBT? DBT significa Data Build Tool e permite que equipes transformem os dados já carregados em seu warehouse através de operações de DML como um simples Select. DBT representa o T no processo de ELT, ou seja, ele não trabalha para extrair e carregar dados mas sim, para transformá-los. Passo 1: Criando o projeto DBT Agora, assumimos que o DBT já esteja instalado, mas se não estiver, recomendo consultar este link para mais informações. Após a instalado, você pode criar um novo projeto usando CLI ou pode clonar este projeto do repositório DBT no Github. Aqui para este post, vamos usar o modo CLI para criar nosso projeto e também para concluir as próximas etapas. Para criar um novo projeto, execute o comando abaixo no seu terminal. dbt init Depois de executar o comando acima, você precisa digitar o nome do projeto e qual warehouse ou banco de dados você vai usar conforme a imagem abaixo. Para este post, vamos usar o adaptador do postgres. É muito importante que você tenha o banco de dados postgres já instalado ou você pode criar uma imagem postgres usando o docker. Sobre os adaptadores, o DBT suporta vários deles e você pode conferir aqui. Criei uma estrutura de tabela e também carreguei os dados simulando dados de uma plataforma de vídeo chamada wetube e vamos utilizá-los para entender como o DBT funciona. Acompanhe a estrutura: Passo 2: Estrutura e mais sobre DBT Após executar o comando dbt init para criar o projeto, uma estrutura de pastas e arquivos abaixo será criada. Não vou falar sobre todos os diretórios do projeto, mas gostaria de focar em dois deles. Sources Antes de falarmos sobre os dois diretórios, vamos falar sobre os Sources, são basicamente os dados já carregados em seu warehouse. No processo DBT, as fontes têm o mesmo significado de dados brutos. Não há pastas que representem dados Sources para este projeto, mas você precisa saber sobre este termo pois vamos configurar tabelas já criadas como Sources para as próximas seções. Seeds Seeds é um diretório que oferece um mecanismo interessante e útil para carregar dados estáticos em seu warehouse por meio de arquivos CSV. Se você deseja carregar esses dados, você precisa criar um arquivo CSV neste diretório e executar o comando abaixo. dbt seed Para cada campo no arquivo CSV, o DBT irá inferir os tipos e criará tabelas e suas colunas no warehouse ou banco de dados. Models O DBT funciona com o paradigma de Model, a ideia principal é que você pode criar modelos através da transformações utilizando instruções SQL baseadas em fontes de tabelas ou modelos existentes Cada arquivo SQL localizado na pasta de model criará um modelo em seu warehouse ou banco de dados quando o comando abaixo for executado. dbt run Lembre-se que um modelo pode ser criado através de uma fonte ou outro modelo e não se preocupe com isso, vou mostrar mais detalhes sobre isso. Passo 3: Configurando a configuração com o banco de dados Com o projeto já criado, precisamos configurar a conexão com o banco de dados e aqui neste post vamos usar o postgres como banco de dados. Depois de inicializar o projeto, vários arquivos são criados e um deles é chamado de profiles.yml. profiles.yml é o arquivo é responsável por controlar os diferentes perfis/profiles para as diferentes conexões com os bancos de dados, como ambiente de desenvolvimento e produção. Se você notou, não podemos ver este arquivo na imagem acima porque este arquivo é criado fora do projeto para evitar credenciais que sejam confidenciais. Você pode encontrar esse arquivo no diretório ~/.dbt/. Se você observar, temos um perfil chamado dbt_blog e um destino chamado dev, por padrão, o destino refere-se a dev com as configurações de conexão do banco de dados. Além disso, é possível criar um ou mais perfis e alvos(target), permitindo trabalhar com diferentes ambientes. Outro detalhe importante é que o perfil dbt_blog deve ser especificado no arquivo dbt_project.yml como um perfil padrão. Nas próximas seções, discutiremos o que é e como o arquivo dbt_project.yml funciona. Passo 4: Criando o arquivo dbt_project.yml Todo projeto DBT possui um arquivo dbt_project.yml, você pode configurar informações como nome do projeto, diretórios, perfis e tipo de materialização. name: 'dbt_blog' version: '1.0.0' config-version: 2 profile: 'dbt_blog' model-paths: ["models"] analysis-paths: ["analyses"] test-paths: ["tests"] seed-paths: ["seeds"] macro-paths: ["macros"] snapshot-paths: ["snapshots"] target-path: "target" # directory which will store compiled SQL files clean-targets: # directories to be removed by `dbt clean` - "target" - "dbt_packages" models: dbt_blog: # Config indicated by + and applies to all files under models/example/ mart: +materialized: table Observe que o campo de profile foi configurado como o mesmo profile especificado no arquivo profiles.yml e outro detalhe importante é sobre o campo materialized. Aqui foi configurado como um valor table, mas por padrão, é uma view. O campo materialized permite que você crie modelos como uma tabela ou view em cada execução. Existem outros tipos de materialização, mas não vamos discutir aqui e eu recomendo ver a documentação do dbt. Passo 5: Criando nosso primeiro modelo Criando os primeiros arquivos Vamos mudar um pouco e vamos criar uma subpasta no diretório do model chamada mart e dentro desta pasta vamos criar nossos arquivos .SQL e também outro arquivo importante que ainda não discutimos chamado schema.yml. Criando o arquivo schema Os arquivos de schema são usados para mapear fontes e documentar modelos como o nome do modelo, colunas e muito mais. Agora você pode criar um arquivo chamado schema.yml e preencher com as informações abaixo. version: 2 sources: - name: wetube tables: - name: account - name: city - name: state - name: channel - name: channel_subs - name: video - name: video_like - name: user_address models: - name: number_of_subs_by_channel description: "Number of subscribers by channel" columns: - name: id_channel description: "Channel's ID" tests: - not_null - name: channel description: "Channel's Name" tests: - not_null - name: num_of_subs description: "Number of Subs" tests: - not_null Sources: No campo source você pode incluir tabelas do seu warehouse ou banco de dados que serão utilizadas na criação do modelo. models: No campo models você pode incluir o nome do modelo, colunas e suas descrições Criando um modelo Esta parte é onde podemos criar scripts .SQL que resultarão em nosso primeiro modelo. Para o primeiro modelo, vamos criar uma instrução SQL para representar um modelo que podemos ver os números de inscritos do canal. Vamos criar um arquivo chamado number_of_subs_by_channel.sql e preenchê-lo com os scripts abaixo. with source_channel as ( select * from {{ source('wetube', 'channel') }} ), source_channel_subs as ( select * from {{ source('wetube','channel_subs') }} ), number_of_subs_by_channel as ( select source_channel.id_channel, source_channel.name, count(source_channel_subs.id_subscriber) num_subs from source_channel_subs inner join source_channel using (id_channel) group by 1, 2 ) select * from number_of_subs_by_channel Entendendo o modelo Observe que temos vários scripts separados por expressão de tabela comum (CTE) que se torna útil para entender o código. O DBT permite usar o template Jinja {{ }} trazendo uma maior flexibilidade ao nosso código. O uso da palavra-chave source dentro do modelo Jinja significa que estamos nos referindo a tabelas de origem. Para referenciar um modelo, você precisa usar a palavra-chave ref. A última instrução SELECT baseada nas tabelas de origem (source) irá gerar o modelo (model) como tabela no banco de dados. Executando o nosso primeiro modelo Execute o comando abaixo para criar nosso primeiro modelo baseado nos arquivos anteriores. dbt run Saída Criando um novo modelo Imagine que precisamos criar um novo modelo contendo as informações da conta e seus canais. Vamos voltar ao arquivo schema.yml para adicionar esse novo modelo. - name: account_information description: "Model containing account information and it's channels" columns: - name: id_account description: "Account ID" tests: - not_null - name: first_name description: "First name of user's account" tests: - not_null - name: last_name description: "Last name of user's account" tests: - not_null - name: email description: "Account's email" tests: - not_null - name: city_name description: "city's name" tests: - not_null - name: state_name description: "state's name" tests: - not_null - name: id_channel description: "channel's Id" tests: - not_null - name: channel_name description: "channel's name" tests: - not_null - name: channel_creation description: "Date of creation name" tests: - not_null Agora, vamos criar um novo arquivo SQL e nomeá-lo como account_information.sql e adicionar os scripts abaixo: with source_channel as ( select * from {{ source('wetube', 'channel') }} ), source_city as ( select * from {{ source('wetube','city') }} ), source_state as ( select * from {{ source('wetube','state') }} ), source_user_address as ( select * from {{ source('wetube','user_address') }} ), source_account as ( select * from {{ source('wetube','account') }} ), account_info as ( select account.id_user as id_account, account.first_name, account.last_name, account.email, city.name as city_name, state.name as state_name, channel.id_channel, channel.name as channel, channel.creation_date as channel_creation FROM source_account account inner join source_channel channel on (channel.id_account = account.id_user) inner join source_user_address user_address using (id_user) inner join source_state state using (id_state) inner join source_city city using (id_city) ) select * from account_info Criando nosso último modelo Para o nosso último modelo, vamos criar um modelo sobre quantas curtidas tem um vídeo. Vamos alterar novamente o schema.yml para descrever e documentar nosso futuro e último modelo. - name: total_likes_by_video description: "Model containing total of likes by video" columns: - name: id_channel description: "Channel's Id" tests: - not_null - name: channel description: "Channel's name" tests: - not_null - name: id_video description: "Video's Id" tests: - not_null - name: title description: "Video's Title" tests: - not_null - name: total_likes description: "Total of likes" tests: - not_null Crie um arquivo chamado total_likes_by_video.sql e coloque o código abaixo: with source_video as ( select * from {{ source('wetube','video') }} ), source_video_like as ( select * from {{ source('wetube','video_like') }} ), source_account_info as ( select * from {{ ref('account_information') }} ), source_total_like_by_video as ( select source_account_info.id_channel, source_account_info.channel, source_video.id_video, source_video.title, count(*) as total_likes FROM source_video_like inner join source_video using (id_video) inner join source_account_info using (id_channel) GROUP BY source_account_info.id_channel, source_account_info.channel, source_video.id_video, source_video.title ORDER BY total_likes DESC ) select * from source_total_like_by_video Executando novamente Após a criação dos arquivos, vamos executar DBT novamente para criar os novos modelos dbt run Saída Os modelos foram criados no banco de dados e você pode executar instruções select diretamente em seu banco de dados para verificá-lo. Perceba que além dos modelos criados, você pode notar as demais tabelas que foram mapeadas no arquivo schema.yml e que já existiam na estrutura do banco inicial. Lembre-se do mecanismo de criar tabelas estáticas através do diretório Seeds, pode ser uma boa escolha para uma carga inicial. Modelo: account_information Modelo: number_of_subs_by_channel Modelo: total_likes_by_video Passo 6: DBT Docs Documentação Depois de gerados nossos modelos, agora vamos gerar documentos com base nestes. O DBT gera uma documentação completa sobre modelos (models), sources e suas colunas, através de uma página da web. Gerando as docs dbt docs generate Disponibilizando as docs no servidor Web Após a geração dos documentos, você pode executar o comando abaixo no seu terminal para iniciar um servidor da Web na porta 8080 e consultar a documentação localmente utilizando o seu navegador. Caso o navegador não abra automaticamente, digite o seguinte endereço localhost:8080 no seu navegador. dbt docs serve Lineage Outro detalhe sobre a documentação é que você pode ver através de um Lineage os modelos e suas dependências. Código no Github Você pode conferir esse código na nossa página do Github. Curtiu? Eu espero que tenha gostado!
- Diferenças entre tabelas externas e internas usando Hive
Existem duas formas de criar tabelas no contexto Hive e neste post vamos mostrar as diferenças, vantagens e desvantagens. Tabelas Internas Para entender melhor, vamos criar uma tabela interna usando SQL no contexto Hive e falaremos sobre as suas vantagens e desvantagens. create table coffee_and_tips_table (name string, age int, address string) stored as textfile; Vantagens Tabelas internas são gerenciadas pelo Hive. Desvantagens Tabelas internas não podem acessar serviços de armazenamento remoto, por exemplo, em nuvens como Amazon AWS, Microsoft Azure e Google Cloud. Ao apagar (drop table) as tabelas internas, todos os dados, incluindo metadados e partições, serão perdidos. Tabelas externas As tabelas externas possuem recursos interessantes se comparado as tabelas internas, e é uma abordagem recomendada quando precisamos criar tabelas para nossos projetos usando Hive. No script abaixo, você pode ver a diferença entre a criação da tabela interna e a tabela externa relacionada à última seção. Acabamos de adicionar a palavra reservada external como forma de identificar uma tabela externa para a criação. create external table coffee_and_tips_external (name string, age int, address string) stored as textfile; Vantagens Os dados e metadados não serão perdidos caso a tabela seja apagada (drop table). Tabelas externas podem ser acessadas e gerenciadas por processos externos. Tabelas externas permitem acesso ao serviço de armazenamento remoto como um local de origem. Desvantagens Não seria bem uma desvantagem, mas caso seja necessário alterar o esquema ou apagar uma tabela, provavelmente será necessário executar um comando de reparação da tabela, conforme mostrado abaixo. msck repair table Dependendo do volume, esta operação pode levar algum tempo para ser concluída. Para verificar se uma tabela é interna ou externa, execute o seguinte comando abaixo e você verá na coluna table_type o resultado. hive> describe formatted Material de estudo Se quer aprender mais sobre o assunto e alcançar um alto nível de conhecimento, recomendo fortemente a leitura do(s) seguinte(s) livro(s): Programming Hive (Versão Inglês) este guia introduz você ao mundo do Apache Hive, a infraestrutura de data warehouse do Hadoop. Você aprenderá rapidamente como usar o dialeto SQL do Hive (HiveQL), consultar e analisar grandes conjuntos de dados armazenados no sistema de arquivos distribuído do Hadoop além de ensinar a como configurar um ambiente Hive. Spark: The Definitive Guide: Big Data Processing Made Simple (Versão Inglês) é uma referência completa para quem quer aprender o Spark e sobre as suas principais funcionalidades. Lendo esse livro, você vai aprender sobre DataFrames, Spark SQL através de exemplos práticos. O autor mergulha nas APIs de baixo nível do Spark, RDDs e também sobre como o Spark é executado em um cluster e como depurar e monitorar os aplicativos de clusters do Spark. Os exemplos práticos estão em Scala e Python. Beginning Apache Spark 3: With Dataframe, Spark SQL, Structured Streaming, and Spark Machine Library (Versão Inglês) com a nova versão do Spark, este livro explora os principais recursos do Spark, como o uso de Dataframes, Spark SQL no qual você pode usar SQL para manipular dados e Structured Streaming para processar dados em tempo real. Este livro contém exemplos práticos e trechos de código para facilitar a leitura. High Performance Spark: Best Practices for Scaling and Optimizing Apache Spark (Versão Inglês) é um livro que explora as melhores práticas usando a linguagem Spark e Scala para lidar com aplicações de dados em larga escala, técnicas para transformações utilizando RDD, e também mostra como as novas interfaces do Spark SQL melhoram o desempenho sobre a estrutura de dados RDD do SQL, exemplos de Spark MLlib e o uso de bibliotecas de aprendizado de máquina de ML e muito mais. Bom é isso, espero que tenham gostado!
- Criando um projeto Spring Boot no Intellij IDEA
Em alguns momentos precisamos criar um novo projeto por várias razões: estudo, trabalho ou testes. Existem uma série de ferramentas que nos ajudam nesse processo, nesse tutorial vou mostrar como podemos criar um novo projeto Spring Boot diretamente do Intellij IDEA. Para este tutorial estou utilizando a última versão do Intellij IDEA (2023.1). Criando o Projeto: A primeira etapa é criar o projeto, para isso podemos ir no seguinte caminho dentro da IDE: File > New > Project Logo após, você deve selecionar a opção Spring Initializr e preencher as informações do projeto: Nesta janela você pode preencher: Name: nome do seu projeto Location: local onde o projeto será salvo Language: linguagem de programação do projeto Type: tipo de gerenciador de pacotes que será utilizado Gradle ou Maven Group: nome da base de pacotes do projeto Artifact: nome do artefato Package name: nome da base de pacotes que será organizado o projeto Jdk: caminho para a jdk a ser utilizada no projeto Packaging: tipo de pacote que será gerado do projeto ao buildar, geralmente se utilizar o Jar Após preencher tudo cliente em NEXT. Na próxima tela você poderá selecionar quais frameworks serão utilizados, como por exemplo Spring Web: Selecione os frameworks que você deseja para seu projeto, em seguida clique em CREATE. Após isso seu projeto estará pronto. Pode começar a codar ! Links: Intellij IDEA - https://www.jetbrains.com/idea/
- Versionamento de Banco de dados com Flyway e Spring boot
Quando estamos desenvolvendo microserviços, um dos itens que buscamos é ter serviços alto contidos. Dessa forma um dos pontos que costumam ficar de fora em vários casos é o banco de dados. Um framework que ajuda a versionar o banco dados através de scripts é o Flyway. O Flyway nos ajuda a tratar todas as mudanças que serão realizadas no banco de dados através de um projeto spring-boot. Ele faz uso de scripts SQL e alguns metadados para gerenciar o estado e as mudanças do banco de dados. A vantagem de utilizar tal framework é que qualquer um que esteja desenvolvendo no projeto vai ter o mesmo estado do banco de dados, geralmente uma cópia do banco de dados de desenvolvimento ou produção. Nesse artigo vou mostrar como configurar o Flyway em um projeto Spring Boot. Criando o projeto Para criar o projeto vamos utilizar o site oficial do Spring. Primeiramente acesse o site:: https://start.spring.io/ Quando a página estiver carregada, configure as informações conforme a imagem abaixo: Quando estiver finalizado basta clicar em GENERATE para baixar o projeto configurado. Assim que realizar o download, você pode importar para sua IDE preferida. Eu vou utilizar o Intellij Idea (https://www.jetbrains.com/idea/). Entendendo o Flyway Se você abrir o arquivo pom.xml, você irá ver a dependência do flyway-core: Dentro da estrutura do projeto você encontrará a pasta db.migration, nela vamos salvar os scripts do banco de dados. Quando o projeto iniciar uma das tarefas durante o processo de inicialização é verificar se há algum novo script no projeto, havendo qualquer script ele irá aplicar no banco de dados. Para criar nosso novo script, precisamos seguir alguns padrões no nome do arquivo. Esse padrão precisa ter um número que será incrementado a cada novo script. Dessa forma ajudamos o flyway a entender que se trata de um script não executado. Para simplificar esse tutorial vamos criar um simples script que irá seguir o padrão V1, V2, V3 para incrementar o arquivo. No final o nome é o seguinte: V1__create_base_tables.sql Criando nosso primeiro script Crie um novo arquivo chamado V1_create_base_tables.sql dentro da pasta db.migration e adicione o conteúdo abaixo: Configurando o banco de dados Para simplificar ainda mais o tutorial, eu utilizei o banco de dados H2 (banco em memória) para mostrar o funcionamento do flyway. Para configurar esse banco no nosso projeto, abra o arquivo pom.xml e adicione a seguinte dependência: Logo em seguida vamos colocar os dados para conexão no banco de dados. Dentro do arquivo application.properties adicione as seguintes configurações: Após isso podemos executar o projeto, nos logs vamos ver algo parecido com isso durante a execução: 2023-04-07 14:12:29.896 INFO 8012 --- [ main] o.f.c.i.database.base.BaseDatabaseType : Database: jdbc:h2:mem:testdb (H2 2.1) 2023-04-07 14:12:30.039 INFO 8012 --- [ main] o.f.core.internal.command.DbValidate : Successfully validated 1 migration (execution time 00:00.037s) 2023-04-07 14:12:30.055 INFO 8012 --- [ main] o.f.c.i.s.JdbcTableSchemaHistory : Creating Schema History table "PUBLIC"."flyway_schema_history" ... 2023-04-07 14:12:30.132 INFO 8012 --- [ main] o.f.core.internal.command.DbMigrate : Current version of schema "PUBLIC": << Empty Schema >> 2023-04-07 14:12:30.143 INFO 8012 --- [ main] o.f.core.internal.command.DbMigrate : Migrating schema "PUBLIC" to version "1 - create base tables" 2023-04-07 14:12:30.177 INFO 8012 --- [ main] o.f.core.internal.command.DbMigrate : Successfully applied 1 migration to schema "PUBLIC", now at version v1 (execution time 00:00.057s) 2023-04-07 14:12:30.477 INFO 8012 --- [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [name: default] Este log mostra que a execução da atualização do banco aconteceu com sucesso. Quando um novo script for adicionado, como por exemplo V2__new_tables.sql, o flyway irá executar somente o novo script V2. Observação: neste caso estamos utilizando um banco de dados em memória, toda vez que a aplicação parar, todos os dados contidos nela serão liberados. Portanto sempre iremos iniciar o banco do zero. Para os próximos tutoriais, vamos explorar cenários parecidos com casos reais. Conclusão O versionamento do banco de dados trás algumas vantagens como dar aos desenvolvedores uma cópia exata do banco de dados. Quando há alguma modificação a própria aplicação irá atualizar e gerenciar todas as mudanças, podendo aplicar tanto em desenvolvimento e produção. Referências Para mais detalhes você pode checar a documentação oficial do Spring: https://docs.spring.io/spring-boot/docs/current/reference/html/howto.html#howto.data-initialization.migration-tool.flyway Criando migrations: https://flywaydb.org/documentation/tutorials/baselineMigrations H2 database http://www.h2database.com/html/tutorial.html
- Tutorial DynamoDB utilizando AWS SDK e Java
O DynamoDB é um banco de dados chave-valor e documentos. Indicado para aplicações que necessitam de um super desempenho em leituras e escritas com baixa latência. O DynamoDB pode processar mais de 20 trilhões de solicitações por dia e mais de 20 milhões de solicitações por segundo. A estrutura do DynamoDB é um pouco diferente dos bancos relacionais, não se cria um banco e suas tabelas. Todas as tabelas são criadas de forma descentralizadas. Para conectar nestas tabelas, basta utilizar a SDK da AWS. Não existe um driver JDBC que nem usamos em bancos relacionais para conecta-los. Para este tutorial vamos criar alguns exemplo de acesso ao DynamoDB criando e lendo itens utilizando a AWS SDK, Java como linguagem de programação e Maven como Build Tool. Maven * Adicionamos a dependência do Lombok para auxiliar na criação do modelo a seguir. Criando o modelo Vamos criar o modelo que utilizaremos como uma instância dos itens que serão adicionados no DynamoBD. Entendendo as anotações da classe Book: @Data Anotação do Lombok que substituirá os getters e setters para cada campo. Estamos utilizando o Lombok apenas para deixar o código menos verboso. Não possui relação direta com o DynamoDB. @DynamoDBTable Anotação da SDK da AWS DynamoDB que define a classe como uma tabela destino do DynamoBD. Veja que é possível passar como parâmetro o nome da tabela que será Books. @DynamoDBHashKey Esta anotação define uma chave de partição, de forma resumida, seria uma espécie de chave primária. Para o nosso exemplo, o campo isbn será definida como campo chave na tabela Books no DynamoDB. @DynamoDBAttribute Na prática, cada campo mapeado no modelo será um campo da tabela de destino Books no DynamoDB. A anotação @DynamoDBAttribute pode ser utilizada para caso você precise definir um nome diferente do que foi declarado no modelo. Por ex: O campo publishingCompany será definido na tabela como publishing_company e os demais serão criadas conforme foram declarados no modelo. Nesse caso, mapeamos todos eles para manter um padrão. Existem várias outras anotações que podem ser utilizadas, basta acessar a documentação para entender um pouco mais. Criando a configuração de acesso ao Dynamo O próximo código será utilizado para conectar ao serviço do DynamoDB na AWS e criar uma instância responsável por manipular os itens. Entendendo a classe DynamoConfig: O objeto amazonDynamoDB é uma instância do tipo AmazonDynamoDB que será responsável em recuperar os recursos necessários para o acesso ao DynamoDB. O método getAmazonDynamoDB( ) conectará na AWS através de suas credencias de sua conta na região US-EAST-1. Caso utilize outra região é só alterar o enum Regions. O método getDynamoDBMapper( ) criará um um objeto do tipo DynamoDBMapper. Perceba que ele cria uma instância a partir do objeto amazonDynamoDB, responsável por manter a conexão com o serviço do AWS DynamoDB. Um objeto do tipo DynamoDBMapper permite invocar operações do tipo CRUD, segue alguns dos métodos disponíveis: save load delete query scan scanPage As operações estão disponíveis nesta doc. Criando o DAO A classe BookDAO é a classe que contém os métodos responsáveis em acessar o DynamoBD e manipular os itens. Entendendo a classe BookDAO: Conforme falamos anteriormente, o objeto dynamoMapper fornece as operações necessárias para manipular um item Método save(Book book) persistirá o item na tabela Books Método delete(Book book) é responsável por remover o item da tabela Books Método findByIsbn(String isbn) executa uma consulta nos itens filtrando pela chave isbn. Dentro deste método invocamos o método load(Class clazz, Object hashKey) do DynamoMapper que nos obriga a passar o tipo do objeto e a chave de busca. Executando o código Antes de executar o código, vamos criar a tabela Books utilizando o console do DynamoDB. Acesse o DynamoDB conforme imagem Clique em Criar Tabela e uma nova página será aberta No campo Nome da Tabela, digite Books No campo Chave primária, digite isbn. Para finalizar, clique em Criar. Após executar as etapas anteriores, vamos criar um código que executará um fluxo de criação de um Item, consulta e por fim, vamos deletá-lo. Após executar o código, verifique no console o resultado do fluxo. Paginando uma consulta utilizando scanPage O método scanPage faz parte do pacote de operações disponíveis na classe DynamoDBMapper. Utilizando este método é possível criar consultas mais completas utilizando paginação. No próximo exemplo vamos utilizar este método junto com expressões que pode deixar bem flexível a consulta utilizando diversos filtros. O método acima foi criada para exemplificar uma forma mais dinâmica e completa para fazer consultas no DynamoDB de forma mais segura. Utilize o scanPage ao invés do scan. Pois este faz uma leitura de toda a tabela que pode sair um pouco caro, lembrando que uma das formas de cobrança do DynamoDB são as quantidades de consultas. Imagine uma tabela com milhões de registro, a cobrança pode ser bem alta. É isso, curtiu? Até mais!
- Entendendo AWS Lambda em 3 minutos
AWS Lambda é um serviço de computação sem servidor, também conhecido como Serverless. A execução do Lambda permite que você crie aplicativos de back-end usando diferentes linguagens de programação como Java, Python, Node.js, .Net, Ruby, Go e muito mais. A melhor parte do Lambda é que você não precisa se preocupar com servidores de aplicação para implantá-lo e executá-lo. Sem preocupações com as responsabilidades de capacidade de provisionamento que geralmente são utilizados em aplicações tradicionais como aplicações Web, onde requer o redimensionamento dependendo do tráfego, tornando-se uma alternativa mais barata para compor arquiteturas. Como funciona Lambdas também são usados para compor arquiteturas sendo responsáveis por cargas de trabalho específicas. Por exemplo, usando o Lambda, você pode começar a capturar/escutar arquivos de um S3 Bucket para efetuar algum tipo de normalização ou também pode usar o EventBridge (Cloudwatch events) criando agendamentos por meio de uma expressão cron para acionar o Lambda executando cargas de trabalho e depois encerrar o mesmo. Conforme mostrado na imagem abaixo, temos alguns exemplos de serviços que integram-se com o Lambda, dessa forma você pode usá-los para invocar os Lambdas para uma variedade de cenários. Limitações Lambdas podem ser executados por até 15 minutos, ou seja, seu timeout é de no máximo 15 minutos ou 900 segundos. Portanto, se for usá-lo, atente-se ao lidar com cargas de trabalho que levam mais de 15 minutos. Integrações Conforme mencionado anteriormente, o AWS Lambda permite que várias integrações de serviços sejam usadas como um gatilho/trigger. Se você deseja escutar objetos criados no S3 Bucket, pode usar o S3 como trigger. Se você precisar processar notificações do SNS, também poderá definir o Amazon Simple Notification Service (SNS) como o trigger e o Lambda receberá todas as notificações para serem processadas. Observe que temos diferentes cenários em que o Lambda pode resolver soluções com eficiência. Aqui você pode ver uma lista completa sobre os serviços integrados. Preços A AWS possui certas políticas sobre o uso de cada serviço. Lambdas são basicamente cobrados pelo número de requisições e pelo tempo de execução do código. Para mais detalhes, veja aqui. Casos de Uso Aqui teremos alguns exemplos onde o uso do Lambda pode ser uma opção interessante. Processamento de dados: imagine que você deve normalizar arquivos não estruturados em semi-estruturados para serem lidos por algum processo. Neste caso é possível escutar um Bucket S3 procurando por novos objetos para serem transformados usando o Lambda. Segurança: um Lambda que atualiza o Token de usuários de um aplicativo Transformação de dados: Você pode usar o Kinesis/Firehose como um gatilho. Neste caso, O Lambda ouvirá cada evento gerado pelo Kinesis, transformá-lo e enviá-lo de volta ao próprio Kinesis para que os dados possam ser entregues ao S3. Benefícios Preço: Pague apenas por requisições e tempo de execução do código Serverless: Não há necessidade de um servidor de aplicação Integrado: o Lambda fornece integração com boa parte dos serviços da AWS Linguagem de Programação: É possível utilizar as principais linguagens de programação Escala e concorrência: Permite controlar a concorrência e dimensionar o número de execuções até o limite da conta Material de estudo Se quer aprender mais sobre o assunto e alcançar um alto nível de conhecimento, recomendo fortemente a leitura do(s) seguinte(s) livro(s): AWS Cookbook (Versão Inglês) é um guia prático contendo 70 receitas detalhadas sobre os recursos da AWS e como resolver diferentes desafios. É um livro bem escrito e de fácil entendimento cobrindo os principais serviços da AWS através de exemplos práticos. A AWS ou Amazon Web Services é o serviço de nuvem mais utilizando atualmente em todo o mundo, caso queira entender mais sobre o tema para ficar bem posicionado no mercado, recomendo fortemente o estudo. Espero que tenha curtido!
- Entendendo Delta Lake - Time Travel em 2 minutos
O Delta Lake fornece uma maneira de controlar a versão dos dados para operações como merge, update e delete. Isso torna transparente o funcionamento do ciclo de vida dos dados gerenciados pelo próprio Delta Lake. Para cada operação, uma versão é incrementada e se você tiver uma tabela com múltiplas operações, diferentes versões de tabela serão criadas. Delta Lake oferece um mecanismo para navegar pelas diferentes versões chamado Time Travel. É uma forma temporária de acessar dados do passado. Para este Post, usaremos esse recurso para navegar por diferentes versões da tabela. Abaixo, temos uma Tabela Delta chamada people onde três versões foram geradas através de operações de escrita usando o modo append. Versão Atual Quando realizamos uma simples leitura em uma tabela, a versão atual é sempre a mais recente. Portanto, para este cenário, a versão atual é 2 (dois). Observe que não precisamos especificar qual versão queremos usar, porque ainda não estamos usando o Time Travel. session.read().format("delta").load("table/people") .orderBy("id").show(); Até aqui, nada mudou, vamos para os próximos passos. Trabalhando com Time Travel Agora vamos começar a explorar esta feature chamada Time Travel, para as próximas etapas, faremos leituras na tabela people especificando diferentes versões para entender como funciona esta feature. Leitura Tabela Delta - Versão 0 (zero) Como falado anteriormente, temos três versões dessa tabela, para o exemplo a seguir, vamos definir para que na leitura seja carregado dados da versão zero. session.read().format("delta") .option("versionAsOf", 0) .load("table/people") .orderBy("id").show(); Observe que adicionamos um novo parâmetro chamado versionAsOf , este parâmetro nos permite configurar o número da versão em que você deseja restaurar temporariamente para uma tabela. Para este cenário configuramos a leitura da Tabela Delta versão zero (0). Esta foi a primeira versão gerada pelo Delta Lake após a primeira operação de escrita. Leitura Tabela Delta - Versão 1(um) Para esta última etapa, estamos utilizando a versão um (1), observe que os dados da versão anterior (0) foram mantidos. session.read().format("delta") .option("versionAsOf", 1) .load("table/people") .orderBy("id").show(); Delta Lake fornece muitos benefícios e Time travel nos permite flexibilidade em uma arquitetura Big Data, para obter mais detalhes, recomendo ver as docs do Delta Lake. Material de estudo Se quer aprender mais sobre o assunto e alcançar um alto nível de conhecimento, recomendo fortemente a leitura do(s) seguinte(s) livro(s): Spark: The Definitive Guide: Big Data Processing Made Simple (Versão Inglês) é uma referência completa para quem quer aprender o Spark e sobre as suas principais funcionalidades. Lendo esse livro, você vai aprender sobre DataFrames, Spark SQL através de exemplos práticos. O autor mergulha nas APIs de baixo nível do Spark, RDDs e também sobre como o Spark é executado em um cluster e como depurar e monitorar os aplicativos de clusters do Spark. Os exemplos práticos estão em Scala e Python. Beginning Apache Spark 3: With Dataframe, Spark SQL, Structured Streaming, and Spark Machine Library (Versão Inglês) com a nova versão do Spark, este livro explora os principais recursos do Spark, como o uso de Dataframes, Spark SQL no qual você pode usar SQL para manipular dados e Structured Streaming para processar dados em tempo real. Este livro contém exemplos práticos e trechos de código para facilitar a leitura. High Performance Spark: Best Practices for Scaling and Optimizing Apache Spark (Versão Inglês) é um livro que explora as melhores práticas usando a linguagem Spark e Scala para lidar com aplicações de dados em larga escala, técnicas para transformações utilizando RDD, e também mostra como as novas interfaces do Spark SQL melhoram o desempenho sobre a estrutura de dados RDD do SQL, exemplos de Spark MLlib e o uso de bibliotecas de aprendizado de máquina de ML e muito mais. Python Crash Course, 2nd Edition: A Hands-On, Project-Based Introduction to Programming (Versão Inglês) abrange os conceitos básicos do Python por meio de exemplos interativos e práticas recomendadas. Learning Scala: Practical Functional Programming for the Jvm (Versão Inglês) é um excelente livro que aborda a linguagem Scala através de exemplos e exercícios práticos. Lendo este livro, você aprenderá sobre os principais tipos de dados, literais, valores e variáveis. Construir classes que compõem uma ou mais características para total reutilização, criar novas funcionalidades misturando-as na instanciação e muito mais. Scala é uma das principais linguagens em projetos de Big Data em todo o mundo, com grande uso em grandes empresas de tecnologia como o Twitter e também a linguagem principal do Spark. Bom é isso, espero que tenham gostado!
- Java Streams API - Filter
Desde o Java 8 lançado em 2014 foram adicionados dezenas de novas funcionalidades dentre melhorias na JVM e funções para facilitar a vida do desenvolvedor, pois ele merece. Dentre estas features, estão as Expression Lambda (EL) que foi o ponta pé inicial para a entrada do Java no mundo da programação funcional, melhoria na API de data e a não necessidade de criar implementações de Interfaces já existentes com a utilização de Default methods. E a outra novidade é a API de Streams, o foco desse post. A Stream API é uma nova abordagem para se trabalhar com Collections deixando o código menos verboso e mais inteligente. A Stream API trabalha com o processamento de dados sob demanda e fornece dezenas de funcionalidades para manipular Collections diminuindo o código e simplificando o desenvolvimento em uma espécie de pipeline que será explicado mais a frente. Para entender melhor, vamos criar um código simples de uma lista de objetos que será percorrida e nela vamos criar algumas condições afim de extrair uma nova lista com os valores desejados. Neste exemplo não utilizaremos Streams API. Vamos criar um Classe representando a entidade Cidade no qual terá como atributos: nome, estado e população. E por fim um método chamado listaCidades que carrega uma lista de objetos do tipo Cidade. Filter No próximo código, vamos percorrer uma lista, e dentro da iteração será verificado quais cidades possuem uma população maior do que 20 e em seguida adicionada em uma lista secundária. Até então, tecnicamente não existe problemas com o código acima. Mas poderia ser menos verboso e mais prático. Agora, utilizando Stream API, segue um novo exemplo. Perceba a diferença, invocamos o método listaCidades e por este retornar uma Collection, é possível invocar o método Stream. A partir da chamada do método stream() se dá início a pipeline. Mais exemplos de Filter Exemplo 1: Saída: Cidade: Hollywood /Estado: CA /População: 30 Cidade: Venice /Estado: CA /População: 10 Exemplo 2: Saída: Cidade: Venice /Estado: CA /População: 10 Como funciona a pipeline? Seguindo o exemplo anterior, a pipeline é um processo sequencial que se diferencia entre operações intermediárias e finais. No exemplo, a Stream é invocada a partir de uma fonte de dados (lista de objetos do tipo Cidade) que trabalha sob demanda, o método filter é uma operação intermediária, ou seja, ela processa os dados até que o método collect é invocado, originando uma operação final. Material de estudo Se quer aprender mais sobre o assunto e alcançar um alto nível de conhecimento, recomendo fortemente a leitura do(s) seguinte(s) livro(s): Use a cabeça: Java é um clássico onde qualquer iniciante no assunto deve ler e estudar. Neste livro você aprenderá sobre os principais pilares de Java como, orientação a objetos, criação de classes, interfaces e seu funcionamento, controlar exceções, objetos genéricos e muito mais. Se quer entrar de cabeça neste mundo, é uma excelente opção! Padrões de Projeto é um livro no qual recomendamos após alcançar uma certa maturidade em programação em geral. Escrito por grandes nomes do assunto e traduzido para o português, Padrões de Projeto ou Design patterns como também são conhecidos, são padrões e estratégias que te ajudará a resolver diferentes desafios arquiteturais, aplicando soluções de forma elegante. São estratégias em que desenvolvedores de todo o mundo tem adotado em seus projetos. Imagina se você precisa atuar em um projeto internacional, caso este projetos tem adotado estratégias de Padrões de projeto, você não terá nenhuma grande dificuldade em entender a dinâmica e a arquitetura do código ou caso contrário, você mesmo poderá aplicar os conhecimentos adquiridos através deste livro. O mais interessante que Padrões de Projeto independem de linguagem de programação, é possível aplicar em qualquer outra linguagem, ou seja, é um conteúdo 100% reutilizável. Java Efetivo escrito por Joshua Bloch e traduzido para o português, é um livro excelente para aqueles que possuem um pouco mais de experiência com Java mas que precisam aprofundar em detalhes mais específicos da linguagem como, quando e como usar específicos Padrões de Projeto ou Design Patterns, utilização de Lambdas e Streams, concorrências e serializações. Para aqueles que possuem mais de experiência, é um excelente material de consulta. E aí, Curtiu? Até mais!
- Java: Streams API - findFirst()
Java 8 Streams introduziu diferentes métodos para manipular coleções. Um destes métodos é o findFirst(), que permite retornar o primeiro elemento de uma Stream através de uma instância Optional. Na prática Output Item: Monica Souza Utilizando filter Output Item: Andre Silva Perceba que retornou o primeiro nome com sobrenome Silva da coleção. A não utilização de Streams Se utilizarmos o modo tradicional, ou seja, sem a utilização de Streams. O código ficaria assim, filtrando pelo sobrenome "Silva" Neste caso dependemos do break para encerrar a execução. Material de estudo Se quer aprender mais sobre o assunto e alcançar um alto nível de conhecimento, recomendo fortemente a leitura do(s) seguinte(s) livro(s): Use a cabeça: Java é um clássico onde qualquer iniciante no assunto deve ler e estudar. Neste livro você aprenderá sobre os principais pilares de Java como, orientação a objetos, criação de classes, interfaces e seu funcionamento, controlar exceções, objetos genéricos e muito mais. Se quer entrar de cabeça neste mundo, é uma excelente opção! Padrões de Projeto é um livro no qual recomendamos após alcançar uma certa maturidade em programação em geral. Escrito por grandes nomes do assunto e traduzido para o português, Padrões de Projeto ou Design patterns como também são conhecidos, são padrões e estratégias que te ajudará a resolver diferentes desafios arquiteturais, aplicando soluções de forma elegante. São estratégias em que desenvolvedores de todo o mundo tem adotado em seus projetos. Imagina se você precisa atuar em um projeto internacional, caso este projetos tem adotado estratégias de Padrões de projeto, você não terá nenhuma grande dificuldade em entender a dinâmica e a arquitetura do código ou caso contrário, você mesmo poderá aplicar os conhecimentos adquiridos através deste livro. O mais interessante que Padrões de Projeto independem de linguagem de programação, é possível aplicar em qualquer outra linguagem, ou seja, é um conteúdo 100% reutilizável. Java Efetivo escrito por Joshua Bloch e traduzido para o português, é um livro excelente para aqueles que possuem um pouco mais de experiência com Java mas que precisam aprofundar em detalhes mais específicos da linguagem como, quando e como usar específicos Padrões de Projeto ou Design Patterns, utilização de Lambdas e Streams, concorrências e serializações. Para aqueles que possuem mais de experiência, é um excelente material de consulta.
- Spring Boot e ActiveMQ
Apache ActiveMQ é um servidor de mensageria de código aberto utilizado por grandes players do mercado que utilizam arquiteturas open-source. Mas qual é a proposta do ActiveMQ? Antes de entender o que é o ActiveMQ, temos que pensar em problemas comuns em aplicações que precisam escalar e integrar melhor seus serviços. Hoje o fluxo de informações trafegadas é infinitamente maior que 10 anos atrás e é quase impossível mensurar capacidade em termos de escalabilidade que uma aplicação pode suportar. Para entendermos melhor, vamos imaginar que você foi contratado para projetar uma arquitetura de um e-commerce que fará vendas de ingressos dos jogos da campeonato brasileiro. Como sempre você tem pouco tempo para pensar uma arquitetura. A primeira ideia é simples e rápida, o resultado é este desenho. Levando em conta a quantidade de acessos e requisições por segundo, você acha uma arquitetura resiliente? Será que o banco de dados escala? Será que o banco suporta multi-acessos? E se o banco por algum motivo cair, a compra será perdida? Podemos melhorar um pouco mais essa arquitetura deixando ela um pouco mais profissional e resiliente. Vamos lá. Vamos entender este último desenho. Agora, ao efetuar um pedido de compra os pedidos são enviados para um servidor de mensagens (Fila). A ideia da Fila é basicamente um serviço capaz de alocar mensagens. Normalmente são textos ou texto em formato Json. Neste desenho podemos dizer que a Fila aloca dados do cliente, quantidade de ingressos, valores e etc. E por fim, existe uma aplicação que faz todo o gerenciamento dos pedidos/compras. Esta aplicação lê/remove as mensagens da Fila podendo fazer validações antes de gravar no banco de dados. Agora, vamos supor que um dos requisitos é para cada venda, o cliente deve receber uma nota fiscal do ingresso. Como a nova arquitetura está bem desacoplada, ficou mais fácil "plugar" uma nova aplicação para fazer este trabalho. Daí você pensou em um novo desenho, segue: Agora a aplicação que gerencia as compras, além de gravar a venda após recuperar as mensagens na fila 1, ela envia uma mensagem também para a fila 2, onde alocará as notas fiscais dos clientes. E uma nova aplicação que gerencia as notas fiscais recupera estas mensagens e grava em uma base especifica para o setor financeiro. Mas quais os benefícios dessa nova arquitetura? A arquitetura está mais resiliente, assíncrona e tolerável a falhas, pois caso umas das aplicações por algum motivo falhe, a mensagem retorna para a fila até o reestabelecimento das aplicações. E por fim, facilita a integração de novas aplicações. E o ActiveMQ? O que ele tem haver com isso? O ActiveMQ é o serviço que provê o servidor de mensagens. No desenho, ele seria os servidores de mensagens (Filas). Lembrando que os desenhos foram uma forma de abrir a cabeça quanto a utilidade de Filas. Para entender melhor ainda, vamos apresentar um exemplo na prática de como configurar e utilizar o ActiveMQ com Spring Boot e JMS. Criando o projeto Acesse o https://start.spring.io para criar o projeto e escolher as dependências. Preencha os campos e selecione as 2 dependências (ActiveMQ 5 e Spring Web) conforme a imagem. Gere o arquivo e importe para o seu projeto. pom.xml Completo 4.0.0 org.springframework.boot spring-boot-starter-parent 2.4.2 com.spring.active.mq spring-boot-active-mq 0.0.1-SNAPSHOT spring-boot-active-mq Demo project for Spring Boot 1.8 org.springframework.boot spring-boot-starter-activemq org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-maven-plugin Instalando o ActiveMQ Vamos fazer o download do ActiveMQ para que o processo fique mais transparente. Mas também existe a possibilidade em utilizar a versão embutida do Spring Boot, mas dessa vez vamos apresentar da forma mais tradicional. Para este exemplo, vamos utilizar a versão clássica do ActiveMQ. Download: https://activemq.apache.org/components/classic/download/ Faça a instalação conforme seu sistema operacional: https://activemq.apache.org/getting-started Após a instalação, inicie o servidor conforme a documentação. Preenchendo o arquivo application.properties Na aplicação Spring-Boot criada, preencha o arquivo application.properties spring.activemq.broker-url=tcp://127.0.0.1:61616 spring.activemq.user=admin spring.activemq.password=admin A primeira linha configura a URL do servidor de mensagens A segunda linha e a subsequente são os dados de autenticação Classe Ticket public class Ticket { private String name; private Double price; private int quantity; public Ticket(){} public Ticket(String name, Double price, int quantity){ this.name = name; this.price = price; this.quantity = quantity; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Double getPrice() { return price; } public void setPrice(Double price) { this.price = price; } public int getQuantity() { return quantity; } public void setQuantity(int quantity) { this.quantity = quantity; } @Override public String toString() { return String.format("Compra de ingresso -> " + "Name=%s, Price=%s, Quantity=%s}", getName(), getPrice(), getQuantity()); } } Na classe SpringBootActiveMqApplication já criada anteriormente pelo gerador, faça a seguinte alteração. @SpringBootApplication @EnableJms public class SpringBootActiveMqApplication { public static void main(String[] args) { SpringApplication.run(SpringBootActiveMqApplication.class, args); } @Bean public JmsListenerContainerFactory defaultFactory( ConnectionFactory connectionFactory, DefaultJmsListenerContainerFactoryConfigurer configurer) { DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory(); configurer.configure(factory, connectionFactory); return factory; } @Bean public MessageConverter jacksonJmsMessageConverter() { MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter(); converter.setTargetType(MessageType.TEXT); converter.setTypeIdPropertyName("_type"); return converter; } } A anotação @EnableJms é o mecanismo responsável por ativar o JMS. O método defaultFactory configura e registra a factory para conectar as filas utilizando JMS. E por fim, o método jacksonJmsMessageConverter faz as conversões das mensagens trafegadas de JSON para o tipo que será passado no JmsTemplate que veremos em breve. Todos estes métodos utilizam a anotação @Bean. Métodos anotados com @Bean são gerenciados pelo contêiner do Spring. Classe TicketController package com.spring.active.mq.springbootactivemq.Controller; import com.spring.active.mq.springbootactivemq.pojo.Ticket; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.jms.core.JmsTemplate; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @RestController public class TicketController { @Autowired private JmsTemplate jmsTemplate; @PostMapping(value = "/buy", consumes = MediaType.APPLICATION_JSON_VALUE) public void buyTicket(@RequestBody Ticket ticket){ jmsTemplate.convertAndSend("compra_queue", new Ticket(ticket.getName(), ticket.getPrice(), ticket.getQuantity())); } } Na classe TicketController, criamos o método chamado buyTicket que será responsável por enviar as mensagens para a fila chamada compra_queue através de uma requisição POST. Neste método utilizamos um objeto do tipo JmsTemplate que possibilita a conversão do objeto e o envio para a fila utilizando JMS. Classe EventListener package com.spring.active.mq.springbootactivemq.listener; import com.spring.active.mq.springbootactivemq.pojo.Ticket; import org.springframework.jms.annotation.JmsListener; import org.springframework.stereotype.Component; @Component public class EventListener { @JmsListener(destination = "compra_queue", containerFactory = "defaultFactory") public void receiveMessage(Ticket ticket) { System.out.println("Mensagem da fila:" + ticket); } } A classe EventListener é uma espécie de "ouvinte". A anotação @JmsListener define esta característica de ouvinte. Nesta mesma anotação é possível configurar o nome da fila que será "ouvida" pelo método. Resumindo, todas a mensagens enviadas para a fila compra_queue serão recebidas por este método. Acessando o serviço de Fila - ActiveMQ Após a inicialização do serviço conforme a documentação, acesse o console do serviço através de um browser http://127.0.0.1:8161/ Criando a fila Para criar a fila, clique na opção Queues na barra superior vermelha, conforme a imagem acima. No campo Queue Name digite nome da fila compra_queue conforme imagem acima e clique no botão Create. Pronto, fila criada! Iniciando a aplicação Via terminal, acesse o diretório do seu projeto e execute o comando Maven abaixo ou inicie via IDE mvn spring-boot:run Enviando mensagens Vamos usar o Postman para o envio das mensagens, caso não tenha o Postman instalado, faça o download acessando este link https://www.postman.com/downloads/ Após a instalação, acesse o Postman e preencha os campos conforme a imagem Conteúdo do Json {"name":"Joao","price":2.0,"quantity":4} Ao clicar no botão Send, acesse o console da aplicação e será possível visualizar a mensagem enviada e trafegada na fila. Acesse novamente o console do ActiveMQ e será possível ver o registro da mensagem que foi enviada para a fila. A coluna Number of Consumers é a quantidade de consumidores da fila, que no caso é realmente 1. A coluna Messages Enqueued mostra a quantidade de mensagens que foram enviadas e por fim, a coluna Messages Dequeued é o número de mensagens que foram removidas da fila. Aqui eu tenho um repositório contendo um projeto SpringBoot com ActiveMQ: https://github.com/jpjavagit/jms-active-mq , vale a pena dar uma olhada! Material de estudo Se quer aprender mais sobre o assunto e alcançar um alto nível de conhecimento, recomendo fortemente a leitura do(s) seguinte(s) livro(s): Spring Microservices in Action (Versão Inglês) cobre os princípios de microserviços utilizando Spring, criação de aplicações Spring Boot utilizando Spring Cloud, resiliência, como fazer o deploy e exemplos da vida real com boas práticas de desenvolvimento. Spring MVC Beginner's Guide: Beginner's Guide (Versão Inglês) cobre os conceitos fundamentais do Spring como a arquitetura, fluxos de requisições, Bean validation, como controlar os fluxos de exceções, utilização de REST e Ajax, Testes e muito mais. Este livro é uma excelente escolha para você que queira entender mais a fundo sobre os fundamentos do Spring. Spring é um Framework Java contendo diferentes projetos, sendo que Spring MVC é um deles. Adquirindo um bom fundamento de Spring MVC, você estará apto para atuar em desafios utilizando qualquer projeto do Framework Spring. Learn Microservices with Spring Boot: A Practical Approach to RESTful Services using RabbitMQ, Eureka, Ribbon, Zuul and Cucumber (Versão Inglês) cobre as principais características do ecosistema Spring utilizando Spring Boot, como a criação de microserviços, arquitetura baseada em eventos, utilização de RabbitMQ como recurso de mensageria, criação de serviços RESTful e muito mais. Este livro é uma excelente escolha para você que deseja conhecer mais sobre o funcionamento e os recursos oferecidos pelo Spring Boot. Use a cabeça: Java é um clássico onde qualquer iniciante no assunto deve ler e estudar. Neste livro você aprenderá sobre os principais pilares de Java como, orientação a objetos, criação de classes, interfaces e seu funcionamento, controlar exceções, objetos genéricos e muito mais. Se quer entrar de cabeça neste mundo, é uma excelente opção! Java Efetivo escrito por Joshua Bloch e traduzido para o português, é um livro excelente para aqueles que possuem um pouco mais de experiência com Java mas que precisam aprofundar em detalhes mais específicos da linguagem como, quando e como usar específicos Padrões de Projeto ou Design Patterns, utilização de Lambdas e Streams, concorrências e serializações. Para aqueles que possuem mais de experiência, é um excelente material de consulta.
- Teste de mutação com Pitest
Como o próprio Pitest se auto intitula, é uma ferramenta que provê o estado da arte para testes de mutação. Foi escrito para rodar em aplicações Java ou em aplicações que rodam em cima de uma JVM. Como funciona? O Pitest funciona gerando códigos mutantes que farão alterações nos bytecodes no código fonte, alterando lógicas, removendo e até alterando valores de retorno de métodos. Dessa forma é possível avaliar o código de uma forma mais completa procurando falhas e fazendo com que o código seja confiável. Exemplo básico de mutação Veja o código abaixo: if(nome == ""){ return "Nome vazio"; }else{ return nome; } Ao rodar o Pitest no código acima, ele é capaz de modificar os bytecodes alterado o código acima para: if(nome != ""){ return nome; }else{ return "Nome vazio";; } Desta forma ele consegue identificar possíveis pontos de falhas e te orientar a criar testes com base nestes pontos. Vamos a prática Maven junit junit 4.12 test org.pitest pitest 1.6.2 Vamos criar uma classe simples representando um conta de banco chamada BankAccount e para ser mais simples vamos implementar a lógica dentro da própria classe de entidade. Nela temos um método chamada userValid que verifica se o usuário é válido. package com.bank.entity; public class BankAccount { public String bankName; public String user; public Double balance; public Boolean userValid(BankAccount bankAccount){ if(bankAccount.user != ""){ return true; }else{ return false; } } } Sem criar nenhuma classe de teste, execute este comando via Maven: mvn org.pitest:pitest-maven:mutationCoverage Veja que no console foi gerado um relatório com as mutações criados com base nas condições que devem ser testadas. Para cada linha acima, foi gerado mutantes e nenhum foi "morto" ainda, ou seja, precisamos criar testes que cubram estes pontos de falhas até que todos os mutantes criados sejam eliminados. Assim o nosso código terá uma cobertura melhor e sem chances de falhas. Por fim a estatística final, no qual foi criado 3 mutações e nenhuma foi eliminado. Outra forma bem interessante de verificar as coberturas e entender melhor estas estatísticas são os relatórios gerados em HTML pelo Pitest. Na pasta target do projeto, acesse a pasta pit-reports. Lá nesta pasta vai ter todos os relatórios que são criados a cada execução dos teste de cobertura do Pitest. No arquivo index.html mostra um overview do que foi coberto ou não pelos testes, no nossa caso não existe cobertura. E no arquivo BankAccount.java.html mostra detalhes do código não coberto Perceba que na imagem acima existe uma lista de Active mutators que são as mutações com base no código que criamos. Deixando bem transparente o que o Pitest criou para testar o código. Eliminando as mutações Com base nos relatórios, vamos criar alguns testes para que a cobertura chegue a 100%. Vamos criar a classe de teste chamada BankAccountTest.java e para isso existe um ponto de atenção. Crie no diretório de src/test/java , o mesmo nome do pacote criado no diretório main (com.bank.entity). package com.bank.entity; import org.junit.Assert; import org.junit.Test; public class BankAccountTest { @Test public void userValid_NegateConditionalsMutator_Test(){ BankAccount bankAccount = new BankAccount( "Chase","Jonas", 2000.00); Boolean actual = bankAccount.userValid(bankAccount); Boolean expected = true; Assert.assertEquals(expected, actual); } @Test public void userValid_BooleanFalseReturnValsMutator_Test(){ BankAccount bankAccount = new BankAccount( "Chase","", 2000.00); Boolean actual = bankAccount.userValid(bankAccount); Boolean expected = false; Assert.assertEquals(expected, actual); } } Nos testes acima, criamos apenas 2 testes para a cobertura: 1.userValid_NegateConditionalsMutator_Test(): Faz a cobertura para nome de usuários preenchidos, ou seja, no construtor foi passado o argumento "Chase" representando o nome do usuário para que a condição do método seja validada. E por fim valida a condição do método ser retornado como TRUE. Neste caso, já eliminamos 2 mutações criadas de acordo com o relatório de estatística. BooleanTrueReturnValsMutator NegateConditionalsMutator 2. userValid_BooleanFalseReturnValsMutator_Test(): Valida a possibilidade do método retornar o valor Booleano FALSE. Execute novamente o comando Maven abaixo: mvn org.pitest:pitest-maven:mutationCoverage Console da aplicação Perceba que para cada mutação gerada, 1 foi eliminada. Cobrindo 100% da cobertura nos testes. Referências: https://pitest.org Material de estudo Se quer aprender mais sobre o assunto e alcançar um alto nível de conhecimento, recomendo fortemente a leitura do(s) seguinte(s) livro(s): Use a cabeça: Java é um clássico onde qualquer iniciante no assunto deve ler e estudar. Neste livro você aprenderá sobre os principais pilares de Java como, orientação a objetos, criação de classes, interfaces e seu funcionamento, controlar exceções, objetos genéricos e muito mais. Se quer entrar de cabeça neste mundo, é uma excelente opção! Padrões de Projeto é um livro no qual recomendamos após alcançar uma certa maturidade em programação em geral. Escrito por grandes nomes do assunto e traduzido para o português, Padrões de Projeto ou Design patterns como também são conhecidos, são padrões e estratégias que te ajudará a resolver diferentes desafios arquiteturais, aplicando soluções de forma elegante. São estratégias em que desenvolvedores de todo o mundo tem adotado em seus projetos. Imagina se você precisa atuar em um projeto internacional, caso este projetos tem adotado estratégias de Padrões de projeto, você não terá nenhuma grande dificuldade em entender a dinâmica e a arquitetura do código ou caso contrário, você mesmo poderá aplicar os conhecimentos adquiridos através deste livro. O mais interessante que Padrões de Projeto independem de linguagem de programação, é possível aplicar em qualquer outra linguagem, ou seja, é um conteúdo 100% reutilizável. Java Efetivo escrito por Joshua Bloch e traduzido para o português, é um livro excelente para aqueles que possuem um pouco mais de experiência com Java mas que precisam aprofundar em detalhes mais específicos da linguagem como, quando e como usar específicos Padrões de Projeto ou Design Patterns, utilização de Lambdas e Streams, concorrências e serializações. Para aqueles que possuem mais de experiência, é um excelente material de consulta. Junit em Ação é um famoso livro sobre testes que cobre técnicas de como efetuar testes práticos em seu código, utilizando técnicas de testes automatizados, testes unitários, testes de forma isolada e muito mais. É através da prática de testes que garantimos uma entrega de qualidade do software para o cliente final, evitando quebras na fase de Build e Deploy, entregando features íntegras e confiáveis de acordo os requisitos do projeto. Mastering Unit Testing Using Mockito and JUnit (Versão em Inglês) é um livro que cobre práticas de JUnit utilizando uma das bibliotecas de testes mais famosas chamada Mockito. Neste livro ensina-se a como criar e manter testes unitários automatizados utilizando features avançadas do JUnit junto ao framewok Mockito. Práticas de integrações contínuas (o famoso CI) utilizando ferramentas de mercado como Jenkins junto com um dos maiores gerenciadores de dependências em projetos Java, o Maven. Para você que está começando neste mundo é uma excelente escolha. Bakana, né? Já é uma opção para melhorar seus testes nas próximas aplicações.
- Lendo arquivo CSV com Apache Spark
Apache Spark atua muito bem na leitura de diversos arquivos para extração de dados, nesse post vamos criar um exemplo de leitura de um arquivo CSV utilizando Spark, Java e Maven. Para quem não sabe o que é um CSV, é um arquivo texto que separa as colunas entre ponto e vírgula ( ; ). Maven org.apache.spark spark-core_2.12 3.1.0 org.apache.spark spark-sql_2.12 3.1.0 Conteúdo do CSV (Crie um arquivo chamado movies.csv com este conteúdo) title;year;rating The Shawshank Redemption;1994;9.3 The Godfather;1972;9.2 The Dark Knight;2008;9.0 The Lord of the Rings: The Return of the King ;2003;8.9 Pulp Fiction;1994;8.9 Fight Club;1999;8.8 Star Wars: Episode V - The Empire Strikes Back;1980;8.7 Goodfellas;1990;8.7 Star Wars;1977;8.6 Criando SparkSession SparkConf sparkConf = new SparkConf(); sparkConf.setMaster("local[*]"); sparkConf.setAppName("app"); SparkSession sparkSession = SparkSession.builder() .config(sparkConf) .getOrCreate(); Executando a leitura Dataset ds = sparkSession.read() .format("CSV") .option("sep",";") .option("inferSchema", "true") .option("header", "true") .load("movies.csv"); ds.select("title","year","rating").show(); Resultado Entendendo alguns parâmetros .option("sep", ";"): Define a utilização de um separador padrão para a leitura do arquivo, neste caso o separador é o ponto e vírgula (;) .option("inferSchema", "true"): O parâmetro inferSchema possibilita inferir o(s) arquivo(s) afim de entender (adivinhar) os tipos dos dados de cada campo .option("header", "true"): Habilitar o parâmetro header possibilita utilizar o nome de cada campo definido no cabeçalho do arquivo .load("movies.csv"): movies.csv é o nome do arquivo a ser lido Material de estudo Se quer aprender mais sobre o assunto e alcançar um alto nível de conhecimento, recomendo fortemente a leitura do(s) seguinte(s) livro(s): Beginning Apache Spark 3: With Dataframe, Spark SQL, Structured Streaming, and Spark Machine Library (Versão Inglês) com a nova versão do Spark, este livro explora os principais recursos do Spark, como o uso de Dataframes, Spark SQL no qual você pode usar SQL para manipular dados e Structured Streaming para processar dados em tempo real. Este livro contém exemplos práticos e trechos de código para facilitar a leitura. Use a cabeça: Java é um clássico onde qualquer iniciante no assunto deve ler e estudar. Neste livro você aprenderá sobre os principais pilares de Java como, orientação a objetos, criação de classes, interfaces e seu funcionamento, controlar exceções, objetos genéricos e muito mais. Se quer entrar de cabeça neste mundo, é uma excelente opção! High Performance Spark: Best Practices for Scaling and Optimizing Apache Spark (Versão Inglês) é um livro que explora as melhores práticas usando Spark e Scala para lidar com processamentos de larga escala. Ensina sobre técnicas para obter o máximo de desempenho no processamento utilizando RDD, Spark SQL, Spark MLlib e muito mais. Maven: The Definitive Guide (Versão Inglês) é um livro escrito em inglês que vale muito a pena ter no seu acervo caso você queira entender mais sobre o assunto. Maven é hoje o principal gerenciador de dependências em projetos Java encontrado no mercado. Em qualquer projeto seja ele nacional ou internacional, Maven vai estar presente facilitando a instalação, gerenciando bibliotecas e dando suporte aos builds dos projetos. Curtiu? Espero que sim, até mais!