Dicas para a Certificação OCM Java EE Enterprise Architect

Olá pessoal, hoje irei postar e comentar algumas dicas para quem tem interesse em adquirir a certificação OCM Java EE 6 Enterprise Architect.

A Certificação

Esta certificação se enquadra no titulo Master da Oracle, por esta razão ela é mais complexa do que as outras Certificações do mundo Java, para mais detalhes consulte a página oficial da certificação.

Fases da Certificação

A certificação é composta por 5 fases, sendo 3 exames, 1 treinamento oficial e o envio de documentos, na seguinte ordem:
  • Realização de Curso Oficial;
  • Exame 1Z0-807;
  • Exame 1Z0-895;
  • Exame 1Z0-866;
  • Envio do curso oficial (Course Submission Form).


Realização do Curso Oficial

Esta etapa é uma exigência que a Oracle faz principalmente para os exames OCM, onde cada candidato deve ter concluído um curso oficial, cada exame tem uma relação de cursos que podem ser realizados, onde você deve realizar pelo menos um curso, não sendo necessário realizar vários.

Você pode realizar o curso antes de começar o processo ou até mesmo no decorrer, o importante, é que ao concluir e ser aprovados em todas os exames, tenha concluído também algum dos cursos relacionados, pois ao final do processo será necessário uma comprovação, através de um envio de informações no site da PersonVUE.

No momento em que escrevi o tutorial, a lista de cursos é a seguinte:

Relação de cursos oficiais que servem para a OCM Java EE, fonte: Oracle.

Onde realizar o Curso Oficial ?

O curso pode ser realizado em algum centro de treinamento que forneça qualquer um dos cursos relacionados e que seja oficial/parceiro Oracle, ou seja, antes de comprar ou realizar o treinamento, confirme se a escola realmente esta credenciada, e se o curso é algum da relação mencionada anteriormente.

Da relação de cursos, eu recomento: Architect Enterprise Applications with Java EE, porque os assuntos e o material do curso, são focados em Arquitetura Java EE, falando sobre Requisitos não Funcionais, Tecnologias Java EE, Análise de Risco, entre outros assuntos que são cobrados nos exames.

Uma outra dica é realizar o curso antes de qualquer prova, novamente porque este curso ajuda muito na realização de todos os exames.

Em São Paulo, realizei o curso na Globalcode Treinamentos, eles possuem em seu catalogo o treinamento Architect Enterprise Applications with Java EE, e são credenciados pela Oracle.


Exame 1Z0-807 (Multiple Choice)

Esta prova segue o modelo tradicional das outras certificações Java, ela é composta por 60 questões de múltipla escolha, onde cada questão pode ter mais de uma alternativa correta, o tempo para realizar o exame é de 150 minutos, o score necessário para ser aprovado é 71%.

Para realizar este exame você precisa comprar o voucher no site da Oracle, ou realizar todo o processo diretamente no site da PersonVUE.

Para se preparar para este exame você precisa estudar basicamente os seguintes tópícos:
  • Design Patterns;
  • Requisitos não funcionais;
  • Tecnologias da Plataforma Java EE 6.

Dicas

  • No momento do exame manter a calma, e evitar ficar muito tempo em uma mesma questão, por exemplo, na tela do exame você tem a opção de marcar para revisão, caso você perceba que esta perdendo tempo em uma determinada questão, marque para revisão e vá para a seguinte, só tenha cuidado para não marcar muitas questões e no final não conseguir responder todas.


Exame 1Z0-865 (Assignment)

Esta prova é sem dúvida a que deixa as pessoas com mais dúvidas, ela é composta por um projeto, onde você é o arquiteto responsável por elaborar uma arquitetura para solucionar os requisitos propostos.

Para realizar este exame você precisa comprar o voucher no site da Oracle, ou realizar todo o processo diretamente no site da PersonVUE.

Após você realizar a compra do exame, você ira realizar o download da especificação do projeto no site da PersonVUE, esta especificação contém todos os detalhes do seu projeto.

