Série DesignPattern:Builder

Olá Pessoal,

No post da série de hoje vamos conhecer mais um Design Pattern: o Builder. Ele pertence aos Padrões de criação. No post vamos entender melhor o objetivo desse padrão e teremos um exemplo prático para desenvolver e entender à nível de código Java como as coisas acontecem, ou seja, será uma pequena prova de conceito.  Como sempre buscarei usar uma linguagem informal e direta.

Lets go…

Builder

É uma interface que define os passos para criação do produto.

Exemplo:

“para gerar um boleto informe:  sacado,cedente, valor, vencimento, NossoNro e após que você informar tudo isso terá um boleto pronto (ou seja, retorne um boleto pronto)”

Permitir separar a construção do objeto e sua representação, possibilitando a construção passo-passo do objeto, esse é o objetivo do Builder.

Exemplo: Boleto Bancário

Cada banco possui informações específicas no boleto, mas todos devem seguir (implementar) as regras básicas FEBRABAN.

O padrão Builder é formado por:

  • Product (boleto): a interface que define os objetos a serem construídos pelo Builder. Podemos usar um exemplo tentando responder a seguinte pergunta: o que um boleto precisa?
    Resposta: sacado, cedente, código de barras, valor e vencimento. (claro que há outras informações requeridas, mas me limitei a essas).
  • Builder: é uma interface que define os passos para criação do produto.
  • ConcreteBuilder: cria o Product (boleto).
  • Director: chama o builder (qualquer implementação de Builder) para construir o produto. “Ei, passe as informações que teremos no boleto para o JoãoBuilder que ele vai gerar um para você.”

Praticando…
Nada melhor que praticar não é? Então a seguir vamos ver como ter o padrão Builder em uma aplicação Java.

Criaremos um projeto conforme a imagem a seguir:

Passo 1
O primeiro passo é pensar como você pode gerar N boletos de maneira simples e de fácil manutenção. Há N bancos no mercado: Itaú, Bradesco, Banco do Brasil etc, e cada dia novos bancos vão surgindo e talvez sua aplicação terá que dar suporte àquele novo banco que, quando você desenvolveu a aplicação, não existia. Mas você quer fazer isso da forma mais simples possível. Adicionar um novo banco emissor de boletos não pode ser algo custoso para seu projeto.
Então vamos ter:

  • – uma interface chamada Boleto: interface tem como objetivo de dizer a cada banco o que um boleto tem e deve ser preenchido. Por exemplo:
    Um boleto deve ter: quem é o sacado, cedente, uma data de vencimento e um valor”. Independente do banco ou produto, um boleto tem quer ter essas informações preenchidas, do contrário não temos um boleto pronto para uso.

package com.camilolopes.interfaces;

import java.util.Calendar;
/*
* interface que define o que um boleto
* deve ter. qualquer banco quer tem interesse em gerar
* um boleto deve informar quem é o sacado, cedente
* o prazo para pagto e o valor.
*/
public interface Boleto {
String getSacado();
String getCedente();
Calendar getVencimento();
double getValor();

}

Passo 2
Uma vez que já definimos o que deve constar em um boleto para que ele possa ser gerado, agora vamos criar uma interface quer será capaz de criar o boleto. É essa interface que vai dizer aos bancos o que eles devem informar para ter o boleto, ou seja, é o nosso Builder:

package com.camilolopes.interfaces;

import java.util.Calendar;

/*
* interface para criação do Product
*/
public interface BoletoBuilder {
void buildSacado(String sacado);
void buildCedente(String cedente);
void buildValor(double valor);
void buildVencimento(Calendar vencimento);
void buildNossoNro(int nossoNro);

Boleto getBoleto();
}

Observe que agora definimos que na geração do boleto um número de controle é passado. Mas por que isso não está no Boleto? Simples, porque nesse caso não é obrigatório que o banco tenha um número de controle interno para gerar um boleto. Ele pode gerar N boletos para diferentes clientes e manter o número de controle (nossoNro) com o mesmo valor. Isso não impacta na regra de negócio de um boleto.

