top of page

Search

87 itens encontrados para ""

  • Gerando um projeto Maven sem IDE em 2 minutos

    O que é Maven? É comum ouvir falar em maven, principalmente para projetos Java mas não confunda Maven com Java, ok? Posso explicar o que é maven e seu caso de uso. Maven é uma ferramenta popular de automação de compilação usada principalmente para projetos Java. Ele fornece uma maneira estruturada de gerenciar dependências do projeto, criar processos e versões. O Maven usa uma abordagem declarativa para gerenciamento de projetos, onde você define as especificações e dependências do seu projeto em um arquivo XML chamado pom.xml (Project Object Model). O Maven ajuda a simplificar o processo de compilação gerenciando as dependências do seu projeto, baixando as bibliotecas necessárias dos repositórios e fornecendo uma maneira padronizada de criar e empacotar seu aplicativo. Ele também pode gerar documentação de projeto, executar testes e executar outras tarefas relacionadas à construção e gerenciamento de projetos Java. Para resumir, o Maven fornece um poderoso conjunto de ferramentas para criar, gerenciar e liberar aplicativos Java e é amplamente usado na comunidade de desenvolvimento Java. Gerando um projeto Maven sem IDE Normalmente, engenheiros geram o projeto Maven por meio de uma IDE, mas há maneiras mais fáceis de fazer o mesmo sem o suporte de IDEs Se você ainda não instalou o Maven, recomendo instalá-lo antes de começar. Assim, você pode baixar o Maven aqui neste link e depois de instalado, siga os passos para instalar utilizando este link aqui. Primeiramente, para ter certeza que você instalou o Maven, abra o terminal e execute o comando abaixo: mvn -version Uma mensagem semelhante à abaixo será exibida no terminal. Agora, vamos começar a gerar o nosso projeto Maven. 1° Passo: Abra o terminal novamente e execute o comando abaixo. mvn archetype:generate -DgroupId=com.coffeeantips.maven.app -DartifactId=coffeeantips-maven-app -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.0 -DinteractiveMode=false 2° Passo: Depois de executar o comando acima, uma pasta chamada coffeeantips-maven-app/ foi criada. Mude para este diretório e veremos a seguinte estrutura de pastas e arquivos. Entendendo os parâmetros do comando archetype:generate: Gera um novo projeto a partir de um archetype ou atualiza o projeto atual. -DgroupId: Especifica o pacote onde as pastas e arquivos de projetos serão gerados. -DartifactId: Nome ou artefato do projeto. -DarchetypeArtifactId: O Maven fornece uma lista de archetypes, você pode conferir aqui. Mas, para este exemplo, estamos usando um archetype para gerar um exemplo de projeto Maven padrão. -DarchetypeVersion: Versão do projeto. -DinteractiveMode: É uma maneira de definir se o Maven irá interagir com o usuário solicitando entradas(inputs). 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): Maven: The Definitive Guide (Versão Inglês) Escrito pelo criador do Maven, Jason Van Zyl, e sua equipe na Sonatype, Maven: The Definitive Guide explica claramente como essa ferramenta pode organizar seus projetos de desenvolvimento de software. Neste livro, você aprenderá sobre: ​​O POM e os relacionamentos do projeto, o ciclo de vida da construção, plug-ins, geração de sites do projeto, geração avançada de sites, relatórios, propriedades, perfis de construção, repositório Maven e muito mais. Bom é isso, espero que tenham gostado!

  • Como gerar massa de testes utilizando biblioteca Java Datafaker

    Às vezes em nossos projetos temos que preencher objetos Java para testes unitários ou até mesmo criar um dump de banco de dados com dados aleatórios para testar uma característica específica e etc. Precisamos ser criativos tentando criar nomes, nomes de ruas, cidades ou documentos. Existe uma biblioteca Java interessante e útil chamada Datafaker que permite criar dados aleatórios com um grande número de provedores. Provedores são objetos baseados em um contexto, por exemplo: Se você deseja gerar dados para o objeto person, existe um provedor específico para este contexto que irá gerar nome, sobrenome e etc. Neste post vamos criar alguns exemplos usando Maven como gerenciador de dependências Java, mas a biblioteca também fornece suporte para projetos Gradle. Maven net.datafaker datafaker 1.1.0 Gerando Dados aleatórios Vamos criar uma classe Java simples que contém algumas propriedades como nome, sobrenome, endereço, gênero musical favorito e comida. public class RandomPerson { public String firstName; public String lastName; public String favoriteMusicGenre; public String favoriteFood; public String streetAddress; public String city; public String country; @Override public String toString() { return "firstName=" + firstName + "\n" + "lastName=" + lastName + "\n" + "favoriteMusicGenre="+favoriteMusicGenre + "\n" + "favoriteFood=" + favoriteFood + "\n" + "streetAddress=" + streetAddress + "\n" + "city=" + city + "\n" + "country=" + country ; } static void print(RandomPerson randomPerson){ System.out.println( randomPerson ); } } No próximo passo, vamos preencher um objeto usando os provedores que citamos na primeira seção. Primeiramente, criamos um objeto chamado randomData do tipo Faker, pois é nesta classe que contém todos os provedores no exemplo abaixo. public static void main(String[] args) { Faker randomData = new Faker(); RandomPerson randomPerson = new RandomPerson(); randomPerson.firstName = randomData.name().firstName(); randomPerson.lastName = randomData.name().lastName(); randomPerson.favoriteMusicGenre = randomData.music().genre(); randomPerson.favoriteFood = randomData.food().dish(); randomPerson.streetAddress = randomData.address().streetAddress(); randomPerson.city = randomData.address().city(); randomPerson.country = randomData.address().country(); print(randomPerson); } Após a execução, podemos ver os resultados como este no console: Resultado firstName=Dorthy lastName=Jones favoriteMusicGenre=Electronic favoriteFood=Cauliflower Penne streetAddress=7411 Darin Gateway city=Gutkowskifort country=Greece Cada execução será um novo resultado porque os provedores são aleatórios. Outra funcionalidade interessante é que podemos configurar o Locale ao instanciar um objeto. Faker randomData = new Faker(Locale.JAPANESE); Veja os resultados com base no Local.JAPANESE: Resultado firstName=航 lastName=横山 favoriteMusicGenre=Non Music favoriteFood=French Fries with Sausages streetAddress=418 美桜Square city=南斉藤区 country=Togo 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): Unit Testing Principles, Practices, and Patterns: Effective Testing Styles, Patterns, and Reliable Automation for Unit Testing, Mocking, and Integration Testing with Examples in C# (Versão Inglês) é um livro que cobre Princípios, Padrões e Práticas de Testes unitários. Ensina a projetar e escrever testes que visam áreas-chave do seu código, incluindo o modelo de domínio. Neste guia escrito de forma clara, você aprenderá a desenvolver testes e conjuntos de testes de qualidade profissional e a integrar testes em todo o ciclo de vida do aplicativo. Junit em Ação é um livro de testes popular que cobre técnicas como teste prático de seu código, usando técnicas de testes unitários e muito mais. É através da prática de testes que garantimos uma entrega de qualidade do software ao cliente final, garantindo a execução do Build e Deploy. Mastering Unit Testing Using Mockito and JUnit (Versão Inglês) é um livro que cobre as práticas do JUnit usando uma das mais famosas bibliotecas de teste chamada Mockito. Este livro ensina como criar e manter testes unitários automatizados utilizando recursos avançados do JUnit com o framework Mockito, práticas de integração contínua (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 nesse mundo, é uma excelente escolha. Bom é isso, espero que tenham gostado!

  • Criando um código Java usando Builder pattern

    Se você estiver usando uma linguagem que suporte orientação a objetos em seu projeto, provavelmente existem algumas linhas de códigos com o Builder pattern. Se não, este post vai te ajudar a entender sobre um dos Design Patterns mais utilizados em projetos orientado a objetos. O que é o Builder Pattern? Builder Pattern pertence a uma área do Engenheiro de Software chamada Design Patterns, a ideia por trás de um padrão é resolver problemas comuns em seu projeto seguindo as melhores práticas. Builder Pattern é muito útil quando precisamos fornecer uma melhor solução na parte de criação de objetos em nosso projeto. Às vezes precisamos instanciar um objeto com muitos parâmetros e isso pode ser um problema se você passar um valor de parâmetro errado. Coisas como essas acontecem sempre e resultam em erros de compilação e você precisará descobrir onde está o problema e talvez refatorar o código para melhorá-lo. Vamos escrever algumas linhas de código para entender como o Builder Pattern funciona e quando aplicá-lo. O código abaixo é um exemplo de uma classe tradicional com construtor usado para carregar valores quando o objeto é instanciado. public class PersonalInfo { private final String firstName; private final String lastName; private final Date birthDate; private final String address; private final String city; private final String zipCode; private final String state; private final int population; public PersonalInfo(String firstName, String lastName, Date birthDate, String address, String city, String zipCode, String state, int population){ this.firstName = firstName; this.lastName = lastName; this.birthDate = birthDate; this.address = address; this.city = city; this.zipCode = zipCode; this.state = state; this.population = population; } } E agora podemos instanciar o objeto simulando o código do cliente. PersonalInfo personalInfo = new BuilderPattern("Mônica", "Avelar", new Date(), "23 Market Street", "San Francisco", "94016", "CA", 800000); Se você reparar, para instanciar o objeto devemos passar todos os valores referentes a cada propriedade da nossa classe e há uma grande chance de passar um valor errado. Outra desvantagem dessa abordagem é a possibilidade de não escalá-la. Neste exemplo temos algumas propriedades mas no futuro, podemos adicionar mais propriedades e a desvantagem fica mais clara. Aplicando Builder Pattern Vamos reescrever o código acima aplicando Builder Pattern e ver as diferenças. public class PersonalInfo { private final String firstName; private final String lastName; private final Date birthDate; private final String address; private final String city; private final String zipCode; private final String state; private final int population; public static class Builder { private String firstName; private String lastName; private Date birthDate; private String address; private String city; private String zipCode; private String state; private int population; public Builder firstName(String value) { firstName = value; return this; } public Builder lastName(String value) { lastName = value; return this; } public Builder birthDate(Date value) { birthDate = value; return this; } public Builder address(String value) { address = value; return this; } public Builder city(String value) { city = value; return this; } public Builder zipCode(String value) { zipCode = value; return this; } public Builder state(String value) { state = value; return this; } public Builder population(int value) { population = value; return this; } public BuilderPattern build() { return new BuilderPattern(this); } } public PersonalInfo(Builder builder){ firstName = builder.firstName; lastName = builder.lastName; birthDate = builder.birthDate; address = builder.address; city = builder.city; zipCode = builder.zipCode; state = builder.state; population = builder.population; } } Se você comparar os dois códigos, perceberá que o primeiro é menor e melhor para entender do que o segundo, e eu concordo. A vantagem do uso ficará clara para o próximo exemplo quando criarmos um objeto baseado no Builder Pattern. Instanciando um objeto utilizando Builder Pattern PersonalInfo personalInfo = new Builder() .firstName("Mônica") .lastName("Avelar") .birthDate(new Date()) .address("23 Market Street") .city("San Francisco") .zipCode("94016") .state("CA") .population(80000) .build(); Este último exemplo de criação de objeto utilizando o Builder Pattern, torna um código organizado seguindo as melhores práticas e de fácil leitura. Outra vantagem do Builder é que, podemos identificar cada propriedade antes de passar valores. Para ser sincero, tenho usado o Builder Pattern em meus projetos e recomendo fortemente que você faça o mesmo em seus próximos projetos. 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. Espero que tenha curtido!

  • Diferenças entre os modes FAILFAST, PERMISSIVE e DROPMALFORMED em Spark Dataframes

    Existem algumas diferenças entre eles e vamos descobrir neste post. O parâmetro mode permite passar como valor, formas de validar Dataframes visando a qualidade dos dados. Neste post vamos criar um Dataframe utilizando PySpark e comparar as diferenças entre esses três tipos de mode, são eles: PERMISSIVE DROPMALFORMED FAILFAST Conteúdo do arquivo CSV Para este post, usaremos como exemplo um arquivo CSV contendo alguns registros variados, dentre eles, registros corrompidos. A definição de registros corrompidos para este contexto é que, para a coluna engines adicionamos alguns registros com tipos diferentes do que serão definidos no esquema. Neste caso, no esquema, a coluna engines será definida como Integer mas no conteúdo abaixo, temos alguns registro com valores do tipo String. "type","country","city","engines","first_flight","number_built" "Airbus A220","Canada","Calgary",2,2013-03-02,179 "Airbus A220","Canada","Calgary","two",2013-03-02,179 "Airbus A220","Canada","Calgary",2,2013-03-02,179 "Airbus A320","France","Lyon","two",1986-06-10,10066 "Airbus A330","France","Lyon","two",1992-01-02,1521 "Boeing 737","USA","New York","two",1967-08-03,10636 "Boeing 737","USA","New York","two",1967-08-03,10636 "Boeing 737","USA","New York",2,1967-08-03,10636 "Airbus A220","Canada","Calgary",2,2013-03-02,179 Vamos começar criando um Dataframe simples que irá carregar dados do arquivo CSV contendo os registros acima, vamos supor que o conteúdo acima seja de um arquivo chamado avioes.csv. Para modelar o conteúdo, também estamos criando um esquema que nos permitirá validar os dados. Criando um Dataframe usando o mode PERMISSIVE O mode PERMISSIVE define valores de campos como nulos quando registros corrompidos são detectados para aquela coluna. Por padrão, se você não especificar nenhum valor para o parâmetro mode, Spark definirá o valor PERMISSIVE. from pyspark.sql import SparkSession from pyspark.sql.types import StructType, StructField, StringType, IntegerType if __name__ == "__main__": spark = SparkSession.builder \ .master("local[1]") \ .appName("spark-app") \ .getOrCreate() schema = StructType([ StructField("TYPE", StringType()), StructField("COUNTRY", StringType()), StructField("CITY", StringType()), StructField("ENGINES", IntegerType()), StructField("FIRST_FLIGHT", StringType()), StructField("NUMBER_BUILT", IntegerType()) ]) read_df = spark.read \ .option("header", "true") \ .option("mode", "PERMISSIVE") \ .format("csv") \ .schema(schema) \ .load("airplanes.csv") read_df.show(10) Resultado utilizando PERMISSIVE mode Perceba que para a colune ENGINES que possui registros que não seguem o padrão de tipagem definido, foram convertidas para o valor null. Criando um Dataframe usando o mode DROPMALFORMED O mode DROPMALFORMED ignora registros corrompidos. O que significa que, se você escolher este tipo de mode, os registros corrompidos não serão listados. from pyspark.sql import SparkSession from pyspark.sql.types import StructType, StructField, StringType, IntegerType if __name__ == "__main__": spark = SparkSession.builder \ .master("local[1]") \ .appName("spark-app") \ .getOrCreate() schema = StructType([ StructField("TYPE", StringType()), StructField("COUNTRY", StringType()), StructField("CITY", StringType()), StructField("ENGINES", IntegerType()), StructField("FIRST_FLIGHT", StringType()), StructField("NUMBER_BUILT", IntegerType()) ]) read_df = spark.read \ .option("header", "true") \ .option("mode", "DROPMALFORMED") \ .format("csv") \ .schema(schema) \ .load("airplanes.csv") read_df.show(10) Resultado utilizando DROPMALFORMED mode Após definirmos o valor do mode como DROPMALFORMED, perceba que ao listar o registros do Dataframe, os registros corrompidos foram ignorados, não sendo apresentados no Dataframe. Criando um Dataframe usando o mode FAILFAST Diferente do mode DROPMALFORMED e PERMISSIVE, FAILFAST lança uma exceção quando detecta registros corrompidos. from pyspark.sql import SparkSession from pyspark.sql.types import StructType, StructField, StringType, IntegerType if __name__ == "__main__": spark = SparkSession.builder \ .master("local[1]") \ .appName("spark-app") \ .getOrCreate() schema = StructType([ StructField("TYPE", StringType()), StructField("COUNTRY", StringType()), StructField("CITY", StringType()), StructField("ENGINES", IntegerType()), StructField("FIRST_FLIGHT", StringType()), StructField("NUMBER_BUILT", IntegerType()) ]) read_df = spark.read \ .option("header", "true") \ .option("mode", "FAILFAST") \ .format("csv") \ .schema(schema) \ .load("airplanes.csv") read_df.show(10) Resultado utilizando FAILFAST mode ERROR Executor: Exception in task 0.0 in stage 0.0 (TID 0) org.apache.spark.SparkException: Malformed records are detected in record parsing. Parse Mode: FAILFAST. To process malformed records as null result, try setting the option 'mode' as 'PERMISSIVE'. 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!

  • Entendendo AWS S3 em 1 minuto

    A Amazon Web Services AWS é um dos serviços de Cloud Computing mais tradicionais e com mais recursos do mercado. Um dos recursos mais utilizados é o S3. O que é o S3? S3 é uma abreviação para Simple Storage Service. É um recurso gerenciado pela própria AWS, ou seja, não preocupamos em gerenciar a infra-estrutura. Provê um repositório de objetos possibilitando armazenar objetos de diversos volumes, backups, sites, execução de análise de dados, gerenciamento de Data Lakes e etc. Provê também diversas integrações com outras ferramentas da AWS visando um repositório base. Organização dos dados O S3 é dividido em diferentes Buckets contendo uma estrutura de pastas com base nas necessidades dos clientes. O que é um Bucket? O Bucket que é uma espécie de contêiner onde todos os objetos serão armazenados e organizados. Uma coisa muito importante é que este Bucket deve ser único. Arquitetura A seguir, temos um desenho mais simplista da arquitetura do S3 com os Buckets e os diretórios de pastas. Poderíamos descrever estes Buckets do desenho como Buckets de diferentes organizações ou até de uma mesma organização. É legal entender que, para uma região pode e vai existir um cenário como mostrado acima. Integrações O eco-sistema da AWS possibilita a integração da maioria de suas ferramentas e de terceiros. O S3 é um dos recursos que mais possui integrações. Alguns exemplos de ferramentas com integração: Athena Glue Kinesis Firehose Lambda Delta Lake RDS Outros SDK A AWS provê SDK compatível para diferentes linguagens de programação que possibilita manipular objetos no S3, como criar Buckets, pastas, upload e download de arquivos e muito mais. 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!

  • Spring Boot com Spring Data + JPA

    O Spring Data é um dos vários projetos do ecossistema Spring que visa facilitar acesso aos dados através da utilização de modelos e sem a necessidade de escrever códigos SQL. Qualquer manipulação de dados pode ser feita através de interfaces Java resultando em um código muito mais compreensível e mais limpo. Criando o projeto Para este projeto vamos usar as seguintes dependências: Spring Data JPA H2 Database Lombok Acesse o site https://start.spring.io selecionando as dependências conforme abaixo Escolha a versão Java que você utiliza e clique em Generate para gerar os arquivos e em seguida faça a importação do arquivo pom.xml para a sua IDE. Maven 4.0.0 org.springframework.boot spring-boot-starter-parent 2.4.4 com.blog.spring.data spring-data 0.0.1-SNAPSHOT spring-data Demo project for Spring Boot 8 org.springframework.boot spring-boot-starter-data-jpa com.h2database h2 org.projectlombok lombok true org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-maven-plugin org.projectlombok lombok Sobre o projeto Neste projeto vamos trabalhar com base na classe Employee. Faremos uma carga inicial para o H2 que é um banco de dados em memória e em seguida vamos explorar mais o Spring Data criando algumas consultas utilizando apenas uma Interface Java. Classe Employee A classe Employee representará o modelo principal do projeto package com.blog.spring.data.springdata.model; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; @Data @AllArgsConstructor @NoArgsConstructor @Entity public class Employee { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String firstName; private String lastName; private String position; @Override public String toString() { return String.format("Employee [ID: %o," + "FistName: %s," + "LastName: %s," + "Position: %s]", getId(), getFirstName(), getLastName(), getPosition()); } } Observações sobre a classe acima: Anotação @Data A anotação @Data é um recurso do Lombok que facilita bastante a criação de modelos deixando o código menos verboso. Perceba que não foi necessário criar os getters e setters das propriedades graças ao uso do Lombok. @AllArgsConstructor e @NoArgsConstructor Também são recursos do Lombok @AllArgsConstructor: Possibilita criar um construtor de forma implícita. @NoArgsConstructor: Não obriga a passagem de argumentos para o construtor. @Entity Recurso do JPA que possibilita identificar a classe Employee como uma entidade de banco de dados. @Id Recurso do JPA utilizado para identificar um campo que deverá ser um identificar único no modelo de dados. Em resumo, a classe Employee por ter sido anotada como @Entity representará uma entidade a nível de banco de dados/tabela para a aplicação, e o @Id permite criar o campo id como um identificador único, ou seja, uma chave primária da entidade Employee. @GeneratedValue(strategy = GenerationType.AUTO) Recurso que permite controlar a geração dos valores únicos para o campo Id. Perceba que é necessário escolher a estratégia para gerar estes valores. Isso depende de cada engine de banco de dados, neste caso estamos utilizando o H2, mas caso utilizamos Oracle, a estratégia seria GenerationType.SEQUENCE. Criando o repositório EmployeeRepository No contexto de projeto Java, utilizamos algumas convenções de nomes para identificar recursos, neste campo vamos criar uma classe que servirá como repositório de dados para a entidade Employee. Para trabalhar com Spring Data, os repositórios são bem importantes e devem ser criados como Interfaces Java herdando a Interface CrudRepository veja o código abaixo. package com.blog.spring.data.springdata.repository; import com.blog.spring.data.springdata.model.Employee; import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Repository; import java.util.List; import java.util.Optional; @Repository public interface EmployeeRepository extends CrudRepository { Optional findById(Long id); List findByFirstName(String firstName); List findByLastName(String lastName); List findByPosition(String position); List findByFirstNameAndPosition(String firstName, String position); } Entendendo em partes: @Repository Identifica esta interface como um repositório no contexto do Spring CrudRepository Herdar (extends) a interface CrudRepository possibilita utilizar os recursos oferecidos pelo Spring Data. Neste caso é necessário passar como parâmetro a entidade (Employee) e o tipo do identificador único da classe Employee, que seria o campo id (Long) Métodos Esta é a parte mais importante deste Post. Perceba que para cada método se inicia com findBy e em seguida o nome do campo da classe Employee combinada ou não com um operador (AND) e um parâmetro. Todos estes métodos equivale a uma consulta SQL, perceba que não foi necessário criar scripts SQL de forma explicita. Isso é um dos recursos mais poderosos quando se utiliza Spring Data. Optional findById(Long id) Retorno: Um objeto do tipo Employee SQL: select * from Employee where id = ? List findByFirstName(String firstName) Retorno: Uma lista de objetos do tipo Employee SQL: select * from Employee where firstName = "?" List findByLastName(String lastName) Retorno: Uma lista de objetos do tipo Employee SQL: select * from Employee where lastName = "?" List findByPosition(String position) Retorno: Uma lista de objetos do tipo Employee SQL: select * from Employee where position = "?" List findByFirstNameAndPosition(String firstName, String position) Retorno: Uma lista de objetos do tipo Employee SQL: select * from Employee where firstName = "?" and position = "?" Creio que agora está mais claro o funcionamento do Spring Data, agora vamos explorar na prática. Criando a classe EmployeeService Nesta classe criaremos a parte negocial onde invocaremos o repositório criado anteriormente. package com.blog.spring.data.springdata.service; import com.blog.spring.data.springdata.model.Employee; import com.blog.spring.data.springdata.repository.EmployeeRepository; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; @Service public class EmployeeService { static EmployeeRepository employeeRepository; public EmployeeService(EmployeeRepository employeeRepository){ this.employeeRepository = employeeRepository; } public static void populateEmployeeToDataBase(){ List employees = new ArrayList<>(); employees.add(new Employee(1L, "Monica", "Silva", "Director")); employees.add(new Employee(2L, "Jessica", "Reies", "Coordinator")); employees.add(new Employee(3L, "Milena", "Torres", "Dev")); employees.add(new Employee(4L, "Maura", "Sanches", "Dev")); employeeRepository.saveAll(employees); } public void runQueries(){ populateEmployeeToDataBase(); employeeRepository.findById(3L) .ifPresent(System.out::println); employeeRepository.findByFirstName("Monica") .ifPresent(System.out::println); employeeRepository .findByFirstNameAndPosition( "Maura", "Dev") .ifPresent(System.out::println); employeeRepository.findByPosition("Dev") .ifPresent(System.out::println); } } A classe EmployeeService será responsável por popular na base uma lista de objetos do tipo Employee e executar os métodos para acesso a base na classe EmployeeRepository. Executando o código Para a execução do código, vamos criar a classe principal do projeto chamada SpringDataApplication.java, seguindo os padrões de um projeto Spring Boot. package com.blog.spring.data.springdata; import com.blog.spring.data.springdata.service.EmployeeService; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class SpringDataApplication { private static EmployeeService employeeService; public SpringDataApplication(EmployeeService employeeService){ this.employeeService = employeeService; } public static void main(String[] args) { SpringApplication.run(SpringDataApplication.class, args); employeeService.runQueries(); } } Esta classe possui 2 particularidades: A anotação @SpringBootApplication Esta anotação permite identificar esta classe como a principal para o contexto do Spring Boot e será responsável por iniciar a aplicação O método main Método responsável pela inicialização da aplicação e para este tutorial a invocação do método runQueries que criamos anteriormente. Resultado da execução Employee [ID: 3,FistName: Milena,LastName: Torres,Position: Dev] [Employee [ID: 1,FistName: Monica,LastName: Silva,Position: Director]] [Employee [ID: 4,FistName: Maura,LastName: Sanches,Position: Dev]] [Employee [ID: 3,FistName: Milena,LastName: Torres,Position: Dev], Employee [ID: 4,FistName: Maura,LastName: Sanches,Position: Dev]] Todas estas linhas acima são resultados de consultas SQL de forma implícita executadas pelos métodos em que criamos na classe EmployeeRepository. Percebeu o poder do Spring Data sem a necessidade de criar consultas SQL no código? 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. Curtiu? Até mais!

  • Escopos do Maven

    Conforme a documentação do próprio Maven, os escopos possuem um papel em limitar as dependências transitivas e o controle de quando um dependência pode ser incluída no classpath do projeto. O Maven provê alguns escopos que podem ser utilizados para configurar as dependências do seu projeto. Neste post, vamos falar de forma resumida dos 5 principais escopos. São eles: compile: Escopo padrão, quando não se especifica nenhum outro escopo. Dependências configuradas com este escopo são disponibilizadas para todo o classpath de um projeto. provided: Basicamente utilizado para dependências que serão adicionadas ao classpath em tempo de compilação e testes. Mas o ponto forte da utilização deste escopo é quando existe uma necessidade em adicionar uma ou mais dependências já existentes dentro de um contexto específico. Na maioria dos casos, isso acontece quando estamos fazendo um deploy de uma aplicação web dentro de um container que já possui dependências em comum. runtime: Esta escopo fala por si. O Maven inclui dependências configuradas como runtime no classpath em tempo de execução (runtime) e testes. test: Escopo utilizado para execução de testes. Normalmente utilizado para bibliotecas como JUnit e Mockito. system: Este escopo é similar ao provided mas com uma diferença. Para a utilização do escopo system, é necessário especificar o caminho do Jar. Lembrando que este escopo está depreciado. 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): Maven: The Definitive Guide (English Edition) é 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 de bibliotecas e dando suporte aos builds dos projetos. Recomendo também os seguintes materiais para complementar seus estudos: 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.

  • Clonando objeto Java

    A ideia de clonar um objeto serve para várias soluções . Uma delas é quando você precisa passar um objeto por parâmetro, mesmo atribuindo a um novo objeto e este uma vez alterado, o objeto original também será alterado. Em Java, os parâmetros são passados por valor, mas quando é utilizado uma variável de objeto as suas referências são de um objeto Neste post vou mostrar uma das soluções quando você quer evitar que o objeto original não seja alterado. Para isso vamos utilizar a interface Cloneable. A classe abaixo é um simples Pojo que implementa a interface Cloneable public class Pessoa implements Cloneable{ public Long id; public String nome; public int idade; public Pessoa(Long id, String nome, int idade){ this.id = id; this.nome = nome; this.idade = idade; } } O próximo passo é sobrescrever o método clone. Para o exemplo vamos alterar o modificador de acesso de protected para public public class Pessoa implements Cloneable{ public Long id; public String nome; public int idade; public Pessoa(Long id, String nome, int idade){ this.id = id; this.nome = nome; this.idade = idade; } @Override public Object clone() throws CloneNotSupportedException { return super.clone(); } } A primeira parte já está pronta, agora vamos criar um exemplo que possamos entender melhor em como utilizar. No método alteraPessoa(Pessoa pessoa), vamos simular a passagem de parâmetro do objeto. public static void main(String[] args) Pessoa pessoa = new Pessoa(1L, "Monica", 18); alteraPessoa(pessoa); } private static void alteraPessoa(Pessoa pessoa) Pessoa pessoaAlterada = (Pessoa) pessoa.clone(); pessoaAlterada.id = 2L; pessoaAlterada.nome = "Jorge"; pessoaAlterada.idade = 34; System.out.println("Objeto original " + pessoa); System.out.println("Objeto alterado " + pessoaAlterada); } No trecho a seguir é onde o método clone é chamado e atribuído o "clone" para o objeto pessoaAlterada Pessoa pessoaAlterada = (Pessoa) pessoa.clone(); Pronto, seguindo estes passos o objeto original pessoa não será alterado pelo objeto pessoaAlterada em alterações posteriores. 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 - Sorted

    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. 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. public class Cidade { String nome; String estado; long populacao; public Cidade(){} public Cidade(String nome, String estado, long populacao){ this.nome = nome; this.estado = estado; this.populacao = populacao; } public List listaCidades(){ List cidades = new ArrayList(); cidades.add(new Cidade("Hollywood", "CA", 30L)); cidades.add(new Cidade("Venice", "CA", 10L)); cidades.add(new Cidade("Houston", "TX", 14L)); cidades.add(new Cidade("New York", "NY", 21L)); cidades.add(new Cidade("Albany", "NY", 11L)); cidades.add(new Cidade("Rio de Janeiro", "RJ", 14L)); cidades.add(new Cidade("São Paulo", "SP", 90L)); return cidades; } @Override public String toString() { return "Cidade: " + nome + " /Estado: " + estado + " /População: " + populacao; } } Sorted O método Sorted() possibilita a ordenação de uma Collection através da passagem do campo em que deseja ser ordenado. cidadesComPopulacaoMaiorQue20 = cidade.listaCidades() .stream() .sorted(Comparator.comparing(c -> c.nome)) .collect(Collectors.toList()); cidadesComPopulacaoMaiorQue20.forEach( c -> System.out.println(c) ); No método sorted() é utilizado o método comparing da interface Comparator que aceita uma função como parâmetro e em seguida extrai retornando uma chave de ordenação. No exemplo anterior a ordenação é feita pelo campo Cidade.nome em ordem alfabética. Saída: Cidade: Albany /Estado: NY /População: 11 Cidade: Hollywood /Estado: CA /População: 30 Cidade: Houston /Estado: TX /População: 14 Cidade: New York /Estado: NY /População: 21 Cidade: Rio de Janeiro /Estado: RJ /População: 14 Cidade: São Paulo /Estado: SP /População: 90 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 sorted é 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!

  • Convertendo tabela Parquet para Delta Table

    Para este post, vamos criar exemplos de como converter tabelas parquet em Delta table. Primeiro, criaremos uma tabela parquet do zero por meio de um Spark Dataframe e depois a converteremos em um Delta Table. O uso de Delta Table fornece benefícios em comparação com uma tabela em Parquet. O Delta permite restaurar versões de sua tabela por meio da função Time Travel, suporta transações ACID e várias outras features interessantes. Criando Tabela Parquet Em primeiro lugar, vamos criar uma tabela parquet para ser convertida posteriormente em uma Delta Table. Vamos criar uma tabela Parquet do início para um melhor entendimento. O código Java e Spark a seguir, será executado uma vez, apenas para criar uma tabela parquet. Vamos usar um Spark Dataframe que será carregado de um arquivo JSON contendo registros semi-estruturados. public static void main(String[] args){ SparkConf conf = new SparkConf(); conf.setAppName("spark-delta-table"); conf.setMaster("local[1]"); SparkSession session = SparkSession.builder() .config(conf) .getOrCreate(); Dataset dataFrame = session.read().json("product.json"); dataframe.write().format("parquet").save("table/product"); } No exemplo acima, começamos a criar um objeto SparkSession para criar e gerenciar um Spark Dataframe que foi carregado a partir do conteúdo do arquivo product.json. Após a carga, o Dataframe cria (ou escreve) uma tabela em formato parquet no diretório table/product. Conteúdo JSON Conteúdo representado pelo arquivo product.json que contém registros semi-estruturados. {"id":1, "name":"rice", "price":12.0, "qty": 2} {"id":2, "name":"beans", "price":7.50, "qty": 5} {"id":3, "name":"coke", "price":5.50, "qty": 2} {"id":4, "name":"juice", "price":3.80, "qty": 1} {"id":5, "name":"meat", "price":1.50, "qty": 1} {"id":6, "name":"ice-cream", "price":6.0, "qty": 2} {"id":7, "name":"potato", "price":3.70, "qty": 10} {"id":8, "name":"apple", "price":5.60, "qty": 5} Após executar o código acima, os arquivos parquets serão gerados no diretório table/product contendo o arquivo abaixo. Convertendo tabela Parquet em Delta Table Agora que temos uma tabela Parquet já criada, podemos converter facilmente para Delta Table, veja o código a seguir. public static void main(String[] args){ SparkConf conf = new SparkConf(); conf.setAppName("spark-delta-table"); conf.setMaster("local[1]"); SparkSession session = SparkSession.builder() .config(conf) .getOrCreate(); DeltaTable.convertToDelta(session, "parquet.`table/product`"); } O método DeltaTable.convertToDelta é responsável por converter a tabela parquet em Delta Table. Observe que tivemos que usar SparkSession como parâmetro e também especificar o caminho da tabela parquet usando este formato"parquet.``" . O resultado após a execução você pode ver na imagem abaixo. Após a execução da conversão, Delta cria o famoso diretório _delta_log contendo informações de commit e arquivos de checkpoint. 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!

  • Como economizar custos no S3 executando um Data Lake

    Os serviços em nuvem ou Cloud Computing fornecem recursos úteis para escalar seu negócio mais rapidamente, mas nem sempre podemos medir os custos da nuvem quando estamos começando um negócio do zero ou mesmo sendo um negócio sólido. Custos sempre fazem parte da estratégia de qualquer empresa que deseja fornecer um melhor serviço Eu e meus colegas temos trabalhado em uma arquitetura de dados baseada em eventos que permite processar cerca de 350 milhões de eventos diariamente. Fornecemos dados para os consumidores finais e para as equipes estratégicas para tomadas de decisões. É sempre um grande desafio lidar com o tráfego massivo dos dados (Big Data), armazenamento e ao mesmo tempo, pensar em economia de custos com Cloud. O armazenamento é muito caro e existem algumas estratégias para economizar dinheiro. Neste post irei descrever algumas estratégias que temos adotado para economizar custos de S3 (Simple Storage Service) e espero contribuir através destas experiências. Estratégias Estratégia #1 Classe de armazenamento S3 (Amazon S3 Storage Class) O Amazon S3 fornece uma maneira de gerenciar arquivos por meio de configurações de ciclo de vida, onde você pode definir maneiras de mover arquivos para diferentes classes de armazenamento, dependendo da idade do arquivo e da frequência de acesso. Essa estratégia pode economizar muito dinheiro para o seu negócio. Trabalhar com classe de armazenamento nos permite economizar custos. Por padrão, os dados são armazenados na classe de armazenamento S3 Standard. Este tipo de armazenamento tem alguns benefícios de armazenamento e acesso aos dados, mas percebemos que após os dados transformados na camada Silver, os dados na camada Bronze não eram acessados ​​com muita frequência e devido a isso, percebemos que era possível movê-los para uma classe de armazenamento mais barata. Decidimos movê-lo usando as configurações de ciclo de vida para a classe de armazenamento S3 Intelligent Tiering. Essa classe de armazenamento se encaixou perfeitamente em nosso contexto, pois pudemos economizar custos com armazenamento e mesmo no caso de acessar esses arquivos por algum motivo, poderíamos manter um custo viável. Até poderíamos mover estes dados para a classe de armazenamento Glacier, fazendo que o custo fique ainda mais barato, porém, o contexto atual impossibilita, pois como precisamos acessar estes dados de forma regular, a camada Glacier poderia aumentar os custos mas não pelo armazenamento, mas sim pelo acesso, no qual se torna caro dependendo da "profundidade" da camada. Se você verificar a documentação da AWS, notará que existem algumas classes de armazenamento mais baratas, mas você e sua equipe devem analisar cada caso, porque quanto mais barato for armazenar dados, mais caro será acessá-los. Portanto, tenha cuidado, tente entender os padrões de armazenamento e acesso aos dados em sua arquitetura Data Lake antes de escolher uma classe de armazenamento que possa se adequar melhor ao seu contexto. Estratégia #2 Particionamento de Dados O Apache Spark é o framework mais famoso por processar grandes volumes de dados e tem sido adotado por equipes de dados por todo o mundo. Durante as transformações de dados usando o Spark, é possível definir colunas em seu Dataframe nas quais serão utilizadas como partição, oferecendo melhor desempenho ao executar consultas SQL. Observe que a abordagem de particionamento de dados não possui relação direta com o Amazon S3, mas a adoção desta estratégia visa boas práticas ao acesso aos objetos no Amazon S3. Uma das formas de cobrança utilizados no S3 é pelo acesso/leitura dos dados, ou seja, quanto mais dados serem carregados maior a cobrança. Isso é inevitável, porém a abordagem de particionar dados, faz com que as leituras sejam mais controladas, evitando grandes carregamentos de dados desnecessários e consequentemente gerando menor custo. Estratégia #3 Delta Lake vacuum Delta Lake possui um recurso interessante chamado vacuum, que é um mecanismo para remover arquivos do disco sem utilidade, liberando espaço de armazenamento. Normalmente as equipes adotam essa estratégia após a restauração de versões em que alguns arquivos remanescente de versões anteriores e não serão mais gerenciados pelo Delta Lake. Por exemplo, na imagem abaixo temos 5 versões de tabelas Delta e suas partições. Suponha que precisamos restaurar a versão porque encontramos alguns dados inconsistentes após a versão 1. Após este comando, Delta apontará seu gerenciamento para a versão 1 como a versão atual, mas os arquivos de parquet relacionados a outras versões permanecerão lá sem uso. Podemos remover esses parquets executando o comando de vacuum, conforme mostrado abaixo. Observe que os parquets relacionados às versões posteriores à 1 foram removidos, liberando espaço de armazenamento. Para obter mais detalhes, recomendo ver a documentação 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): 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. Bom é isso, espero que tenham gostado!

  • How to save costs on S3 running Data Lake

    Cloud services provides useful resources to scale your business faster but not always we can measure cloud costs when we’re starting a business from the scratch or even being a solid business, costs always makes part of the strategy for any company who want to provide a better service. Me and my teammates have worked in a Data platform based on events enable to process 350 million events every day. We provide data to the client applications and to the businesses teams to make decisions and it always a challenge do deal with the massive data traffic and how we can maintain these data and saving money with storage at the same time. Storage is too expensive and there are some strategies to save money. For this post I’ll describe some strategies that we’ve adopted to save costs on S3 (Simple Storage Service) and I hope we can help it. Strategies Strategy #1 Amazon S3 storage classes Amazon S3 provides a way to manage files through life cycle settings, out there you can set ways to move files to different storage classes depending on the file’s age and access frequency. This strategy can save a lot of money to your company. Working with storage class enable us saving costs. By default, data are stored on S3 Standard storage class. This storage type has some benefits of storage and data access but we realized that after data transformed in the Silver layer, data in the Bronze layer it wasn’t accessed very often and it was totally possible to move them to a cheaper storage class. We decided to move it using life cycle settings to S3 Intelligent Tiering storage class. This storage class it was a perfect fit to our context because we could save costs with storage and even in case to access these files for a reason we could keeping a fair cost. We’re working on for a better scenario which we could set it a life cycle in the Silver layer to move files that hasn’t been accessed for a period to a cheaper storage class but at the moment we need to access historical files with high frequency. If you check AWS documentation you’ll note that there’s some cheapest storage classes but you and your team should to analyse each case because how cheapest is to store data more expensive will be to access them. So, be careful, try to understand the patterns about storage and data access in your Data Lake architecture before choosing a storage class that could fit better to your business. Strategy #2 Partitioning Data Apache Spark is the most famous framework to process a large amount of data and has been adopted by data teams around the world. During the data transformation using Spark you can set it a Dataframe to partition data through a specific column. This approach is too useful to perform SQL queries better. Note that partitioning approach has no relation to S3 directly but the usage avoids full scans in S3 objects. Full scans means that after SQL queries, the SQL engine can load gigabytes even terabytes of data. This could be very expensive to your company, because you can be charged easily depending on amount of loaded data. So, partitioning data has an important role when we need to save costs. Strategy #3 Delta Lake vacuum Delta Lake has an interesting feature called vacuum that’s a mechanism to remove files from the disk with no usage. Usually teams adopt this strategy after restoring versions that some files will be remain and they won’t be managed by Delta Lake. For example, in the image below we have 5 versions of Delta tables and their partitions. Suppose that we need to restore to version because we found some inconsistent data after version 1. After this command, Delta will point his management to version 1 as the current version but the parquet files related to others version will be there with no usage. We can remove these parquets running vacuum command as shown below. Note that parquets related to versions after 1 were removed releasing space in the storage. For more details I strongly recommend seeing Delta Lake documentation. Well that’s it, I hope you enjoyed it!

bottom of page