Dicas

  • Prazo de Entrega
    • Aqui sem dúvida é o principal ponto de atenção, após a compra do exame, você tem 6 meses para efetuar o submit do projeto;
    • Atenção: Este prazo agrega o envio do projeto (1Z0-865) e a realização do exame (1Z0-866), então você precisa enviar o projeto e realizar a prova dissertativa dentro do prazo de 6 meses.
  • Criação do Projeto
    • Leia com muita atenção o documento de requisitos, procure entender e focar nos requisitos não funcionais, por exemplo, caso seu projeto necessite de Escalabilidade, deixe claro Como você irá solucionar este problema;
    • O projeto é criado utilizando UML, ou seja, não é necessário nenhum código, em sua especificação irá conter todos os diagramas que você precisa enviar e o score que cada um terá em sua nota final, mas basicamente os diagramas são: Classes, Componentes, Deployment e Sequência;
    • Quando estamos entendendo os requisitos do projeto, é comum identificar pontos com pouca clareza, ou até mesmo não detalhados, então precisamos realizar algumas suposições sobre os requisitos, é muito importante que você crie um documento contendo todas as suas suposições (Assumptions), porque é necessário que você encaminhe estas informações no seu projeto;
    • Outras informações que devemos registrar são as decisões (Decisions) que tomamos no decorrer do desenvolvimento, por exemplo, "Utilizamos Cluster de Application Server para aumentar a escalabilidade";
    • No projeto também é necessário pontuar os riscos do projeto (Risks), e detalhar como você irá solucionar cada um deles;
    • Todo o projeto deve ser desenvolvido em Inglês, sendo as notas que vocês acrescenta nos diagramas, os documentos, e qualquer outra parte onde você escreva.


Exame 1Z0-866 (Essay)

Esta fase é a ultima etapa para concluir a Certificação, sendo ela um exame onde você irá responder algumas questões sobre o projeto que você desenvolveu, diferente das outras certificações Java, esta é uma prova dissertativa, então caso não tenha um total domínio do Inglês (leitura e escrita), recomendo treinar antes, para que não tenha dúvidas ou interpretações erradas.

Para realizar o exame você terá 120 minutos, o site marca o número de questões como NA, quando realizei o exame foram 8 questões, e os 120 minutos foram em cima para responder todas, então recomendo muita atenção neste ponto para não se preocupar com tempo.

Dicas
  • Prazo de Entrega
    • Como mencionei anteriormente, você terá um prazo de 6 meses após comprar o Assigment, para realizar o submit do projeto prático e realizar o Essay em um centro oficial;
    • Muito importante não deixe para os últimos dias o envio do Assigment e o exame Essay, porque em caso de passar o tempo, terá que realizar uma nova compra de ambas as provas, assim irá perder tempo e dinheiro;
    • Outra dica que acho fundamental é marcar o Essay logo após enviar o Assigment, porque dessa forma você tem seu projeto e todos detalhes em mente, facilitando e muito as suas respostas, lembre-se que os avaliadores iram analisar se as respostas do Essay estão alinhadas com o Assigment. 
  • Questões
    • As Questões focam em vários aspectos da arquitetura, então podem existir questões como:
      • How does your Design handle Availability ?
      • How does your Design handle Persistence ?
    • Do decorrer do projeto prático, recomendo ir treinando possíveis questões, isso ajuda muito na hora do exame.


Envio do Curso Oficial (Course Submission Form)

Esta etapa exige que o candidato tenha concluído um Curso Oficial, e envie os dados através do site da PersonVUE.

Esta etapa consiste em preencher alguns dados com informações sobre o titulo que você deseja, no caso a OCM Java EE, e dados sobre curso que realizou, após alguns dias do envio, você será notificado se as informações são válidas para obter o titulo.

Realize esta etapa somente após ser aprovado em todos os exames anteriores, pois caso não seja aprovado, esta etapa não é necessária.

Materiais de Estudo