Passo 3
Uma vez que já definimos o que o boleto deve ter e como ele deve ser construído, agora vamos criar as classes (os bancos) que terão interesse em gerar um boleto.

ItauBoleto.java

package com.camilolopes.classes.impl;

import java.util.Calendar;

import com.camilolopes.interfaces.Boleto;
/*
* cada instituicao financeira monta o seu boleto
*/

public class ItauBoleto implements Boleto {

private String sacado;
private int nossoNro;
private Calendar vencimento;
private double valor;
private String cedente;

public ItauBoleto(String sacado, String cedente, double valor,
Calendar vencimento, int nossoNro) {
this.sacado =sacado;
this.cedente = cedente;
this.valor = valor;
this.vencimento = vencimento;
this.nossoNro = nossoNro;
}

@Override
public String getSacado() {
// TODO Auto-generated method stub
return sacado;
}

@Override
public String getCedente() {
// TODO Auto-generated method stub
return cedente;
}

@Override
public Calendar getVencimento() {
// TODO Auto-generated method stub
return vencimento;
}

@Override
public double getValor() {
// TODO Auto-generated method stub
return valor;
}

@Override
public String toString() {
return “ItauBoleto [sacado=” + sacado + “, nossoNro=” + nossoNro
+ “, vencimento=” + vencimento.getTime() + “, valor=” + valor
+ “, cedente=” + cedente + “]”;
}

}

Essa classe apenas implementa o Boleto informando e seus respectivos métodos. O método toString() é o mais importante, pois retornamos os dados do boleto quando obtemos o objeto dessa classe. Se eu quiser adicionar um logomarca ou informação extra no boleto é nesse momento que vamos implementar.

Note: infelizmente a data não está formatada comercialmente, mas não é o objetivo do post.

Passo 4
Agora eu já tenho o meu boleto para o Itaú, que é o ItauBoleto. Porém ele não é gerado ainda, preciso ter alguém que gere esse boleto. Ao consultar o sr. Builder ele falou que não pode fazer nada, apenas dizer o que eu preciso para gerar um boleto. Segundo sr. Builder, para gerar um boleto eu preciso dizer:o sacado, o cedente, valor, vencimento e um nro de controle.

ItauBoletoBuilder.java

package com.camilolopes.classes.impl;
import java.util.Calendar;
import com.camilolopes.interfaces.Boleto;
import com.camilolopes.interfaces.BoletoBuilder;

/*
* a instituicao tem um criador de boletos
*/
public class ItauBoletoBuilder implements BoletoBuilder {

private String sacado;
private String cedente;
private double valor;
private Calendar vencimento;
private int nossoNro;

@Override
public void buildSacado(String sacado) {
this.sacado = sacado;

}

@Override
public void buildCedente(String cedente) {
this.cedente = cedente;

}
@Override
public void buildValor(double valor) {
this.valor = valor;

}
@Override
public void buildVencimento(Calendar vencimento) {
this.vencimento = vencimento;

}
@Override
public void buildNossoNro(int nossoNro) {
this.nossoNro = nossoNro;
}
@Override
public Boleto getBoleto() {

return new ItauBoleto(sacado,cedente,valor,vencimento,nossoNro);
}
}

Agora sim já podemos obter um objeto Boleto pronto para uso. Uma vez que o ItauBoletoBuilder já pode construir um Boleto com base nas informações que ele recebe.

Passo 5
Porém a classe anterior apenas constrói um boleto para o ItauBoleto e o usuário não quer conhecer a construção de boleto, ele apenas quer passar um objeto de um dos bancos disponíveis  para que o boleto seja gerado. Para isso precisamos criar um GerenciadorDeBoletos que é capaz de gerar um boleto com base no tipo do objeto.

package com.camilolopes.generator;

import java.util.Calendar;

import com.camilolopes.interfaces.Boleto;
import com.camilolopes.interfaces.BoletoBuilder;
/*
* classe que gera o boleto a partir do xxBuilder
*/
public class GeneratorBoleto {
//código orientado a interfaces
private BoletoBuilder boletoBuilder;
//espero um objeto que implemente o criador de boleto
public GeneratorBoleto(BoletoBuilder boletoBuilder) {
super();
this.boletoBuilder = boletoBuilder;
}

public Boleto geraBoleto(){
//informações sobre o boleto a ser gerado
boletoBuilder.buildSacado(“Camilo Lopes”);
boletoBuilder.buildCedente(“Disney”);
boletoBuilder.buildValor(2000.00);

Calendar vencimento = Calendar.getInstance();
vencimento.add(Calendar.DATE, 20);
boletoBuilder.buildVencimento(vencimento);
boletoBuilder.buildNossoNro(1234);
//olha isso aqui que mágico
Boleto boleto = boletoBuilder.getBoleto();
return boleto;
}
}

E assim obtemos o objeto Boleto pronto para uso. Na classe Gerador de boletos não há nenhuma particularidade  de qual banco será gerado o boleto. Tudo isso depende do tipo do boleto recebido, ou seja, o que foi escolhido para ser gerado.

Passo 6
Podemos criar uma classe com o método main para visualizar o resultado. Vamos ver:

package com.camilolopes.main;

import com.camilolopes.classes.impl.ItauBoletoBuilder;
import com.camilolopes.generator.GeneratorBoleto;
import com.camilolopes.interfaces.Boleto;
import com.camilolopes.interfaces.BoletoBuilder;

public class GeradorBoletoMain {
public static void main(String[] args) {
BoletoBuilder boletoBuilder = new ItauBoletoBuilder();
GeneratorBoleto generatorBoleto = new GeneratorBoleto(boletoBuilder); //itau
Boleto boleto = generatorBoleto.geraBoleto();//retorna o boleto pronto
System.out.println(boleto);
}

}

O resultado será:

Resumindo…
Para finalizar, observe que com o padrão Builder definimos uma forma que os boletos podem ser gerados, ou seja, temos que implementar a interface Builder, é a única forma de construir um Boleto e para gerar temos uma classe responsável por qualquer tipo de Boleto, ou seja, ele gera boleto para qualquer classe que tem o boleto já construído, que nesse caso deve implementar BoletoBuilder (o nosso Builder). Adição de um novo banco é muito simples, o novo banco apenas precisa implementar a interface, nada no gerador é alterado. Observe o quanto isso é eficiente. Talvez se você não conhecesse o padrão Builder pensou em implementar usando if/else. Hmmm isso seria um inferno na sua vida, pois ia crescer/diminuir de acordo com a necessidade de negócio de ter mais ou menos bancos, sem falar que a legibilidade do código estaria comprometida.

Git Hub 

Os projetos encontram-se no Github:

https://camilolopes@github.com/camilolopes/workspacedesignpattern.git 

Vou ficando por aqui e espero que tenham gostado de mais um post da série DesignPattern não é receita de bolo.

Abraços, see ya!

Série DesignPattern: Factory Method

Olá Pessoal,

Dando continuidade a série “Design Pattern não é receita de bolo” hoje vamos conhecer o padrão Factory Method que pertence aos Padrões de Criação. Para quem não acompanhou o ultimo post, conhecemos como Design Pattern é dividido, saber qual padrão usar é tão importante quanto saber que tipo de padrão ele pertence.

Lets go…

Download do Projeto

Os projetos que serão usados no post estão no meu GitHub:

https://github.com/camilolopes/workspacedesignpattern

note: Sei que para alguns nem merecia colocar esse note por ser obvio, mas por medida de segurança achei bom não faltar. Esqueça tradução ao querer estudar Design Pattern. É em inglês o nome do padrão e evite ao máximo de traduzir. O motivo, que a tradução atrapalha mais do que ajuda.

Factory Method (Padrão de Criação)

Encapsula a escolha da classe concreta na criação de objetos de um TIPO.Ou seja, é quando tenho várias “respostas” com base no TIPO passado.