Com relação a materiais, existem muitos, isto porque praticamente passamos por todas as áreas da Plataforma, sendo Web, Segurança, Persistência, Requisitos não Funcionais, etc, vou listar alguns materiais e livros que recomendo para ajudar nas etapas da certificação:
  • Material do Curso Oficial
    • Sem dúvida ajudou muito, principalmente no exame 1Z0-807, como mencionei realizei o treinamento "Architect Enterprise Applications with Java EE";
  • Livro: UML 2 - UMA ABORDAGEM PRATICA 
    • Autor: GILLEANES T. A. GUEDES
    • Editora: Novatec
  • Livro: OCM Java EE 6 Enterprise Architect Exam Guide 
    • Autor: Paul R. Allen ‎e Joseph J. Bambara
    • Editora: McGraw-Hill Education 
  • Documentação Oficial Java EE Oracle


Conclusão

Esta Certificação é bem complexa e detalhada, mas com certeza vale muito a pena buscar este titulo, além de ser o mais importante entre as certificações do mundo Java, sem dúvida é uma ótima maneira de aprender e se aprofundar no mundo Java EE.

Até a próxima.

Utilizando Profiles com Spring Boot

Olá hoje iremos ver como trabalhar com Profiles dentro de aplicações desenvolvidas com SpringBoot.

O que são Profiles

Profiles são recursos para determinar o ambiente onde a aplicação irá executar, e o Spring trabalha com esse tipo de situação de uma maneira muito transparente, e em aplicações onde utilizamos SpringBoot isso se torna ainda mais simples.

Imagine o cenário onde você tenha uma interface e sua implementação muda de acordo com o ambiente de execução, veja o exemplo:
  • Desenvolvimento (dev);
  • Homologação (homolog);
  • Produção (prod).


Criando Profiles

Antes de tudo vamos criar uma aplicação com Spring Boot, caso tenha dúvidas de como criar uma aplicação veja Aqui , abaixo veja como ficou nosso pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>

 <groupId>br.com.cvinicius</groupId>
 <artifactId>boot-profile</artifactId>
 <version>1.0.0-SNAPSHOT</version>
 <packaging>jar</packaging>

 <parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>1.5.9.RELEASE</version>
 </parent>

 <properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  <java.version>1.8</java.version>
 </properties>

 <dependencies>
  <dependency>
   <groupId>org.projectlombok</groupId>
   <artifactId>lombok</artifactId>
  </dependency>
 
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
  </dependency>

  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-test</artifactId>
   <scope>test</scope>
  </dependency>
 </dependencies>

 <build>
  <plugins>
   <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
   </plugin>
  </plugins>
 </build>
</project>

Repare que é uma aplicação básica, e não precisamos de nenhum starter especifico para trabalhar com profiles, pois este recurso já esta embutido no core do Spring Framework.

Vamos criar as seguintes classes e interfaces em nosso projeto:

Interface Message

public interface Message {

    String getMessage();
}

Classe DevMessage

@Profile("dev")
@Component
public class DevMessage implements Message{

 @Override
 public String getMessage() {
  return "Ambiente de Desenvolvimento";
 }
}

Classe HomologMessage

@Profile("homolog")
@Component
public class HomologMessage implements Message{

 @Override
 public String getMessage() {
  return "Ambiente de Homologação";
 }
}

Classe ProdMessage

@Profile("prod")
@Component
public class ProdMessage implements Message{

 @Override
 public String getMessage() {
  return "Ambiente de Produção";
 }
}

Classe MessageApi

@RestController
public class MessageApi{

 @Autowired
 private Message message;
 
 @GetMapping("/")
 public String sendMessage(){
  return message.getMessage();
 }
}

Após criar toda a estrutura basta configurar qual profile vamos utilizar, para isto, basta adicionar uma configuração no arquivo .yml ou .properties para definir qual ambiente o sistema irá executar, a configuração é a seguinte:

server:
  port: 8080
  
spring:
  profiles:
    active: homolog

O valor adicionado na tag active: deve ser o mesmo adicionado na Annotation @Profile.

Ao Executar o sistema com profile "homolog" o resultado será o abaixo:

Resultado exibindo a mensagem da classe HomologMessage.

Faça a troca do profile e perceba que para cada ambiente o Spring irá retornar uma implementação diferente.

Código fonte:


Até a próxima.

Criando uma Aplicação com Spring Boot e MongoDB

Olá pessoal hoje iremos ver como criar uma aplicação utilizando Spring Boot e o banco NoSQL MongoDB.

Criando o Projeto

Para criar um sistema usando o SpringBoot a melhor maneira seria criar o projeto via Maven, este processo pode ser realizado de várias maneiras:
Segue como ficou o pom.xml do projeto:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>

 <groupId>br.com.cvinicius</groupId>
 <artifactId>boot-data-mongodb</artifactId>
 <version>1.0.0-SNAPSHOT</version>
 <packaging>jar</packaging>

 <description>SpringBoot com MongoDB</description>

 <parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>1.5.2.RELEASE</version>
 </parent>

 <properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  <java.version>1.8</java.version>
 </properties>

 <dependencies>
  <dependency>
   <groupId>org.projectlombok</groupId>
   <artifactId>lombok</artifactId>
  </dependency>
 
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
  
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-mongodb</artifactId>
  </dependency>

  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-test</artifactId>
   <scope>test</scope>
  </dependency>
 </dependencies>

 <build>
  <plugins>
   <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
   </plugin>
  </plugins>
 </build>
</project>

Analisando nossas configurações temos alguns pontos interessantes:
  • Utilizamos o spring-boot-starter-web, este é utilizado para a criação de apps web com SpringWeb;
  • Utilizamos o spring-boot-starter-data-mongodb, este é uma extensão do Spring Data com foco no banco de dados MongoDB.

Configuração do Spring Boot

Após a criação do projeto vamos configurar o Spring Boot, para isso vamos criar/editar o arquivo application.yml, localizado dentro de src/main/resources, nosso arquivo ficará da seguinte forma:

1
2
3
4
5
6
7
8
9
server:
  port: 8080
  
spring:
  data:
    mongodb:
      host: localhost
      port: 27017
      database: boot-mongodb

  • server.port: Aqui configuramos a porta que o servidor embedded irá alocar;
  • spring.data.mongodb.*: Aqui adicionamos detalhes da conexão com o MongoDB, tais como host, port, e database.
Caso a sua instalação do MongoDB esteja com o recurso de autenticação ativada, o application.yml ficará da seguinte forma:

1
2
3
4
5
6
7
8
server:
  port: 8080
  
spring:
  data:
    mongodb:
      uri: mongodb://{user}:{password}@localhost:27017
      database: boot-mongodb

Também temos a classe comum de todo projeto que usa SpringBoot, esta é responsável por inicializar nossa aplicação:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
package br.com.cvinicius.mongo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class BootDataMongodbApplication {

 public static void main(String[] args) {
  SpringApplication.run(BootDataMongodbApplication.class, args);
 }
}

Criando o Domain

Vamos criar o nosso modelo de domínio, aqui iremos adicionar tudo que faz parte da camada de negocio da nossa aplicação:

Entidade Cliente:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
package br.com.cvinicius.mongo.domain;

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

import lombok.Data;

@Data
@Document(collection="cliente")
public class Cliente {

 @Id
 private String id;
 
 private String razaoSocial;
}

A Entidade possui 2 atributos sendo id e razaoSocial, onde o id (cnpj) é a chave unica representada com o @Id, temos o @Document que mapeia a entidade para a collection no MongoDB, e também utilizando o Lombok para evitar o código boilerplate.

Repository Cliente:

1
2
3
4
5
6
7
package br.com.cvinicius.mongo.domain;

import org.springframework.data.mongodb.repository.MongoRepository;

public interface ClienteRepository extends MongoRepository<Cliente, String>{

}

Aqui apenas fazemos um extends para a interface MongoRepository, assim já herdamos todos os métodos, tais como:  find, count, insert, update e findOne.

Criando a API