Exemplo:
se o cliente é JURIDICO(do tipo juridico) envio uma mensagem com o CNPJ;
se o cliente é FISICO(do tipo fisico) envio  uma mensagem com CPF;

Esse padrão normalmente tem um intermediario que ajuda decidir qual implementacao da classe concreta será chamada com base no tipo da chamada.

Esqueleto do padrão

  • Product: é interface que define o objeto a ser criado
  • ConcreteProduct: implementação particular do tipo do objeto a ser criado
  • Creator: classe/interface que define a assinatura do metodo responsavel pela criacao do produto
  • concreteCreator: classe que implementa ou sobrescreve o método de criação do produto.

Na prática

Veremos agora na pratica ele em ação, crie um projeto seu Eclipse e chame como achar melhor, aqui chamei de  FactoryMethodPessoa com essa estrutura:

Deixe seu projeto conforme a imagem acima. A seguir vamos meter mão na massa.

Desenvolvendo
Chegou a hora de desenvolver. O ponto mais importante ao querer entender como usar o design pattern X ou Y. É entender o objetivo dele. Na maioria das vezes, um design pattern sempre começa por uma interface para manter o código orientado a interfaces. Mas, isso não é regra. Vou fazer um desenvolvimento orientado a questionamento e alinhamento como tipo de design pattern. Foi assim que fiz para buscar entender e saber usar na hora “H”. Eu particularmente não tive ainda a felicidade de usar todos os design pattern em uma “solução cliente”, como prova de conceito é sempre mais simples. Mas, em regra de negócio as coisas são mais dinâmicas. Vamos largar de papo e mão na massa.

Passo 1
Eu me pergunto: o que minha aplicação pode fazer?  Enviar mensagens para diferentes tipos de pessoa.
Então é bom eu ter uma interface onde cada pessoa diz como quer ser chamada.

package br.com.camilolopes.interfaces;

/* Product */
public interface Envio {
void enviar(String mensagem);
}

Posso dizer que o serviço de envio de mensagens é um produto? Sim. E que será implementado com base no tipo de mensagem que deseja enviar.

Passo 2
Agora precisamos definir que tipo de mensagens vamos poder enviar. No nosso exemplo, podemos mandar mensagens com o CPF ou CNPJ, porém isso depende do tipo do cliente. Não posso mandar CPF para um cliente que é pessoa Juridica. A seguir temos a implementação da maneira mais simples, possível o objetivo é entender o design pattern.

PessoaFisica.java

package br.com.camilolopes.classes.impl;
import br.com.camilolopes.interfaces.Envio;
/*
* concreteProduct
*/
public class PessoaFisica implements Envio {
@Override
public void enviar(String mensagem) {
System.out.println(mensagem + “CPF “);
}}

PessoaJuridica.java

package br.com.camilolopes.classes.impl;
import br.com.camilolopes.interfaces.Envio;
/*
* ConcreteProduct
*/
public class PessoaJuridica implements Envio {
@Override
public void enviar(String mensagem) {
System.out.println(mensagem + “CNPJ”);
}}

Observe que para cada PessoaXX passamos uma mensagem  + uma informação privada que cada um tem. Que nesse caso seria o CPF e CNPJ. Pense assim à nivel de negócio:
“Se eu estou me comunicando com Pessoa Juridica as minhas negociações, contrato serão feitas em cima de um CNPJ, é ele que é importante na relação.” Então nesse contexto se eu quiser mandar uma  mensagem e no final envio o cnpj para confirmação.

Exemplo:
“Houve uma alteração de contrato para o CNPJ xxx”

Passo 3
Já temos as implementações do produto. Agora que vem a parter do Factory Method, onde precisamos chamar cada implementação com base no tipo. Algo assim:

Se for PessoaFisica
    chame new PessoaFisica().enviar
senão se for PessoaJuridica
    chame new PessoaJuridica().enviar