Para criar a API iremos utilizar os recursos do SpringMVC, aqui iremos adicionar 2 métodos, sendo uma listagem e um detalhamento:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package br.com.cvinicius.mongo.api;

import java.util.List;
import java.util.Objects;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import br.com.cvinicius.mongo.domain.Cliente;
import br.com.cvinicius.mongo.domain.ClienteRepository;

@RestController
@RequestMapping("/cliente")
public class ClienteAPI {

 @Autowired
 private ClienteRepository repository;
 
 @GetMapping
 public ResponseEntity<?> list(){
  
  List<Cliente> list = repository.findAll();
  
  return ResponseEntity.ok(list);
 }
 
 @GetMapping(path="/{cnpj}")
 public ResponseEntity<Cliente> view(@PathVariable String cnpj){
  
  Cliente cliente = repository.findOne(cnpj);
  
  if(Objects.isNull(cliente)){
   
   return ResponseEntity.noContent().build();
  }
  else{
   return ResponseEntity.ok(cliente);
  }
 }
}

Aqui temos os métodos:
  • list: este retorna uma lista de clientes;
    • URL: http://localhost:8080/cliente
  • view: este retorna detalhes de um cliente a partir de um CNPJ;
    • URL: http://localhost:8080/cliente/{cnpj}

Dados no MongoDB

Após a aplicação estar pronta, é necessário que o MongoDB esteja configurado e funcionando corretamente, para testes criamos o seguinte banco de dados:
  • Database: boot-mongodb
    • Collection: cliente
Collection cliente com 2 registros adicionados.
Após todos os passos temos nossa Aplicação pronta para o uso, para ver o código acesse o repo no GitHub.

https://github.com/cvinicius987/projetos-spring-boot

Referências

Criando objetos com @Builder e @Value do framework Lombok

Hoje iremos ver como utilizar as anotações @Builder e @Value do framework Lombok, visando melhorar a forma de criação de objetos.

Utilizando a anotação @Builder


O nome vem do Pattern Builder, que é um pattern que visa a criação de objetos, ou seja é um pattern de Criação.

Vamos analisar a classe abaixo:

1
2
3
4
5
6
7
@Getter
@Builder
public class Cliente {
     private String nome;
     private String cnpj;
     private String endereco;
}

O arquivo compilado irá ter a seguinte estrutura:

Resultado da compilação utilizando @Builder.

No exemplo acima, notamos que o Lombok criou uma classe interna chamada ClienteBuilder, seguindo os preceitos do pattern, agora podemos criar um objeto Cliente utilizando uma forma fluente, assim deixando o código mais simples e funcional, como abaixo:

1
2
3
4
5
Cliente.builder()
       .nome("Nome do Cliente")
       .cnpj("1234567890")
       .endereco("São Paulo")
       .build();

Quando trabalhamos com a criação de modelos de domínio complexos, onde cada entidade possui vários relacionamentos e atributos o uso dessa abordagem ajuda muito.


Utilizando a anotação @Value


Um outro recurso interessante do Lombok é a anotação @Value, com ela podemos criar objetos imutáveis, este tipo de objeto, são aqueles que após criados, não podem ter seu conteúdo alterado, os principais exemplos que temos desse tipo de objeto são as classes String, Integer, Calendar, etc.

Na plataforma Java, para criarmos objetos imutáveis temos que utilizar a palavra reservada final, evitar o uso de setters, e toda lógica de criação deve ser realizada no momento da construção do objeto.

1
2
3
4
5
6
7
@Value
@Builder
public class Cliente {
    private String nome;
    private String cnpj;
    private String endereco;
}

Perceba que adicionamos a anotação @Value e removemos a @Getter, pois o seu comportamento é justamente marcar a classe e seus atributos como final, criar todos os getters necessários e criar os métodos equals(), hascode() e toString().

Resultado a compilação da classe usando @Value e @Builder.
O uso dessa classe fica da mesma forma do exemplo com @Builder, mas agora temos certeza de estarmos trabalhando com um objeto imutável, em conjunto de uma forma fluente de criação de objetos.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public class CriacaoCliente {

 public static void main(String[] args){
 
      Cliente cliente = Cliente.builder()                                          
                                      .nome("Titulo Cliente")
                               .cnpj("1234567890")
                               .endereco("Endereço Cliente")
                               .build();
  
       System.out.println(cliente);
 }
}

Utilizando essas boas práticas conseguimos ter um código Java limpo e de simples evolução.

Até a próxima.

Referências



Melhorando a qualidade do código com Lombok

Olá pessoal, hoje iremos ver como podemos melhorar a escrita do código Java evitando o famoso "Don't repeat your self", conhecido também como código boilerplate, isso tudo usando o projeto Lombok.

O famoso código boilerplate


O código boilerplate é aquele que a linguagem ou tecnologia, nos obriga a fazer para criar classes, métodos, e compor comportamentos aos nossos sistemas, no Java, temos muitos pontos que fazemos código boilerplate, as vezes nem percebemos, pois já estamos acostumados com a estrutura da linguagem.

Com a evolução da plataforma Java, vários recursos foram introduzidos, que nos ajudou a reduzir o famoso código boilerplate, tais como: Lambdas, Streams, Optional, Default Methods, etc.

Apesar da constante evolução da plataforma, ainda existem pontos que precisamos executar de forma manual, ou com a ajuda das IDEs, vamos avaliar alguns deles:
  • Getters/Setters;
  • Construtores;
  • Equals e HashCode;
  • toString();
  • Variáveis de log e depuração. 
Mas a grande vantagem da plataforma Java, é sua flexibilidade e extensibilidade, com isso podemos resolver esse tipo de problema utilizando frameworks que executam esse tipo de tarefa, que é o caso do Lombok.

Conhecendo o Lombok


O Lombok é um framework que permite a criação de códigos boilerplate de forma mais clara usando anotações, ele atua no processo de compilação, onde temos a instrução no bytecode (.class), mas no arquivo .java o código fica limpo contendo apenas as anotações.

Configurando o Lombok


A configuração do Lombok é bem simples, ele consiste em adicionar a dependência  no pom.xml, para compilação via maven, e executar um jar para compilação nas IDEs:

Maven:

1
2
3
4
5
6
 <dependency>
  <groupId>org.projectlombok</groupId>
  <artifactId>lombok</artifactId>
  <version>1.16.14</version>
  <scope>provided</scope>
 </dependency>

Eclipse IDE:
  • Execute o jar lombok.jar;
  • Na tela de configuração, indique o diretório de instalação da sua IDE.
Para mais detalhes sobre a instalação consulte:


Estudo de Caso 


Para analisar os ganhos no uso do Lombok, vamos analisar a classe abaixo:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
public class Usuario{

 private String nome;
 private String cpf;
 private String rg;
 
 public Usuario() {}

 public Usuario(String nome, String cpf, String rg) {
  this.nome = nome;
  this.cpf = cpf;
  this.rg = rg;
 }

 public String getNome() {
  return nome;
 }

 public void setNome(String nome) {
  this.nome = nome;
 }

 public String getCpf() {
  return cpf;
 }

 public void setCpf(String cpf) {
  this.cpf = cpf;
 }

 public String getRg() {
  return rg;
 }

 public void setRg(String rg) {
  this.rg = rg;
 }

 @Override
 public int hashCode() {
  final int prime = 31;
  int result = 1;
  result = prime * result + ((cpf == null) ? 0 : cpf.hashCode());
  result = prime * result + ((nome == null) ? 0 : nome.hashCode());
  result = prime * result + ((rg == null) ? 0 : rg.hashCode());
  return result;
 }

 @Override
 public boolean equals(Object obj) {
  if (this == obj)
   return true;
  if (obj == null)
   return false;
  if (getClass() != obj.getClass())
   return false;
  Usuario other = (Usuario) obj;
  if (cpf == null) {
   if (other.cpf != null)
    return false;
  } else if (!cpf.equals(other.cpf))
   return false;
  if (nome == null) {
   if (other.nome != null)
    return false;
  } else if (!nome.equals(other.nome))
   return false;
  if (rg == null) {
   if (other.rg != null)
    return false;
  } else if (!rg.equals(other.rg))
   return false;
  return true;
 }