ifs encadeados nunca é uma boa opção, afeta a legibilidade e manutenção do código. Sem falar que amanhã pode nascer um novo tipo de PessoaXXX e teremos que aumentar mais ainda essa condição if/else. E veremos a seguir que conseguirmos evitar isso através do padrão factory method.

Criaremos uma classe que retorna o tipo do objeto com base no que foi passado para ele. E com esse retorno, chamaremos uma das implementações da nossa interface (Product). Veja:

package br.com.camilolopes.creator;
import br.com.camilolopes.interfaces.Envio;
/*
* classe que vai retornar o metodo implementado
* com base no tipo que recebeu
*/
public class CreatorEnvio {
//o segredo que evita N if/else encadeados \o/
public Envio getEnvio(Envio envio){
if (envio==null) {
throw new NullPointerException();
}
return envio;
}
}

Observe o segredo todo está aqui. Estamos com o código orientado à interfaces. O nosso método espera qualquer objeto que seja do tipo Envio, ou seja, qualquer implementação da interface. Verificamos se é null para não acontecer NullPointerException ao chamar o método e em seguida retornamos o objeto que recebemos.
E agora?
Simples. A classe principal que envia as mensagens, chamará CreatorEnvio passando para o tipo de pessoa que ele deseja enviar a mensagem e que mensagem será enviada. Veja:

package br.com.camilolopes.main;
import br.com.camilolopes.classes.impl.PessoaFisica;
import br.com.camilolopes.classes.impl.PessoaJuridica;
import br.com.camilolopes.creator.CreatorEnvio;
import br.com.camilolopes.interfaces.Envio;

public class MainPessoa {

public static void main(String[] args) {
CreatorEnvio creator = new CreatorEnvio();

//enviando mensagem para pessoa fisica
Envio envio = creator.getEnvio(new PessoaFisica());
envio.enviar(“caro cliente inscrito no “);

//enviando para pessoa juridica
envio = creator.getEnvio(new PessoaJuridica());
envio.enviar(“Prezada Empresa inscrita no “);
}
}

Observe que é muito simples, todo código orientado à interfaces. Se amanhã nascer um novo tipo de Pessoa, não precisamos nos preocupar, apenas passaremos isso para o método getEnvio e ele chamará a implementação de enviar(mensagem) daquele novo tipo de PessoaXX.

O resultado

Eu gosto de criar unit tests, a seguir tem o unit test que fiz para validar. Com unit test não precisamos ter uma classe com o método main para saber se o nosso código está funcionando. Veja:

package br.com.camilolopes.creator;
import static org.junit.Assert.assertTrue;
import org.junit.Before;
import org.junit.Test;
import br.com.camilolopes.classes.impl.PessoaFisica;
import br.com.camilolopes.classes.impl.PessoaJuridica;
import br.com.camilolopes.creator.CreatorEnvio;

public class CreatorEnvioTest {

private CreatorEnvio creatorEnvio;

@Before
public void setUp() throws Exception {
creatorEnvio = new CreatorEnvio();
}

@Test
public void testGetPessoaFisica() {
assertTrue(creatorEnvio.getEnvio(new PessoaFisica()) instanceof PessoaFisica);
}

@Test
public void testGetPessoaJuridica() {
assertTrue(creatorEnvio.getEnvio(new PessoaJuridica()) instanceof PessoaJuridica);
}

@Test(expected = NullPointerException.class)
public void testNullIsInvalid() {
creatorEnvio.getEnvio(null);
}
}

Criei apenas um unit test para a classe CreatorEnvio e verifiquei se ele estava retornando o tipo do  objeto correto com base no que foi passado para o método getEnvio.

Git Hub 

Os projetos encontram-se no Github:

https://camilolopes@github.com/camilolopes/workspacedesignpattern.git 

Vou ficando por aqui espero que tenham gostado do post. Apesar de ter ficado grande devido a parte pratica hehe.

Abracos, see ya

Série Design Pattern: Não é Receita de Bolo

Olá Pessoal,
Estarei dando inicio à mais uma série aqui no blog. E dessa vez será sobre Design Pattern. Claro que não abordarei todos os padrões (até porque não tenho experiência de ter usado todos no dia-dia, na minha opinião fazer um projeto como prova de conceito é uma coisa e usar para resolver problemas de cliente é outra.Não posso assumir que sei algo só porque fiz uma prova de conceito um house made e deu certo), mas aqueles que considerei importantes e que é muito comum no dia-dia. Uma vez que, para padrões não há uma receita de bolo, e sim que depende muito do contexto. E não se preocupe se você não sabe todos os design pattern de cabeça ao olhar um problema. Até por que a ideia não é decorar e sim saber usar, ter um bom livro de design pattern na sua mesa sempre é bom.
Para essa série não vou seguir um padrão em cada post, pois tudo depende do tipo do padrão que vou abordar, alguns nem precisam de código para entender, outros são tão abstratos que é preciso desenhar, enfim vou buscar usar diferentes formas de tentar explicar cada design pattern da série de forma que você ao término do post saiba o objetivo tanto teórico e uma ideia pratica de onde como usá-lo.

Lets go…

Design Pattern
Antes de mais nada é preciso conhecer os padrões: criação, estruturais e comportamentais. Pois, eles dizem qual padrão iremos usar. Por exemplo: se preciso adotar um padrão para criação de objetos, terei que olhar  para os padrões existentes  em “Padrões de criação”. Por que lá? Veremos daqui à pouco.

Então não adianta querer decorar os padrões. Na verdade eles não foram feitos para serem decorados e saber quando aplica-los de acordo com o contexto. Design Pattern não é receita de bolo, que se você seguir do passo 1 até o 10, vai ter a solução. Alias a solução do seu “problema” é com você. Design Pattern não é uma biblioteca com resoluções de problemas.

Conhecendo os Padrões

A seguir fiz uma definição de maneira mais simples e objetiva possível para cada padrão.

Note:  Quando você tiver com algum problema de design, pense em que tipo de problema que você tem antes de adotar algum padrão.

  • Padrões de criação: ajuda a encapsular  a criação de objetos de um TIPO. Ou seja, é quando temos várias “respostas” com base no tipo do objeto passado.

São eles:factory method,abstract method, builder, prototype, singleton, multiton, object pool

Exemplo:  Se o objeto é do tipo pessoa juridica eu vou fazer isso: “Olá xxx,  CNPJ:111”. Mas, se for pessoa fisica é assim: “olá xxx, CPF:0000”.

  • Padrões Estruturais: Está relacionado as interações entre os objetos no sistema. Ou seja, é como os meus objetos vão se relacionar com os outros objetos. Busca evitar o alto acomplamento entre objetos.

São eles:adapter, bridge, composite, decorator, facade, front controller, flyweight, proxy

Então quando você precisar definir como será as interações entre objetos, não esqueça em dar uma olhada nos Padrões Estruturais e ver qual deles podem atender à sua necessidade.

  • Padrões Comportamentais: está relacionado  em saber as intenções  que um objeto pode fazer e como ele se relaciona com os outros objetos.

São eles:command, iterator, mediator, observer, state, strategy, template method, visitor

Como estudar?

Há dois livros bem famosos sobre o assunto. Um deles é do Erich Gama: Design Patterns: Elements of Reusable Object-Oriented Software e o outro é da série use a cabeça: Head First Design Pattern. E qual comprar?
Eu recomendo os dois.A ordem de leitura na minha opinião seria primeiro o da série Head First, caso você seja iniciante no assunto. O livro é bem didático. O do Erich eu diria é quando já temos uma certa dose de conhecimento sobre design pattern e queremos entender com mais detalhe. Há trechos no livro que o autor não é muito claro, e que para conseguir entender o que ele quis dizer é preciso já ter uma certa base de Design Pattern do contrário a informação fica perdida.  O livro do Erich Gamma é uma especie de referência que deve ficar na sua mesa para consultar. Até pq você não vai decorar os design pattern.

Git Hub 

Os projetos da série  estão Github:

https://camilolopes@github.com/camilolopes/workspacedesignpattern.git 

Abracos, vou ficando por aqui e espero que tenham gostado desse primeiro post. No próximo já vamos brincar colocando mão na massa.
See ya!!!

Validando campos com JSF

 

olá Pessoal, hoje o post é dedicado para quem está aprendendo JSF e pretende usar os recursos de validação de campo do proprio  framework. Perguntas comuns sobre validação: como validar um email? Como validar um campo número? É isso que veremos, claro que mostrarei um pequeno exemplo “motivador”, vai de você criar outras validações para seu formulário. Observe que é algo bem simples e funcional. E para aqueles que  estão estudando para antiga SCJP e acham que regex é algo somente para certificação, Vejam nesse post o poder que regex tem. No post tem um link para “testador de expressões regex online”. Muito show, já tem até alguns exemplos prontos tais como: validação de IP, telefone etc.

lets go…

Preparando o ambiente

Certifique-se que você tem os arquivos .jars necessário para rodar JSF. Confira nos posts a seguir quais os arquivos que vc precisa. Sem falar que usar Jboss tools seria uma boa ideia. Para o nosso exemplo usaremos o plugin no Eclipse Jboss tools para suporte à JSF. Também não pode esquecer que nosso application server  será  o Tomcat, se ainda não instalou/configurou veja no exemplo abaixo.

Desenvolvimento

    1. Com o Jboss tools configurado e Eclipse aberto crie um novo JSF Project.

    2. Em WebContent crie uma página .jsp que redirecione para uma página chamada formulario.jsp. Mas, lembre-se que no seu arquivo index.jsp o code fica assim:

    3. Feito isso, vamos agora codificar nosso formulário em JSF. Para isso crie uma página em jsp com suporte JSF em WebContent chamando de formulario.jsp. Veja abaixo como criar uma página caso tenha esquecido:

    4. Abaixo temos nossa página em JSF. O uso de immediate=true em cada campo é para quando aparecer a mensagem de validação a pagina atual não seja processada, ou seja, ela não vai para a página seguinte enquanto você não atender os requisitos da validação.

    5. Agora crie uma página em .jsp que exiba uma mensagem qualquer. Pois, ela somente será exibida quando as validações da pagina do formulário forem válidas. Nos colocamos nessa página uma mensagem: Mensagem enviada com sucesso!

    6. Feito isso, precisamos criar nosso bean e controller. Então crie um package chamado br.com.bean e nele crie uma classe Java chamada de Usuario.java e deixe conforme abaixo:

  1. Agora crie um package br.com.controller e nele crie uma classe chamada Controller. É essa classe que será responsável por controlar nossa aplicação. Ela que diz aonde o usuário vai parar depois de uma determinada ação. Deixe conforme abaixo:

  2. Vá no arquivo face-config.xml e crie um ManageBean para a classe Controller conforme a imagem abaixo:

  3. Agora vamos adicionar as rules para navegação com as pages. Clique em Navigation Rules e a direita add. Veja abaixo como ficou:

  4. Precisamos apenas configurar o Navigation Cases. Veja:

  5. Uma explicação básica: “Quando vinher a uma mensagem chamada ‘sucesso’ da página formulario.jsp, favor de ir para a pagina mensagem.jsp”.

  6. Agora precisamos criar uma classe que vai validar os campos do nosso formulário, que nesse caso será apenas e-mail e idade. Para isso precisamos implementar uma interface JSF que vai nos auxiliar no processo. É a interface Validator. Para isso crie um package br.com.validator e uma classe EmailValidar e informe que essa classe implementa a interface Validator. Veja meu exemplo abaixo:

  7. Agora deixe sua classe conforme abaixo. E para não perder o costume, explicação está nos comentários.

  8. Agora vamos validar o campo idade, onde é permitido apenas digito. Crie a classe IdadeValidar.java e implemente o método Validator.

  9. Feito isso precisamos apenas informar para o nosso face-config.xml que usaremos nosso validador nesta aplicação. Veja como fazer isso:

  10. Faça o mesmo para o validator idade.

  11. Damos um nome ao validador e informamos a classe que tem a validação, o nome é requirido pois é ele que vamos usar no form.

  12. Agora vá na sua página que contém o formulário e deixe os campos email e idade conforme o código abaixo.

Testando Aplicação

  1. Salve as alterações. Se o tomcat estiver rodando, dar um stop e em seguida um start. E veja aplicação rodando. No nosso caso vamos rodar dentro do próprio Eclipse. Para isso a perspectiva que estamos usando é JavaEE depois clique com o botão direito em cima do projeto e vá em Run >> Run as >> Run on Server.

Vou ficando por aqui e espero que tenham gostado do post. Simples e básico.

See you next post! 😀

Conectar JasperReport com DB via Hibernate

Olá Pessoal,

O objetivo deste post é mostrar como conectar com jasperReport com DB usando Hibernate, é comum ver a conexão via JDBC tradicional, mas nem sempre é isso que queremos.Então veremos agora com Hibernate.

Lets go…

Contexto

Talvez você já tenha passado por o problema abaixo:

Class.forName(“com.mysql.jdbc.Driver”);

String db = “jdbc:mysql://localhost:3306/relatorios”;

conn = DriverManager.getConnection(db,”camilo”,”lopes”);

E não será nada legal ter que colocar esses dados dentro do seu code Java, ou criar um arquivo separado só para isso, e quando o user/password/url, sofrerem alterações teremos que mudar em mais de um lugar? Duplicated Context is not good! :). Até um dia desses nunca precisei eu não tinha preocupação com a conexão uma vez que já passava para o JasperPrint uma lista(list) dos dados recuperados via HQL, conforme os posts a seguir:

JasperReport com JEE

JasperReport + Hibernate

Mas, nem sempre HQL,Criteria etc, atende a uma regra de negócio da melhor forma, no meu caso, já tinhamos o .SQL com as devidas queries e lá que estavam as regras com base no DB que estamos trabalhando, que vai além de um simples retrieve. Daí, será q eu deveria usar HQL/Criteria somente porque estou usando Hibernate? Neste caso, a resposta não. Tive que analisar o impacto, o custo disso e onde as mudanças aconteceriam, e após uma investigação baseado em testes, usar o .SQL será a melhor solução pelo seguintes pontos:

  • toda mudança de regra de negócio referente à DataWarehouse acontece de fato no banco, nos .SQL etc. Então não tem porque eu querer “repetir” as regras do .SQL dentro do código Java;
  • evitou a duplicação de código, porque se a regra vem da DW, o código Java só ia executar ela, então se .SQL muda, terei que mudar também o HQL, seria maior trabalho;
  • Ireport com .SQL eles tem um bom relacionamento;
  • Minha app Java fica mais especifica, com o objetivo apenas de gerar o report;

Desenvolvendo

Levando em conta que você já tem seu report pronto, vou mostrar apenas como configurar sua app para conectar do DB via Hibernate.

Step 1

Na class DAO

Adicione o método a seguir:

publicstatic Connection getConnection() throws HibernateException, SQLException{

returnnew AnnotationConfiguration().configure().buildSettings().getConnectionProvider()
.getConnection();

}

Agora na sua classe que gera o Report adicione:

Não esqueça de importar o arquivo .jrxml para o seu projeto no eclipse.

JasperReport pathRxml = JasperCompileManager.compileReport(“layout/reportcamilo.jrxml”);

JasperPrint printReport = JasperFillManager.fillReport(pathRxml, null, DAO.getConnection());

JasperExportManager.exportReportToPdfFile(printReport, “reportexcamilo.pdf”);

 

Pronto, era apenas isso, passar o objeto Connection vindo do Hibernate para o método fillReport(), se você viu os posts mais antigos, a diferença é que não tem mais a List, sendo passada no terceiro parametro.

Feito, isso, salve e rode Java Application.

Resultado:


Vou ficando por aqui, e espero que tenham gostado do post.

See ya!