 @Override
 public String toString() {
  return "Usuario [nome=" + nome + ", cpf=" + cpf + ", rg=" + rg + "]";
 } 

Esta classe possui 2 construtores, métodos Get/Set para os 3 atributos, equals(), hashcode() e toString(), repare que a classe não possui nenhuma lógica de negócio, mas mesmo assim possui uma grande quantidade de código.

Para garantir o funcionamento da classe vamos executar um caso de teste feito com JUnit:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class UsuarioTest {

 @Test
 public void criarUsuarioComSetterGetterTest(){
  
  Usuario usuario = new Usuario();
  
  usuario.setCpf("0123456789");
  usuario.setRg("9874563210");
  usuario.setNome("Usuario 1");
  
  Usuario usuario2 = new Usuario();
  
  usuario2.setCpf("9874563210");
  usuario2.setRg("0123456789");
  usuario2.setNome("Usuario 2");
  
  Assert.assertNotEquals(usuario, usuario2);
 }
 
 @Test
 public void criarUsuarioComConstrutorTest(){
  
  Usuario usuario  = new Usuario("0123456789", "9874563210", "Usuario 1");
  Usuario usuario2 = new Usuario("9874563210", "0123456789", "Usuario 2");
  
  Assert.assertNotEquals(usuario, usuario2);
 }
}


Melhorando o código com Lombok 


Vamos aplicar alguns recursos do Lombok visando reduzir muito do código acima, vamos usar as seguintes anotações:
  • @Getter/@Setter: Geração dos métodos Get/Set;
  • @EqualsAndHasCode: Criação dos métodos equals() e hashCode();
  • @NoArgsConstructor: Criação de um construtor sem argumentos;
  • @AllArgsContructor: Criação de um construtor com todos os atributos da classe;
  • @ToString: Criação do método toString().

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
@AllArgsConstructor
@NoArgsConstructor
@ToString
@EqualsAndHashCode
public class Usuario{

 @Getter @Setter
 private String nome;
 
 @Getter @Setter
 private String cpf;
 
 @Getter @Setter
 private String rg;
}


Analisando o código acima, percebemos uma grande redução de códigos, reduzindo de 79 para apenas 15 linhas, veja no Outline do Eclipse a estrutura gerada:

Classe gerada após a compilação do .java
Será que podemos reduzir um pouco mais ? 
A resposta é sim, usando a anotação @Data, podemos retirar as anotações @Getter/@Setter, @ToString, @EqualsAndHashCode, nosso código ficará assim:


1
2
3
4
5
6
7
8
9
@AllArgsConstructor
@NoArgsConstructor
@Data
public class Usuario{

 private String nome;
 private String cpf;
 private String rg;
}

Ao executar os testes todos são executamos normalmente, e agora temos um código muito mais simples com as mesmas funcionalidades da primeira versão apresentada. 

Outros recursos do Lombok


O Lombok possui muitos outros recursos que podemos usar dentro das aplciações Java, para mais detalhes dos recursos acesse a pagina oficial:


Aqui existem exemplos de todas as anotações que podem ser usadas para reduzir códigos boilerplate. das aplicações.

Conclusão


Vimos aqui o poder do framework Lombok, e que é possível escrever código Java simples e reduzir aqueles códigos boilerplate, que escrevemos sem perceber.

Podemos usar Lombok em tudo ? 
A resposta é depende, para cada cenário vale a pena analisar as características da sua classe e método, na maioria dos casos é possível utilizar.

Podemos customizar a geração do método ?
A resposta é sim, cada anotação possui vários atributos que podem ser utilizados para gerenciar o criação do recurso.

Até a próxima.

Referências




Melhorando a sobrescrita dos métodos equals() e hashCode()

Olá hoje iremos melhorar a forma que realizamos uma tarefa que muitos desenvolvedores não gostam de fazer, ou até mesmo deixam de lado, mas é de extrema importância para o correto funcionamento dos nossos Objetos, que é a sobrescrita dos métodos equals e hashCode().

Sobrescrita utilizando uma IDE


A maioria das IDEs realizam a tarefa de sobrescrever os métodos equals(Object o) e hashCode(), mas o código gerado não é dos melhores, vamos analisar um exemplo da geração automática usando a IDE Eclipse, segue o código:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class Cliente {

 private String cpf;
 
 public Cliente(String cpf) {
  this.cpf = cpf;
 }

 public String getCpf() {
  return cpf;
 }

 @Override
 public int hashCode() {
  final int prime = 31;
  int result = 1;
  result = prime * result + ((cpf == null) ? 0 : cpf.hashCode());
  return result;
 }

 @Override
 public boolean equals(Object obj) {
  if (this == obj)
   return true;
  if (obj == null)
   return false;
  if (getClass() != obj.getClass())
   return false;
  Cliente other = (Cliente) obj;
  if (cpf == null) {
   if (other.cpf != null)
    return false;
  } else if (!cpf.equals(other.cpf))
   return false;
  return true;
 }
}

O código acima esta bem poluído, porque a IDE adiciona vários blocos condicionais para garantir a integridade dos métodos, para confirma o funcionamento vamos criar um caso de teste usando JUnit:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public class ClienteTest{
 
 @Test
 public void equalsClienteTest(){
  
  Cliente cliente  = new Cliente("9876543210");
  Cliente cliente2 = new Cliente("9876543210");

  Assert.assertEquals(cliente, cliente2);
 }
 
 @Test
 public void notEqualsClienteTest(){
  
  Cliente cliente  = new Cliente("0123456789");
  Cliente cliente2 = new Cliente("9876543210");

  Assert.assertNotEquals(cliente, cliente2);
 }
 
 @Test
 public void leftNullEqualsClienteTest(){
  
  Cliente cliente  = new Cliente(null);
  Cliente cliente2 = new Cliente("9876543210");

  Assert.assertNotEquals(cliente, cliente2);
 }

 @Test
 public void rightNullEqualsClienteTest(){
  
  Cliente cliente  = new Cliente("0123456789");
  Cliente cliente2 = new Cliente(null);

  Assert.assertNotEquals(cliente, cliente2);
 }
}

Ao executar o teste, podemos notar que nossa implementação esta correta, porém a escrita do código pode melhorar.

Sobrescrita usando a classe java.util.Objects


A classe java.util.Objects possui uma porção de métodos utilitários que ajudam na manipulação de objetos variados, esta classe esta disponível a partir do Java 7, vamos analisar como esta classe pode nos ajudar a melhorar a sobrescrita do método equals(Object o) e hasCode():


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class Cliente {

 private String cpf;
 
 public Cliente(String cpf) {
  this.cpf = cpf;
 }

 public String getCpf() {
  return cpf;
 }
 
 @Override
 public int hashCode(){
  return Objects.hash(this.cpf);
 }

 @Override
 public boolean equals(Object obj){
  
  if(Objects.nonNull(obj) && getClass() != obj.getClass()){
   return false;
  }
  else{
   final Cliente other = (Cliente) obj;
         
         return Objects.equals(this.cpf, other.cpf);
  }
 }
}

Executando o JUnit novamente, todos os casos de testes são executados com sucesso, e podemos notar um código bem mais limpo e simples, isso porque estamos usando os métodos Objects.hash e Objects.equals que ajudam na escrita das implementações do hashcode e equals.

Melhorando ainda mais seu Código


Mesmo usando a classe java.util.Objects,  nossa classe ainda possui um código muito vinculado a sua infraestrutura, com isso temos o famoso código boilerplate, que é aquele código repetitivo que temos que criar em todas as classes do nosso domínio, exemplo:
  • Construtores;
  • Getters e Setters;
  • hashCode();
  • equals(Object o);
  • toString().
Para melhorar isso existem uma porção de APIs e Frameworks que podem gerenciar esse tipo de tarefa: