Escolar Documentos
Profissional Documentos
Cultura Documentos
Caelum Java Testes JSF Web Services Design Patterns fj22 PDF
Caelum Java Testes JSF Web Services Design Patterns fj22 PDF
Cursos Online
www.caelum.com.br/online
Casa do Cdigo
Livros para o programador
www.casadocodigo.com.br
Blog Caelum
blog.caelum.com.br
Newsletter
www.caelum.com.br/newsletter
Facebook
www.facebook.com/caelumbr
Twitter
twitter.com/caelum
Sobre esta apostila
Esta apostila da Caelum visa ensinar de uma maneira elegante, mostrando apenas o que necessrio e quando
necessrio, no momento certo, poupando o leitor de assuntos que no costumam ser de seu interesse em
determinadas fases do aprendizado.
A Caelum espera que voc aproveite esse material. Todos os comentrios, crticas e sugestes sero muito
bem-vindos.
Essa apostila constantemente atualizada e disponibilizada no site da Caelum. Sempre consulte o site para
novas verses e, ao invs de anexar o PDF para enviar a um amigo, indique o site para que ele possa sempre
baixar as ltimas verses. Voc pode conferir o cdigo de verso da apostila logo no final do ndice.
Esse material parte integrante do treinamento Laboratrio Java com Testes, JSF, Web Services e Design
Patterns e distribudo gratuitamente exclusivamente pelo site da Caelum. Todos os direitos so reservados
Caelum. A distribuio, cpia, revenda e utilizao para ministrar treinamentos so absolutamente vedadas.
Para uso comercial deste material, por favor, consulte a Caelum previamente.
www.caelum.com.br
1
Sumrio
3 Testes Automatizados 31
3.1 Nosso cdigo est funcionando corretamente? . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
3.2 Exerccios: testando nosso modelo sem frameworks . . . . . . . . . . . . . . . . . . . . . . . . . 31
3.3 Definindo melhor o sistema e descobrindo mais bugs . . . . . . . . . . . . . . . . . . . . . . . . 34
3.4 Testes de Unidade . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
3.5 JUnit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
3.6 Anotaes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
3.7 JUnit4, convenes e anotao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
3.8 Exerccios: migrando os testes do main para JUnit . . . . . . . . . . . . . . . . . . . . . . . . . . 39
3.9 Vale a pena testar classes de modelo? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
3.10 Exerccios: novos testes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
3.11 Para saber mais: Import Esttico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
3.12 Mais exerccios opcionais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
3.13 Discusso em aula: testes so importantes? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
i
4.4 XStream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
4.5 Exerccios: Lendo o XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
4.6 Discusso em aula: Onde usar XML e o abuso do mesmo . . . . . . . . . . . . . . . . . . . . . . 63
ii
9.1 Por que usar grficos? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
9.2 Grficos com o Primefaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
9.3 Documentao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
9.4 Definio do modelo do grfico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
9.5 Isolando a API do Primefaces: baixo acoplamento . . . . . . . . . . . . . . . . . . . . . . . . . . 131
9.6 Para saber mais: Design Patterns Factory Method e Builder . . . . . . . . . . . . . . . . . . . . 134
9.7 Exerccios: Grficos com Primefaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
iii
Captulo 1
Na maioria dos casos, as pessoas, inclusive os facnoras, so muito mais ingnuas e simples do que
costumamos achar. Alis, ns tambm.
Fiodr Dostoivski, em Irmos Karamazov
Pragmtico aquele que se preocupa com as questes prticas, menos focado em ideologias e tentando
colocar a teoria pra andar.
Esse curso tem como objetivo trazer uma viso mais prtica do desenvolvimento Java atravs de uma experi-
ncia rica em cdigo, onde exercitaremos diversas APIS e recursos do Java. Vale salientar que as bibliotecas
em si no so os pontos mais importantes do aprendizado neste momento, mas sim as boas prticas, a cultura
e um olhar mais amplo sobre o design da sua aplicao.
Os design patterns, as boas prticas, a refatorao, a preocupao com o baixo acoplamento, os testes de uni-
dade (tambm conhecidos como testes unitrios) e as tcnicas de programao (idiomismos) so passados
com afinco.
Para atingir tal objetivo, esse curso baseia-se fortemente em artigos, blogs e, em especial, na literatura que se
consagrou como fundamental para os desenvolvedores Java. Aqui citamos alguns desses livros:
http://blog.caelum.com.br/2006/09/22/livros-escolhendo-a-trindade-do-desenvolvedor-java/
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Somamos a esses mais dois livros, que sero citados no decorrer do curso, e influenciaram muito na elabo-
rao do contedo que queremos transmitir a vocs. Todos os cinco so:
Livro de um dos principais autores das maiores bibliotecas do Java SE (como o java.io e o java.util),
arquiteto chefe Java na Google atualmente. Aqui ele mostra como enfrentar os principais problemas e
limitaes da linguagem. Uma excelente leitura, dividido em mais de 70 tpicos de 2 a 4 pginas cada,
em mdia. Entre os casos interessantes est o uso de factory methods, os problemas da herana e do
protected, uso de colees, objetos imutveis e serializao, muitos desses abordados e citados aqui
no curso.
Livro de Erich Gamma, por muito tempo lder do projeto Eclipse na IBM, e mais outros trs autores,
o que justifica terem o apelido de Gang of Four (GoF). Uma excelente leitura, mas cuidado: no saia
lendo o catlogo dos patterns decorando-os, mas concentre-se especialmente em ler toda a primeira
parte, onde eles revelam um dos princpios fundamentais da programao orientada a objetos:
Livro do cientista chefe da ThoughtWorks. Um excelente catlogo de como consertar pequenas falhas
do seu cdigo de maneira sensata. Exemplos clssicos so o uso de herana apenas por preguia,
uso do switch em vez de polimorfismo, entre dezenas de outros. Durante o curso, faremos diversos
refactoring clssicos utilizando do Eclipse, muito mais que o bsico rename.
As melhores prticas para ser um bom desenvolvedor: desde o uso de versionamento, ao bom uso do
logging, debug, nomenclaturas, como consertar bugs, etc.
Um livro que fala dos problemas que encontramos no dia a dia do desenvolvimento de software, numa
abordagem mais gerencial. Aqui h, inclusive, o clssico artigo No Silver Bullet, que afirma que nunca
haver uma soluo nica (uma linguagem, um mtodo de desenvolvimento, um sistema operacional)
que se adeque sempre a todos os tipos de problema.
No se assuste, h muito cdigo aqui nesse curso, onde vamos construir uma pequena aplicao que l um
XML com dados da bolsa de valores e plota o grfico de candlesticks, utilizando diversas APIs do Java SE e
at mesmo bibliotecas externas.
Fora isso, sinta-se vontade para entrar em contato com seu instrutor e tirar todas as dvidas que tiver
durante o curso.
Voc pode estar interessado no livro TDD no mundo real, da editora Casa do Cdigo:
http://www.tddnomundoreal.com.br/
http://www.caelum.com.br/curso/online/testes-automatizados/
O FJ-21 indicado para ser feito antes ou depois deste curso, dependendo das suas necessidades e do seu
conhecimento. Ele o curso que apresenta o desenvolvimento Web com Java e seus principais ferramentas
e frameworks.
Depois destes cursos, que constituem a Formao Java da Caelum, indicamos dois outros cursos, da Forma-
o Avanada:
http://www.caelum.com.br/formacao-java-avancada/
O FJ-25 aborda Hibernate e JPA 2 e o FJ-26 envolve JSF 2, Facelets e CDI. Ambos vo passar por tecnologias
hoje bastante utilizadas no desenvolvimento server side para web, e j na verso do Java EE 6.
Primeiro aprenda cincia da computao e toda a teoria. Depois desenvolva um estilo de programao. E a
esquea tudo e apenas hackeie."
George Carrette
O objetivo do FJ-22 aprender boas prticas da orientao a objetos, do design de classes, uso correto dos
design patterns, princpios de prticas geis de programao e a importncia dos testes de unidade.
Dois livros que so seminais na rea sero referenciados por diversas vezes pelo instrutor e pelo material:
Effective Java, do Joshua Bloch, e Design Patterns: Elements of Reusable Object-Oriented Software, de Erich
Gamma e outros (conhecido Gang of Four).
Neste curso, abordaremos esse assunto que, hoje em dia, chega a ser cotidiano desenvolvendo uma aplicao
que interpreta os dados de um XML, trata e modela eles em Java e mostra grficos pertinentes.
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Apesar da triste histria, foi em Dojima, no jardim do prprio Yodoya Keian, que nasceu a bolsa de arroz
do Japo. L eram negociados, precificados e categorizados vrios tipos de arroz. Para anotar os preos do
arroz, desenhava-se figuras no papel. Essas figuras parecem muito com velas -- da a analogia candlestick.
Esses desenhos eram feitos em um papel feito de... arroz! Apesar de usado a sculos, o mercado ocidental s
se interessou pela tcnica dos candlesticks recentemente, no ltimo quarto de sculo.
Um candlestick indica 4 valores: o maior preo do dia, o menor preo do dia (as pontas), o primeiro preo
do dia e o ltimo preo do dia (conhecidos como abertura e fechamento, respectivamente).
Os preos de abertura e fechamento so as linhas horizontais e dependem do tipo de candle: se for de alta, o
preo de abertura embaixo; se for de baixa, em cima. Um candle de alta costuma ter cor azul ou branca
e os de baixa costumam ser vermelhos ou pretos. Caso o preo no tenha se movimentado, o candle tem a
mesma cor que a do dia anterior.
Voc pode ler mais sobre a histria dos candles em: http://www.candlestickforum.com/PPF/Parameters/1_
279_/candlestick.asp
Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - Candlesticks: O Japo e o arroz - Pgina 5
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Apesar de falarmos que o Candlestick representa os principais valores de um dia, ele pode ser usado para
os mais variados intervalos de tempo: um candlestick pode representar 15 minutos, ou uma semana, depen-
dendo se voc est analisando o ativo para curto, mdio ou longo prazo.
Ele ento teve a ideia de juntar ao grupo alguns alunos do mestrado atravs de um sistema de coorientao,
onde os mestrandos auxiliariam os graduandos na implementao, modelagem e metodologia do projeto.
Somente ento o grupo definiu o tema: o desenvolvimento de um software open source de anlise tcnica
grafista (veremos o que a anlise tcnica em captulos posteriores).
http://sourceforge.net/projects/tail/
Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - O projeto Tail - Pgina 6
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Essa ideia, ainda vaga, foi gradativamente tomando a forma do projeto desenvolvido. O grupo se reunia
semanalmente adaptando o projeto, atribuindo novas tarefas e objetivos. Os graduandos tiveram a oportu-
nidade de trabalhar em conjunto com os mestrandos, que compartilharam suas experincias anteriores.
Implementar os componentes bsicos da anlise tcnica grafista: srie temporal, operaes de compra
e venda e indicadores tcnicos;
Implementar as estratgias de compra e venda mais utilizadas no mercado, assim como permitir o
rpido desenvolvimento de novas estratgias;
Permitir que o critrio de escolha da melhor estratgia seja trocado e desenvolvido facilmente;
Criar relatrios que facilitem o estudo e a compreenso dos resultados obtidos pelo algoritmo;
Criar uma interface grfica, permitindo o uso das ferramentas implementadas de forma fcil, rpida e
de simples entendimento, mas que no limite os recursos da biblioteca;
Arquitetura orientada a objetos, com o objetivo de ser facilmente escalvel e de simples entendimento;
Analisar o funcionamento do sistema de coorientao, com o objetivo estend-lo para projetos futuros.
Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - O projeto Tail - Pgina 7
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
O Tail foi desenvolvido por Alexandre Oki Takinami, Carlos Eduardo Mansur, Mrcio Vinicius dos San-
tos, Thiago Garutti Thies, Paulo Silveira (mestre em Geometria Computacional pela USP e diretor da Cae-
lum), Julian Monteiro (mestre em sistemas distribudos pela USP e doutor pelo INRIA, em Sophia Antipolis,
Frana) e Danilo Sato (mestre em Metodologias geis pela USP e Lead Consultant na ThoughtWorks).
Esse projeto foi a primeira parceria entre a Caelum e a USP, onde a Caelum patrocinou o trabalho de con-
cluso de curso dos 4 graduandos, hoje todos formados.
Caso tenha curiosidade voc pode acessar o CVS do projeto, utilizando o seguinte repositrio:
http://tail.cvs.sourceforge.net/viewvc/tail/
Essas classes formaro a base do projeto que criaremos durante o treinamento, o Argentum (do latim, di-
nheiro ou prata). As funcionalidades do sistema sero as seguintes:
Nossa base sero as negociaes. Precisamos converter uma lista de negociaes em uma lista de
Candles.
Para isso, implementar um pequeno framework de indicadores e criar alguns deles de forma a facilitar
o desenvolvimento de novos.
Gerar grficos
Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - O projeto Argentum: modelando o sistema - Pgina 8
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Para comear a modelar nosso sistema, precisamos entender alguns recursos de design de classes que ainda
no foram discutidos no FJ-11. Entre eles podemos citar o uso da imutabilidade de objetos, uso de anotaes
e aprender a trabalhar e manipular datas usando a API do Java.
O problema do double que no possvel especificar a preciso mnima que ele vai guardar e, dessa forma,
estamos sujeitos a problemas de arredondamento ao fracionar valores e voltar a som-los. Por exemplo:
System.out.println(resultado);
// 33.333?
// 33.333333?
// 33.3?
Se no queremos correr o risco de acontecer um arredondamento sem que percebamos, a alternativa usar
a classe BigDecimal, que lana exceo quando tentamos fazer uma operao cujo resultado inexato.
Como modificador de mtodo, final indica que aquele mtodo no pode ser reescrito. Mtodos muito
importantes costumam ser definidos assim. Claro que isso no necessrio declarar caso sua classe j seja
final.
Ao usarmos como modificador na declarao de varivel, indica que o valor daquela varivel nunca poder
ser alterado, uma vez atribudo. Se a varivel for um atributo, voc tem que inicializar seu valor durante a
construo do objeto - caso contrrio, ocorre um erro de compilao, pois atributos final no so iniciali-
zados com valores default.
Imagine que, quando criamos um objeto Negociacao, no queremos que seu valor seja modificado:
Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - Trabalhando com dinheiro - Pgina 9
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
class Negociacao {
// getters e setters?
Esse cdigo no compila, nem mesmo com um setter, pois o valor final deveria j ter sido inicializado. Para
resolver isso, ou declaramos o valor da Negociacao direto na declarao do atributo (o que no faz muito
sentido nesse caso), ou ento populamos pelo construtor:
class Negociacao {
Uma varivel static final tem uma cara de constante daquela classe e, se for public static final, a pa-
rece uma constante global! Por exemplo, na classe Collections do java.util existe uma constante public
static final chamada EMPTY_LIST. conveno que constantes sejam declaradas letras maisculas e sepa-
radas por travesso (underscore) em vez de usar o padro camel case. Outros bons exemplos so o PI e o E,
dentro da java.lang.Math.
Isso muito utilizado, mas hoje no java 5 para criarmos constantes costuma ser muito mais interessante
utilizarmos o recurso de enumeraes que, alm de tipadas, j possuem diversos mtodos auxiliares.
No caso da classe Negociacao, no entanto, bastar usarmos atributos finais e tambm marcarmos a prpria
classe como final para que ela crie apenas objetos imutveis.
Effective Java
Para que uma classe seja imutvel, ela precisa ter algumas caractersticas:
Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - Imutabilidade de objetos - Pgina 10
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Os atributos devem ser final, apenas para legibilidade de cdigo, j que no h mtodos que modifi-
cam o estado do objeto;
Caso sua classe tenha composies com objetos mutveis, eles devem ter acesso exclusivo pela sua
classe.
Diversas classes no Java so imutveis, como a String e todas as classes wrapper. Outro excelente exemplo
de imutabilidade so as classes BigInteger e BigDecimal:
Como o objeto imutvel, a composio interna de cada um pode ser compartilhada entre eles, j que no
h chances de algum deles mudar tais atributos. Esse compartilhamento educado possibilita fazer cache de
suas partes internas, alm de facilitar a manipulao desses objetos.
fcil entender os benefcios dessa prtica quando olhamos para o caso da String: objetos do tipo String
que contm exatamente o mesmo texto ou partes exatas do texto original (como no caso de usarmos o
substring) compartilham a array privada de chars!
Na prtica, o que isso quer dizer que se voc tem uma String muito longa e cria vrias outras com trechos
da original, voc no ter que armazenar os caracteres de novo para cada trecho: eles utilizaro o array de
chars da String original!
Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - Imutabilidade de objetos - Pgina 11
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Esses objetos tambm so ideais para usar como chave de tabelas de hash.
Thread safety
Uma classe imutvel mais simples de dar manuteno. Como no h chances de seu objeto ser modificado,
voc tem uma srie de garantias sobre o uso daquela classe.
Se os construtores j abrangem todas as regras necessrias para validar o estado do objeto, no h preocupa-
o em relao a manter o estado consistente, j que no h chances de modificao.
Uma boa prtica de programao evitar tocar em variveis parmetros de um mtodo. Com objetos imu-
tveis nem existe esse risco quando voc os recebe como parmetro.
Se nossa classe Negociacao imutvel, isso remove muitas dvidas e medos que poderamos ter durante o
desenvolvimento do nosso projeto: saberemos em todos os pontos que os valores da negociao so sempre
os mesmos, no corremos o risco de um mtodo que constri o candlestick mexer nos nossos atributos
(deixando ou no num estado inconsistente), alm de a imutabilidade tambm garantir que no haver pro-
blemas no caso de acesso concorrente ao objeto.
A classe mais antiga que representa uma data dentro do Java a Date. Ela armazena a data de forma cada
momento do tempo seja representado por um nmero - isso quer dizer, que o Date guarda todas as datas
como milissegundos que se passaram desde 01/01/1970.
O armazenamento dessa forma no de todo ruim, mas o problema que a API no traz mtodos que
ajudem muito a lidar com situaes do dia como, por exemplo, adicionar dias ou meses a uma data.
A classe Date no mais recomendada porque a maior parte de seus mtodos esto marcados como
deprecated, porm ela tem amplo uso legado nas bibliotecas do java. Ela foi substituda no Java 1.1 pelo
Calendar, para haver suporte correto internacionalizao e localizao do sistema de datas.
Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - Trabalhando com datas: Date e Calendar - Pgina 12
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
A classe abstrata Calendar tambm encapsula um instante em milissegundos, como a Date, mas ela prov
mtodos para manipulao desse momento em termos mais cotidianos como dias, meses e anos. Por ser
abstrata, no entanto, no podemos criar objetos que so simplesmente Calendars.
A subclasse concreta de Calendar mais usada a GregorianCalendar, que representa o calendrio usado pela
maior parte dos pases -- outras implementaes existem, como a do calendrio budista BuddhistCalendar,
mas estas so bem menos usadas e devolvidas de acordo com seu Locale.
H ainda a API nova do Java 8, chamada java.time, desenvolvida com base no Joda Time. Trabalharemos
aqui com Calendar por ser ainda muito mais difundida, dado que o Java 8 muito recente. Caso voc tenha
a possibilidade de trabalhar com Java 8, favorea o uso da API nova.
Para obter um Calendar que encapsula o instante atual (data e hora), usamos o mtodo esttico
getInstance() de Calendar.
Porque no damos new diretamente em GregorianCalendar? A API do Java fornece esse mtodo esttico
que fabrica um objeto Calendar de acordo com uma srie de regras que esto encapsuladas dentro de
getInstance. Esse o padro de projeto factory, que utilizamos quando queremos esconder a maneira em
que um objeto instanciado. Dessa maneira podemos trocar implementaes devolvidas como retorno a
medida que nossas necessidades mudem.
Nesse caso algum pas que use calendrios diferente do gregoriano pode implementar esse mtodo de ma-
neira adequada, retornando o que for necessrio de acordo com o Locale configurado na mquina.
Effective Java
Repare ainda que h uma sobrecarga desse mtodo que recebe Locale ou Timezone como argumento, caso
voc queira que essa factory trabalhe com valores diferentes dos valores que a JVM descobrir em relao ao
seu ambiente.
Um outro excelente exemplo de factory o DriverManager do java.sql que fabrica Connection de acordo
com os argumentos passados.
A partir de um Calendar, podemos saber o valor de seus campos, como ano, ms, dia, hora, minuto, etc.
Para isso, usamos o mtodo get que recebe um inteiro representando o campo; os valores possveis esto em
constantes na classe Calendar.
No exemplo abaixo, imprimimos o dia de hoje e o dia da semana correspondente. Note que o dia da semana
devolvido um inteiro que representa o dia da semana (Calendar.MONDAY etc):
Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - Trabalhando com datas: Date e Calendar - Pgina 13
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Calendar c = Calendar.getInstance();
System.out.println(Dia do Ms: + c.get(Calendar.DAY_OF_MONTH));
System.out.println(Dia da Semana: + c.get(Calendar.DAY_OF_WEEK));
Um possvel resultado :
Dia do Ms: 4
Dia da Semana: 5
Da mesma forma que podemos pegar os valores dos campos, podemos atribuir novos valores a esses campos
por meio dos mtodos set.
H diversos mtodos set em Calendar. O mais geral o que recebe dois argumentos: o primeiro indica qual
o campo (usando aquelas constantes de Calendar) e, o segundo, o novo valor. Alm desse mtodo, outros
mtodos set recebem valores de determinados campos; o set de trs argumentos, por exemplo, recebe ano,
ms e dia. Vejamos um exemplo de como alterar a data de hoje:
Calendar c = Calendar.getInstance();
c.set(2011, Calendar.DECEMBER, 25, 10, 30);
// mudamos a data para as 10:30am do Natal
Outro mtodo bastante usado add, que adiciona uma certa quantidade a qualquer campo do Calendar. Por
exemplo, para uma aplicao de agenda, queremos adicionar um ano data de hoje:
Calendar c = Calendar.getInstance();
c.add(Calendar.YEAR, 1); // adiciona 1 ao ano
Note que, embora o mtodo se chame add, voc pode us-lo para subtrair valores tambm; basta colocar
uma quantidade negativa no segundo argumento.
Os mtodos after e before so usados para comparar o objeto Calendar em questo a outro Calendar. O
mtodo after devolver true quando o objeto atual do Calendar representar um momento posterior ao do
Calendar passado como argumento. Por exemplo, after devolver false se compararmos o dia das crianas
com o Natal, pois o dia das crianas no vem depois do Natal:
Analogamente, o mtodo before verifica se o momento em questo vem antes do momento do Calendar
que foi passado como argumento. No exemplo acima, c1.before(c2) devolver true, pois o dia das crianas
vem antes do Natal.
Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - Trabalhando com datas: Date e Calendar - Pgina 14
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Note que Calendar implementa Comparable. Isso quer dizer que voc pode usar o mtodo compareTo para
comparar dois calendrios. No fundo, after e before usam o compareTo para dar suas respostas - apenas,
fazem tal comparao de uma forma mais elegante e encapsulada.
Por ltimo, um dos problemas mais comuns quando lidamos com datas verificar o intervalo de dias entre
duas datas que podem ser at de anos diferentes. O mtodo abaixo devolve o nmero de dias entre dois
objetos Calendar. O clculo feito pegando a diferena entre as datas em milissegundos e dividindo esse
valor pelo nmero de milissegundos em um dia:
Voc pode pegar um Date de um Calendar e vice-versa atravs dos mtodos getTime e setTime presentes na
classe Calendar:
Isso faz com que voc possa operar com datas da maneira nova, mesmo que as APIs ainda usem objetos do
tipo Date (como o caso de java.sql).
O que fazer quando descobrimos que algum mtodo ou alguma classe no saiu bem do jeito que deveria?
Simplesmente apag-la e criar uma nova?
Essa uma alternativa possvel quando apenas o seu programa usa tal classe, mas definitivamente no uma
boa alternativa se sua classe j foi usada por milhes de pessoas no mundo todo.
o caso das classes do Java. Algumas delas (Date, por exemplo) so repensadas anos depois de serem lana-
das e solues melhores aparecem (Calendar). Mas, para no quebrar compatibilidade com cdigos existen-
tes, o Java mantm as funcionalidades problemticas ainda na plataforma, mesmo que uma soluo melhor
exista.
Mas como desencorajar cdigos novos a usarem funcionalidades antigas e no mais recomendadas? A prtica
no Java para isso marc-las como deprecated. Isso indica aos programadores que no devemos mais us-las
e que futuramente, em uma verso mais nova do Java, podem sair da API (embora isso nunca tenha ocorrido
na prtica).
Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - Trabalhando com datas: Date e Calendar - Pgina 15
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Antes do Java 5, para falar que algo era deprecated, usava-se um comentrio especial no Javadoc. A partir
do Java 5, a anotao @Deprecated foi adicionada plataforma e garante verificaes do prprio compilador
(que gera um warning). Olhe o Javadoc da classe Date para ver tudo que foi deprecated.
A API de datas do Java, mesmo considerando algumas melhorias da Calendar em relao a Date, ainda
muito pobre. Numa prxima verso novas classes para facilitar ainda mais o trabalho com datas e horrios
devem entrar na especificao do Java, baseadas na excelente biblioteca JodaTime.
2) Na janela que abrir em sequncia, preencha o nome do projeto como fj22-argentum e clique em Next:
Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - Exerccios: o modelo do Argentum - Pgina 16
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
3) Na prxima tela, podemos definir uma srie de configuraes do projeto (que tambm podem ser feitas
depois, atravs do menu Build path -> Configure build path, clicando com o boto da direita no projeto.
Queremos mudar o diretrio que conter nosso cdigo fonte. Faremos isso para organizar melhor nosso
projeto e utilizar convenes amplamente utilizadas no mercado.
Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - Exerccios: o modelo do Argentum - Pgina 17
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Agora, na mesma tela, adicione um novo diretrio fonte, chamado src/main/java. Para isso, clique em
Create new source folder e preencha com src/main/java:
4) Agora basta clicar em Finish. A estrutura final de seu projeto deve estar parecida com isso:
Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - Exerccios: o modelo do Argentum - Pgina 18
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
6) Transforme a classe em final e j declare os trs atributos que fazem parte de uma negociao da bolsa de
valores (tambm como final):
public final class Negociacao {
private final double preco;
private final int quantidade;
private final Calendar data;
Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - Exerccios: o modelo do Argentum - Pgina 19
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
7) Vamos criar um construtor que recebe esses dados, j que so obrigatrios para nosso domnio. Em vez
de fazer isso na mo, na edio da classe, use o atalho ctrl + 3 e comece a digitar constructor. Ele vai
mostrar uma lista das opes que contm essa palavra: escolha a Generate constructor using fields.
Alternativamente, tecle ctrl + 3 e digite GCUF, que so as iniciais do menu que queremos acessar.
Agora, selecione todos os campos e marque para omitir a invocao ao super, como na tela abaixo.
Ateno para deixar os campos na ordem preco, quantidade, data. Voc pode usar os botes Up e
Down para mudar a ordem.
Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - Exerccios: o modelo do Argentum - Pgina 20
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
8) Agora, vamos gerar os getters dessa classe. Faa ctrl + 3 e comece a digitar getter, as opes aparecero e
basta voc escolher generate getters and setters. sempre bom praticar os atalhos do ctrl + 3.
Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - Exerccios: o modelo do Argentum - Pgina 21
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
return data;
}
}
10) Um dado importante para termos noo da estabilidade de uma ao na bolsa de valores o volume de
dinheiro negociado em um perodo.
Vamos fazer nossa classe Negociacao devolver o volume de dinheiro transferido naquela negociao.
Na prtica, s multiplicar o preco pago pela quantidade de aes negociadas, resultando no total de
dinheiro que aquela negociao realizou.
Repare que um mtodo que parece ser um simples getter pode (e deve muitas vezes) encapsular regras de
negcio e no necessariamente refletem um atributo da classe.
11) Siga o mesmo procedimento para criar a classe Candlestick. Use o ctrl + N Class para isso, marque-a
como final e adicione os seguintes atributos finais, nessa ordem:
public final class Candlestick {
private final double abertura;
private final double fechamento;
private final double minimo;
private final double maximo;
private final double volume;
private final Calendar data;
12) Use o ctrl + 3 para gerar o construtor com os seis atributos. Ateno ordem dos parmetros no cons-
trutor:
Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - Exerccios: o modelo do Argentum - Pgina 22
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - Exerccios: o modelo do Argentum - Pgina 23
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
return minimo;
}
public double getMaximo() {
return maximo;
}
public double getVolume() {
return volume;
}
public Calendar getData() {
return data;
}
}
14) (opcional) Vamos adicionar dois mtodos de negcio, para que o Candlestick possa nos dizer se ele do
tipo de alta, ou se de baixa:
public boolean isAlta() {
return this.abertura < this.fechamento;
}
A regra um tanto simples: dentre uma lista de negociaes, precisamos descobrir quais so os valores a
preencher na Candlestick:
Algumas dessas informaes so fceis de encontrar por que temos uma conveno no sistema: quando va-
mos criar a candle, a lista de negociaes j vem ordenada por tempo. Dessa forma, a abertura e o fechamento
Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - Resumo dirio das Negociaes - Pgina 24
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
J mnimo, mximo e volume precisam que todos os valores sejam verificados. Dessa forma, precisamos
passar por cada negociao da lista verificando se aquele valor menor do que todos os outros que j vi-
mos, maior que nosso mximo atual. Aproveitando esse processo de passar por cada negociao, j vamos
somando o volume de cada negociao.
O algoritmo, agora, est completamente especificado! Basta passarmos essas ideias para cdigo. Para isso,
lembremos, voc pode usar alguns atalhos que j vimos antes:
Falta apenas, antes de pr em prtica o que aprendemos, decidirmos onde vai esse cdigo de criao de
Candlestick. Pense bem a respeito disso: ser que uma negociao deveria saber resumir vrios de si em
uma candle? Ou ser que uma Candlestick deveria saber gerar um objeto do prprio tipo Candlestick a
partir de uma lista de negociaes.
Em ambos os cenrios, nossos modelos tm que ter informaes a mais que, na realidade, so responsabili-
dades que no cabem a eles!
Criaremos, ento, uma classe que: dado a matria-prima, nos constri uma candle. E uma classe com esse
comportamento, que recebem o necessrio para criar um objeto e encapsulam o algoritmo para tal criao,
costuma ser chamadas de Factory.
No nosso caso particular, essa uma fbrica que cria Candlesticks, ento, seu nome fica
CandlestickFactory.
Perceba que esse nome, apesar de ser um tal Design Pattern nada mais faz do que encapsular uma lgica um
pouco mais complexa, isto , apenas aplica boas prticas de orientao a objetos que voc j vem estudando
desde o FJ-11.
Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - Exerccios: fbrica de Candlestick - Pgina 25
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
}
}
2) Procuraremos os preos mximo e mnimo percorrendo todas as negociaes. Para isso usare-
mos variveis auxiliares maximo e minimo e, dentro do for, verificaremos se o preo da negociao
atual maior que o valor da varivel maximo. Se no for, veremos se ele menor que o minimo.
Calcularemos o volume somando o volume de cada negociao em uma varivel auxiliar chamada
volume. Poderemos pegar o preo de abertura atravs de negociacoes.get(0) e o de fechamento por
negociacoes.get(negociacoes.size() - 1).
Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - Exerccios: fbrica de Candlestick - Pgina 26
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
double volume = 0;
3) Vamos testar nosso cdigo, criando 4 negociaes e calculando o Candlestick, finalmente. Crie a classe
TestaCandlestickFactory no pacote br.com.caelum.argentum.testes
System.out.println(candle.getAbertura());
System.out.println(candle.getFechamento());
System.out.println(candle.getMinimo());
System.out.println(candle.getMaximo());
Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - Exerccios: fbrica de Candlestick - Pgina 27
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
System.out.println(candle.getVolume());
}
}
O mtodo asList da classe java.util.Arrays cria uma lista dada uma array. Mas no passamos ne-
nhuma array como argumento! Isso acontece porque esse mtodo aceita varargs, possibilitando que
invoquemos esse mtodo separando a array por vrgula. Algo parecido com um autoboxing de arrays.
Effective Java
Effective Java
1)
Item 10: Sempre reescreva o toString
Reescreva o toString da classe Candlestick. Como o toString da classe Calendar retorna uma
String bastante complexa, faa com que a data seja corretamente visualizada, usando para isso o
SimpleDateFormat. Procure sobre essa classe na API do Java.
Ao imprimir um candlestick, por exemplo, a sada deve ser algo como segue:
[Abertura 40.5, Fechamento 42.3, Mnima 39.8, Mxima 45.0,
Volume 145234.20, Data 12/07/2008]
Para reescrever um mtodo e tirar proveito do Eclipse, a maneira mais direta de dentro da classe
Candlestick, fora de qualquer mtodo, pressionar ctrl + espao.
Uma lista com todas as opes de mtodos que voc pode reescrever vai aparecer. Escolha o toString, e
ao pressionar enter o esqueleto da reescrita ser montado.
2) Um double segue uma regra bem definida em relao a contas e arredondamento, e para ser rpido e caber
em 64 bits, no tem preciso infinita. A classe BigDecimal pode oferecer recursos mais interessantes em
um ambiente onde as casas decimais so valiosas, como um sistema financeiro. Pesquise a respeito.
Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - Exerccios opcionais - Pgina 28
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
3) O construtor da classe Candlestick simplesmente muito grande. Poderamos usar uma factory, porm
continuaramos passando muitos argumentos para um determinado mtodo.
Quando construir um objeto complicado, ou confuso, costumamos usar o padro Builder para resolver
isso. Builder uma classe que ajuda voc a construir um determinado objeto em uma srie de passos,
independente da ordem.
Effective Java
builder.comAbertura(40.5);
builder.comFechamento(42.3);
builder.comMinimo(39.8);
builder.comMaximo(45.0);
builder.comVolume(145234.20);
builder.comData(new GregorianCalendar(2012, 8, 12, 0, 0, 0));
Os setters aqui possuem nomes mais curtos e expressivos. Mais ainda: utilizando o padro de projeto
fluent interface, podemos tornar o cdigo acima mais conciso, sem perder a legibilidade:
Candlestick candle = new CandleBuilder().comAbertura(40.5)
.comFechamento(42.3).comMinimo(39.8).comMaximo(45.0)
.comVolume(145234.20).comData(
new GregorianCalendar(2008, 8, 12, 0, 0, 0)).geraCandle();
Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - Exerccios opcionais - Pgina 29
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Escreva um cdigo com main que teste essa sua nova classe. Repare como o builder parece bastante com
a StringBuilder, que uma classe builder que ajuda a construir Strings atravs de fluent interface e
mtodos auxiliares.
Fluent interfaces so muito usadas no Hibernate, por exemplo. O jQuery, uma famosa biblioteca
de efeitos javascript, popularizou-se por causa de sua fluent interface. O JodaTime e o JMock so
dois excelentes exemplos.
http://martinfowler.com/bliki/FluentInterface.html
Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - Exerccios opcionais - Pgina 30
Captulo 3
Testes Automatizados
Apenas duas coisas so infinitas: o universo e a estupidez humana. E eu no tenho certeza do primeiro.
Albert Einstein
Pode parecer que o cdigo funciona, mas ele tem muitas falhas. Olhemos com mais cuidado.
System.out.println(candle.getAbertura());
System.out.println(candle.getFechamento());
System.out.println(candle.getMinimo());
System.out.println(candle.getMaximo());
System.out.println(candle.getVolume());
}
}
A sada deve indicar 40.5 como todos os valores, e 4050.0 como volume. Tudo parece bem?
2) Mais um teste: as aes menos negociadas podem ficar dias sem nenhuma operao acontecer. O que
nosso sistema gera nesse caso?
Vamos ao teste:
public class TestaCandlestickFactorySemNegociacoes {
System.out.println(candle.getAbertura());
System.out.println(candle.getFechamento());
System.out.println(candle.getMinimo());
System.out.println(candle.getMaximo());
System.out.println(candle.getVolume());
}
}
Rodando o que acontece? Voc acha essa sada satisfatria? Indica bem o problema?
Captulo 3 - Testes Automatizados - Exerccios: testando nosso modelo sem frameworks - Pgina 32
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Qual deciso vamos tomar? Podemos lanar nossa prpria exception, podemos retornar null ou ainda
podemos devolver um Candlestick que possui um significado especial. Devolver null deve ser sempre
a ltima opo.
Vamos retornar um Candlestick que possui um volume zero. Para corrigir o erro, vamos alterar o cdigo
do nosso CandlestickFactory.
Poderamos usar um if logo de cara para verificar se negociacoes.isEmpty(), porm podemos tentar
algo mais sutil, sem ter que criar vrios pontos de return.
Vamos ento iniciar os valores de minimo e maximo sem usar a lista, que pode estar vazia. Mas, para nosso
algoritmo funcionar, precisaramos iniciar o maximo com um valor bem pequeno, isto , menor do que o
da ao mais barata. Assim, quando percorrermos o for, qualquer valor que encontremos vai substituir
o maximo.
No caso do mximo, fcil pensar nesse valor! Qual o limite inferior para o preo de uma ao? Ser
que ele chega a ser negativo? A resposta no. Ningum vai vender uma ao por um preo negativo!
Portanto, se inicializarmos o mximo com zero, certeza que ele ser substituido na primeira iterao do
for.
Similarmente, queremos inicializar o minimo com um valor bem grande, maior do que o maior valor
possvel para o valor de uma ao. Esse um problema mais complexo, j que no existe um limitante
superior to claro para o preo de uma ao!
Qual valor colocaremos, ento? Quanto um nmero grande o suficiente? Podemos apelar para a limi-
tao do tipo que estamos usando! Se o preo um double, certamente no poderemos colocar nenhum
valor que estoure o tamanho do double. Felizmente, a classe Double conta com a constante que representa
o maior double vlido! o Double.MAX_VALUE.
Alm disso, devemos verificar se negociacoes est vazia na hora de calcular o preo de abertura e
fechamento. Altere novamente o mtodo:
Pronto! Rode o teste, deve vir tudo zero e nmeros estranhos para mximo e mnimo!
4) Ser que tudo est bem? Rode novamente os outros dois testes, o que acontece?
Incrvel! Consertamos um bug, mas adicionamos outro. A situao lhe parece familiar? Ns desenvolve-
dores vivemos com isso o tempo todo: tentando fugir dos velhos bugs que continuam a reaparecer!
Captulo 3 - Testes Automatizados - Exerccios: testando nosso modelo sem frameworks - Pgina 33
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
O teste com apenas uma negociao retorna 1.7976931348623157E308 como valor mnimo agora! Mas
deveria ser 40.5. Ainda bem que lembramos de rodar essa classe, e que percebemos que esse nmero est
diferente do que deveria ser.
5) (opcional) Ser que esse erro est ligado a ter apenas uma negociao? Vamos tentar com mais negocia-
es? Crie e rode um teste com as seguintes negociaes:
Negociacao negociacao1 = new Negociacao(40.5, 100, hoje);
Negociacao negociacao2 = new Negociacao(45.0, 100, hoje);
Negociacao negociacao3 = new Negociacao(49.8, 100, hoje);
Negociacao negociacao4 = new Negociacao(53.3, 100, hoje);
De qualquer maneira, crie um cdigo curto para testar cada uma das situaes, em um main apropriado.
1) Uma negociao da Petrobras a 30 reais, com uma quantidade negativa de negociaes vlida? E com
nmero zero de negociaes?
Em outras palavras, posso dar new em uma Negociacao com esses dados?
2) Uma negociao com data nula vlida? Posso dar new Negociacao(10, 5, null)? Deveria poder?
4) Um candle em que o preo de abertura igual ao preo de fechamento, um candle de alta ou de baixa?
O que o sistema diz? O que o sistema deveria dizer?
6) E se a ordem das negociaes passadas ao CandlestickFactory no estiver na ordem crescente das datas?
Devemos aceitar? No devemos?
7) E se essas Negociaes forem de dias diferentes que a data passada como argumento para a factory?
Captulo 3 - Testes Automatizados - Definindo melhor o sistema e descobrindo mais bugs - Pgina 34
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
em questo passando o mnimo possvel por outras classes ou dependncias do nosso sistema.
Unidade
Unidade a menor parte testvel de uma aplicao. Em uma linguagem de programao orien-
tada a objetos como o Java, a menor unidade um mtodo.
O termo correto para esses testes testes de unidade, porm o termo teste unitrio propagou-se
e o mais encontrado nas tradues.
Em testes de unidade, no estamos interessados no comportamento real das dependncias da classe, mas em
como a classe em questo se comporta diante das possveis respostas das dependncias, ou ento se a classe
modificou as dependncias da maneira esperada.
Para isso, quando criamos um teste de unidade, simulamos a execuo de mtodos da classe a ser testada.
Fazemos isso passando parmetros (no caso de ser necessrio) ao mtodo testado e definimos o resultado
que esperamos. Se o resultado for igual ao que definimos como esperado, o teste passa. Caso contrrio, falha.
Ateno
Muitas vezes, principalmente quando estamos iniciando no mundo dos testes, comum criarmos
alguns testes que testam muito mais do que o necessrio, mais do que apenas a unidade. Tais
testes se transformam em verdadeiros testes de integrao (esses sim so responsveis por testar
o sistemas como um todo).
3.5 JUnit
O JUnit (junit.org) um framework muito simples para facilitar a criao destes testes de unidade e em
especial sua execuo. Ele possui alguns mtodos que tornam seu cdigo de teste bem legvel e fcil de fazer
as asseres.
Uma assero uma afirmao: alguma invariante que em determinado ponto de execuo voc quer ga-
rantir que verdadeira. Se aquilo no for verdade, o teste deve indicar uma falha, a ser reportada para o
programador, indicando um possvel bug.
medida que voc mexe no seu cdigo, voc roda novamente toda aquela bateria de testes com um comando
apenas. Com isso voc ganha a confiana de que novos bugs no esto sendo introduzidos (ou reintrodu-
zidos) conforme voc cria novas funcionalidades e conserta antigos bugs. Mais fcil do que ocorre quando
fazemos os testes dentro do main, executando um por vez.
O JUnit possui integrao com todas as grandes IDEs, alm das ferramentas de build, que vamos conhecer
mais a frente. Vamos agora entender um pouco mais sobre anotaes e o import esttico, que vo facilitar
muito o nosso trabalho com o JUnit.
O JUnit uma biblioteca escrita por terceiros que vamos usar no nosso projeto. Precisamos das classes do
JUnit para escrever nossos testes. E, como sabemos, o formato de distribuio de bibliotecas Java o JAR,
muito similar a um ZIP com as classes daquela biblioteca.
Precisamos ento do JAR do JUnit no nosso projeto. Mas quando rodarmos nossa aplicao, como o Java vai
saber que deve incluir as classes daquele determinado JAR junto com nosso programa? (dependncia)
aqui que o Classpath entra histria: nele que definimos qual o caminho para buscar as classes que vamos
usar. Temos que indicar onde a JVM deve buscar as classes para compilar e rodar nossa aplicao.
E, nessa tela:
1) Java Build Path onde voc configura o classpath do seu projeto: lista de locais definidos que, por
padro, s vm com a mquina virtual configurada;
2) Opes para adicionar mais caminhos, Add JARs... adiciona Jars que estejam no seu projeto; Add
External JARs adiciona Jars que estejam em qualquer outro lugar da mquina, porm guardar uma
referncia para aquele caminho (ento seu projeto poder no funcionar corretamente quando colocado
em outro micro, mas existe como utilizar variveis para isso);
No caso do JUnit, por existir integrao direta com Eclipse, o processo ainda mais fcil, como veremos no
exerccio. Mas para todas as outras bibliotecas que formos usar, basta copiar o JAR e adicion-lo ao Build
Path. Vamos ver esse procedimento com detalhes quando usarmos as bibliotecas que trabalham com XML
e grficos em captulos posteriores.
3.6 Anotaes
Anotao a maneira de escrever metadados na prpria classe, isto , configuraes ou outras informaes
pertinentes a essa classe. Esse recurso foi introduzido no Java 5.0. Algumas anotaes podem ser mantidas
(retained) no .class, permitindo que possamos reaver essas informaes, se necessrio.
utilizada, por exemplo, para indicar que determinada classe deve ser processada por um framework de
uma certa maneira, evitando assim as clssicas configuraes atravs de centenas de linhas de XML.
Apesar dessa propriedade interessante, algumas anotaes servem apenas para indicar algo ao compilador.
@Override o exemplo disso. Caso voc use essa anotao em um mtodo que no foi reescrito, vai haver
um erro de compilao! A vantagem de us-la apenas para facilitar a legibilidade.
@Deprecated indica que um mtodo no deve ser mais utilizado por algum motivo e decidiram no retir-lo
da API para no quebrar programas que j funcionavam anteriormente.
@SurpressWarnings indica para o compilador que ele no deve dar warnings a respeito de determinado
problema, indicando que o programador sabe o que est fazendo. Um exemplo o warning que o compilador
do Eclipse d quando voc no usa determinada varivel. Voc vai ver que um dos quick fixes a sugesto
de usar o @SupressWarnings.
Anotaes podem receber parmetros. Existem muitas delas na API do java 5, mas realmente ainda mais
utilizada em frameworks, como o Hibernate 3, o EJB 3 e o JUnit4.
package br.com.caelum.argentum.modelo;
negociacao3, negociacao4);
Em vez de um main, criamos um mtodo com nome expressivo para descrever a situao que ele est testando.
Mas... como o JUnit saber que deve executar aquele mtodo? Para isso anotamos este mtodo com @Test,
que far com que o JUnit saiba no momento de execuo, por reflection, de que aquele mtodo deva ser
executado:
@Test
public void sequenciaSimplesDeNegociacoes() {
// ...
}
}
Pronto! Quando rodarmos essa classe como sendo um teste do JUnit, esse mtodo ser executado e a View
do JUnit no Eclipse mostrar se tudo ocorreu bem. Tudo ocorre bem quando o mtodo executado sem
lanar excees inesperadas e se todas as asseres passarem.
Uma assero uma verificao. Ela realizada atravs dos mtodos estticos da classe Assert, importada
do org.junit. Por exemplo, podemos verificar se o valor de abertura desse candle 40.5:
O primeiro argumento o que chamamos de expected, e ele representa o valor que esperamos para argumento
seguinte (chamado de actual). Se o valor real for diferente do esperado, o teste no passar e uma barrinha
vermelha ser mostrada, juntamente com uma mensagem que diz:
Double inexato
Logo na primeira discusso desse curso, conversamos sobre a inexatido do double ao trabalhar com arre-
dondamentos. Porm, diversas vezes, gostaramos de comparar o double esperado e o valor real, sem nos
preocupar com diferenas de arredondamento quando elas so muito pequenas.
O JUnit trata esse caso adicionando um terceiro argumento, que s necessrio quando comparamos valores
double ou float. Ele um delta que se aceita para o erro de comparao entre o valor esperado e o real.
Por exemplo, quando lidamos com dinheiro, o que nos importa so as duas primeiras casas decimais e,
portanto, no h problemas se o erro for na quinta casa decimal. Em softwares de engenharia, no entanto,
um erro na quarta casa decimal pode ser um grande problema e, portanto, o delta deve ser ainda menor.
Nosso cdigo final do teste, agora com as devidas asseres, ficar assim:
@Test
public void sequenciaSimplesDeNegociacoes() {
Calendar hoje = Calendar.getInstance();
Existem ainda outras anotaes principais e mtodos importantes da classe Assert, que conheceremos no
decorrer da construo do projeto.
Captulo 3 - Testes Automatizados - Exerccios: migrando os testes do main para JUnit - Pgina 39
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
nesse novo diretrio em que voc colocar todos seus testes de unidade.
2) Vamos criar um novo unit test em cima da classe CandlestickFactory. O Eclipse j ajuda bastante: com
o editor na CandlestickFactory, crie um novo (ctrl + N) JUnit Test Case.
Na janela seguinte, selecione o source folder como src/test/java. No esquea, tambm, de selecionar
JUnit4.
Captulo 3 - Testes Automatizados - Exerccios: migrando os testes do main para JUnit - Pgina 40
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
A anotao @Test indica que aquele mtodo deve ser executado na bateria de testes, e a classe Assert pos-
sui uma srie de mtodos estticos que realizam comparaes, e no caso de algum problema um exceo
lanada.
@Test
public void sequenciaSimplesDeNegociacoes() {
Captulo 3 - Testes Automatizados - Exerccios: migrando os testes do main para JUnit - Pgina 41
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
No se assuste! Houve a falha porque o nmero esperado do volume est errado no teste. Repare que
o Eclipse j associa a falha para a linha exata da assero e explica porque falhou:
Captulo 3 - Testes Automatizados - Exerccios: migrando os testes do main para JUnit - Pgina 42
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
O nmero correto mesmo 16760.0. Adicione esse zero na classe de teste e rode-o novamente:
comum digitarmos errado no teste e o teste falhar, por isso, importante sempre verificar a corretude
do teste, tambm!
3) Vamos adicionar outro mtodo de teste mesma classe CandlestickFactoryTest, dessa vez para testar
o mtodo no caso de no haver nenhuma negociao:
@Test
public void semNegociacoesGeraCandleComZeros() {
Calendar hoje = Calendar.getInstance();
Captulo 3 - Testes Automatizados - Exerccios: migrando os testes do main para JUnit - Pgina 43
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
4) E, agora, vamos para o que tem apenas uma negociao e estava falhando. Ainda na classe
CandlestickFactoryTest adicione o mtodo: (repare que cada classe de teste possui vrios mtodos
com vrios casos diferentes)
@Test
public void apenasUmaNegociacaoGeraCandleComValoresIguais() {
Calendar hoje = Calendar.getInstance();
Captulo 3 - Testes Automatizados - Exerccios: migrando os testes do main para JUnit - Pgina 44
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Como consertar?
A resposta para essa pergunta um grande e sonoro sim! Apesar de serem classes mais simples elas tambm
tm comportamentos especficos como:
1) as classes Negociacao e Candlestick devem ser imutveis, isto , no devemos ser capazes de alterar
nenhuma de suas informaes depois que o objeto criado;
3) se voc fez o opcional CandleBuilder, ele no deveria gerar a candle se os valores no tiverem sido preen-
chidos;
4) etc...
Por essa razo, ainda que sejam classes mais simples, elas merecem ter sua integridade testada - mesmo
porque so os objetos que representam nosso modelo de negcios, o corao do sistema que estamos desen-
volvendo.
Vamos criar um novo Unit Test para a classe Negociacao. O processo o mesmo que fizemos para o teste
da CandlestickFactory: abra a classe Negociacao no editor e faa Ctrl + N JUnit Test Case.
@Test
public void dataDaNegociacaoEhImutavel() {
// se criar um negocio no dia 15...
Calendar c = Calendar.getInstance();
c.set(Calendar.DAY_OF_MONTH, 15);
Negociacao n = new Negociacao(10, 5, c);
Voc pode rodar esse teste apenas, usando o atalho (alt + shift + X T) ou pode fazer melhor e o que mais
comum, rodar todos os testes de unidade de um projeto.
Basta selecionar o projeto na View Package Explorer e mandar rodar os testes: para essa ao, o nico
atalho possvel o alt + shift + X T.
Esse teste falha porque devolvemos um objeto mutvel atravs de um getter. Deveramos ter retornado
uma cpia desse objeto para nos assegurarmos que o original permanece intacto.
Effective Java
Basta alterar a classe Negociacao e utilizar o mtodo clone que todos os objetos tm (mas s quem
implementa Cloneable executar com xito):
public Calendar getData() {
return (Calendar) this.data.clone();
}
Sem clone, precisaramos fazer esse processo na mo. Com Calendar relativamente fcil:
public Calendar getData() {
Calendar copia = Calendar.getInstance();
copia.setTimeInMillis(this.data.getTimeInMillis());
return copia;
}
Com outras classes, em especial as que tem vrios objetos conectados, isso pode ser mais complicado.
Listas e arrays
Esse tambm um problema que ocorre muito com colees e arrays: se voc retorna uma List
que um atributo seu, qualquer um pode adicionar ou remover um elemento de l, causando
estrago nos seus atributos internos.
2) Podemos criar uma Negociacao com data nula? Por enquanto, podemos, mas no deveramos. Para que
outras partes do meu sistema no se surpreendam mais tarde, vamos impedir que a Negociacao seja criada
se sua data estiver nula, isto , vamos lanar uma exceo.
Mas qual exceo? Vale a pena criar uma nova exceo para isso?
Effective Java
Antes de fazer a modificao na classe, vamos preparar o teste. Mas o que queremos testar? Queremos
saber se nossa classe Negociacao no permite a criao do objeto e lana uma IllegalArgumentException
quando passamos null no construtor.
Ou seja, esperamos que uma exceo acontea! Para o teste passar, ele precisa dar a exceo (parece meio
contraditrio). fcil fazer isso com JUnit.
Rode os testes. Barrinha vermelha! J que ainda no verificamos o argumento na classe Negociacao e
ainda no lanamos a exceo:
Vamos alterar a classe Negociacao, para que ela lance a exceo no caso de data nula. No construtor,
adicione o seguinte if:
public Negociacao(double preco, int quantidade, Calendar data) {
if (data == null) {
throw new IllegalArgumentException(data nao pode ser nula);
}
this.preco = preco;
this.quantidade = quantidade;
this.data = data;
}
3) (opcional) Nosso teste para quando no h negociaes na CandlestickFactory est verificando apenas
se o volume zero. Ele tambm poderia verificar que os outros valores dessa candle so zero.
Corrija ele da mesma forma que resolvemos o problema para as variveis abertura e fechamento.
4) (opcional) Um Candlestick pode ter preo mximo menor que o preo mnimo? No deveria.
Crie um novo teste, o CandlestickTest, da maneira que fizemos com o Negociacao. boa prtica que
todos os testes da classe X se encontrem em XTest.
A ideia testar se o construtor de Candlestick faz as validaes necessrias. Lembre-se que o constru-
tor recebe como argumento Candlestick(abertura, fechamento, minimo, maximo, volume, data),
portanto queremos testar se algo assim gera uma exceo (e deveria gerar):
new Candlestick(10, 20, 20, 10, 10000, Calendar.getInstance());
5) (opcional) Um Candlestick pode ter data nula? Pode ter algum valor negativo?
Teste, verifique o que est errado, altere cdigo para que os testes passem! Pegue o ritmo, essa ser sua
rotina daqui para a frente.
import pacote.ClasseComMetodosEstaticos;
class UsandoMetodosEstaticos {
void metodo() {
ClasseComMetodosEstaticos.metodo1();
ClasseComMetodosEstaticos.metodo2();
}
}
Comea a ficar muito chato escrever, toda hora, o nome da classe. Para resolver esse problema, no Java 5.0
foi introduzido o static import, que importa mtodos e atributos estticos de qualquer classe. Usando essa
nova tcnica, voc pode importar os mtodos do exemplo anterior e us-los diretamente:
Apesar de voc ter importado todos os mtodos e atributos estticos da classe ClasseComMetodosEstaticos,
a classe em si no foi importada e, se voc tentasse dar new, por exemplo, ele no conseguiria encontr-la,
precisando de um import normal parte.
class TesteMatematico {
@Test
void doisMaisDois() {
assertEquals(4, 2 + 2);
}
}
Use os imports estticos dos mtodos de Assert nos testes de unidade que voc escreveu.
O teste deve falhar. Corrija-o criando booleans que indicam se cada mtodo setter foi invocado, ou utili-
zando alguma outra forma de verificao.
2) Se voc fez os opcionais do primeiro exerccio do captulo anterior (criao do projeto e dos modelos)
voc tem os mtodos isAlta e isBaixa na classe Candlestick. Contudo, temos um comportamento no
especificado nesses mtodos: e quando o preo de abertura for igual ao de fechamento?
Perguntando para nosso cliente, ele nos informou que, nesse caso, o candle deve ser considerado de alta.
3) O que mais pode ser testado? Testar viciante, e aumentar o nmero de testes do nosso sistema comea
a virar um hbito divertido e contagioso. Isso no ocorre de imediato, necessrio um tempo para se
apaixonar por testes.
Existem inmeros formatos para se trabalhar com diversas bolsas. Sem dvida XML um formato comu-
mente encontrado em diversas indstrias, inclusive na bolsa de valores.
Utilizaremos esse tal de XML. Para isso, precisamos conhec-lo mais a fundo, seus objetivos, e como
manipul-lo. Considere que vamos consumir um arquivo XML como o que segue:
<list>
<negociacao>
<preco>43.5</preco>
<quantidade>1000</quantidade>
<data>
<time>1222333777999</time>
</data>
</negociacao>
<negociacao>
<preco>44.1</preco>
<quantidade>700</quantidade>
<data>
<time>1222444777999</time>
</data>
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
</negociacao>
<negociacao>
<preco>42.3</preco>
<quantidade>1200</quantidade>
<data>
<time>1222333999777</time>
</data>
</negociacao>
</list>
Uma lista de negociaes! Cada negociao informa o preo, quantidade e uma data. Essa data composta
por um horrio dado no formato de Timestamp, e opcionalmente um Timezone.
http://www.w3.org/XML/
Exemplo de dados que so armazenados em XMLs e que no conhecemos to bem, o formato aberto de
grficos vetoriais, o SVG (usado pelo Corel Draw, Firefox, Inkscape, etc), e o Open Document Format (ODF),
formato usado pelo OpenOffice, e hoje em dia um padro ISO de extrema importncia. (na verdade o ODF
um ZIP que contm XMLs internamente).
A ideia era criar uma linguagem de marcao que fosse muito fcil de ser lida e gerada por softwares, e
pudesse ser integrada as outras linguagens. Entre seus princpios bsicos, definidos pelo W3C:
Simplicidade e Legibilidade
O XML uma excelente opo para documentos que precisam ter seus dados organizados com uma certa
hierarquia (uma rvore), com relao de pai-filho entre seus elementos. Esse tipo de arquivo dificilmente
organizado com CSVs ou properties. Como a prpria imagem do wikipedia nos trs e mostra o uso estrutu-
rado e encadeado de maneira hierrquica do XML:
Esses caracteres no devem ser usados como elemento, e devem ser escapados":
, use '
, use "
Voc pode, em Java, utilizar a classe String e as regex do pacote java.util.regex para criar um programa
que l um arquivo XML. Isso uma grande perda de tempo, visto que o Java, assim como quase toda e
qualquer linguagem existente, possui uma ou mais formas de ler um XML. O Java possui diversas, vamos ver
algumas delas, suas vantagens e suas desvantagens.
Neste processo de anlise tambm podemos ler o arquivo XML para procurar algum determinado elemento
e manipular seu contedo.
O parser l os dados XML como um fluxo ou uma sequncia de dados. Baseado no contedo lido, o parser
vai disparando eventos. o mesmo que dizer que o parser SAX funciona orientado a eventos.
Captulo 4 - Trabalhando com XML - Lendo XML com Java de maneira difcil, o SAX - Pgina 55
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
novo atributo;
Para tratar estes eventos, o programador deve passar um objeto listener ao parser que ser notificado auto-
maticamente pelo parser quando um desses eventos ocorrer. Comumente, este objeto chamado de Handler,
Observer, ou Listener e quem faz o trabalho necessrio de processamento do XML.
@Override
public void startDocument() throws SAXException {
@Override
public void startElement(String uri, String localName,
String name, Attributes attributes) throws SAXException {
// aqui voc avisado, por exemplo
// do inicio da tag <preco>
}
@Override
public void characters(char[] chars, int offset, int len)
throws SAXException {
// aqui voc seria avisado do inicio
// do contedo que fica entre as tags, como por exemplo 30
// de dentro de <preco>30</preco>
// para saber o que fazer com esses dados, voc precisa antes ter
// guardado em algum atributo qual era a negociao que estava
// sendo percorrida
}
@Override
public void endElement(String uri, String localName, String name)
throws SAXException {
// aviso de fechamento de tag
}
}
A classe DefaultHandler permite que voc reescreva mtodos que vo te notificar sobre quando um elemento
(tag) est sendo aberto, quando est sendo fechado, quando caracteres esto sendo parseados (contedo de
Captulo 4 - Trabalhando com XML - Lendo XML com Java de maneira difcil, o SAX - Pgina 56
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
uma tag), etc.. Voc o responsvel por saber em que posio do object model (rvore) est, e que atitude
deve ser tomada. A interface ContentHandler define mais alguns outros mtodos.
Originalmente o SAX foi escrito s para Java e vem de um projeto da comunidade (http://www.
saxproject.org) , mas existem outras implementaes em C++, Perl e Python.
O SAX est atualmente na verso 2 e faz parte do JAX-P (Java API for XML Processing).
O SAX somente sabe ler dados e nunca modific-los e s consegue ler para frente, nunca para trs. Quando
passou um determinado pedao do XML que j foi lido, no h mais como voltar. O parser SAX no guarda
a estrutura do documento XML na memria.
Tambm no h como fazer acesso aleatrio aos itens do documento XML, somente sequencial.
Por outro lado, como os dados vo sendo analisados e transformados (pelo Handler) na hora da leitura, o
SAX ocupa pouca memria, principalmente porque nunca vai conhecer o documento inteiro e sim somente
um pequeno pedao. Devido tambm a leitura sequencial, ele muito rpido comparado com os parsers que
analisam a rvore do documento XML completo.
Quando for necessrio ler um documento em partes ou s determinado pedao e apenas uma vez, o SAX
parser uma excelente opo.
StAX um projeto que foi desenvolvido pela empresa BEA e padronizado pela JSR-173. Ele
mais novo do que o SAX e foi criado para facilitar o trabalho com XML. StAX faz parte do Java
SE 6 e JAX-P.
Como o SAX, o StAX tambm l os dados de maneira sequencial. A diferena entre os dois a
forma como notificada a ocorrncia de um evento.
No SAX temos que registrar um Handler. o SAX que avisa o Handler e chama os mtodos dele.
Ele empurra os dados para o Handler e por isso ele um parser do tipo push, .
O StAX, ao contrrio, no precisa deste Handler. Podemos usar a API do StAX para chamar seus
mtodos, quando e onde preciso. O cliente decide, e no o parser. ele quem pega/tira os
dados do StAX e por isso um parser do tipo pull.
O site http://www.xmlpull.org fornece mais informaes sobre a tcnica de Pull Parsing, que
tem sido considerada por muitos como a forma mais eficiente de processar documentos xml.
A biblioteca XPP3 a implementao em Java mais conhecida deste conceito. usada por outras
bibliotecas de processamento de xml, como o CodeHaus XStream.
Captulo 4 - Trabalhando com XML - Lendo XML com Java de maneira difcil, o SAX - Pgina 57
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
4.4 XStream
O XStream uma alternativa perfeita para os casos de uso de XML em persistncia, transmisso de dados e
configurao. Sua facilidade de uso e performance elevada so os seus principais atrativos.
um projeto hospedado na Codehaus, um repositrio de cdigo open source focado em Java, que foi for-
mado por desenvolvedores de famosos projetos como o XDoclet, PicoContainer e Maven. O grupo patroci-
nado por empresas como a ThoughWorks, BEA e Atlassian. Entre os desenvolvedores do projeto, Guilherme
Silveira da Caelum est tambm presente.
http://xstream.codehaus.org
Como gerar o XML de uma negociao? Primeiramente devemos ter uma referncia para o objeto. Podemos
simplesmente cri-lo e popul-lo ou ento deixar que o Hibernate faa isso.
Com a referncia negociacao em mos, basta agora pedirmos ao XStream que gera o XML correspondente:
E o resultado :
<br.com.caelum.argentum.Negociacao>
<preco>42.3</preco>
<quantidade>100</quantidade>
<data>
<time>1220009639873</time>
<timezone>America/Sao_Paulo</timezone>
</data>
</br.com.caelum.argentum.Negociacao>
A classe XStream atua como faade de acesso para os principais recursos da biblioteca. O construtor da
classe XStream recebe como argumento um Driver, que a engine que vai gerar/consumir o XML. Aqui
voc pode definir se quer usar SAX, DOM, DOM4J dentre outros, e com isso o XStream ser mais rpido,
mais lento, usar mais ou menos memria, etc.
O default do XStream usar um driver chamado XPP3, desenvolvido na universidade de Indiana e conhecido
por ser extremamente rpido (leia mais no box de pull parsers). Para us-lo voc precisa de um outro JAR
no classpath do seu projeto.
O mtodo toXML retorna uma String. Isso pode gastar muita memria no caso de voc serializar uma lista
grande de objetos. Ainda existe um overload do toXML, que alm de um Object recebe um OutputStream
como argumento para voc poder gravar diretamente num arquivo, socket, etc.
Diferentemente de outros parsers do Java, o XStream serializa por default os objetos atravs de seus atributos
(sejam privados ou no), e no atravs de getters e setters.
Repare que o XStream gerou a tag raiz com o nome de br.com.caelum.argentum.Negociacao. Isso porque
no existe um conversor para ela, ento ele usa o prprio nome da classe e gera o XML recursivamente para
cada atributo no transiente daquela classe.
Porm, muitas vezes temos um esquema de XML j muito bem definido, ou simplesmente no queremos
gerar um XML com cara de java. Para isso podemos utilizar um alias. Vamos modificar nosso cdigo que
gera o XML:
Essa configurao tambm pode ser feita atravs da anotao @XStreamAlias("negociacao") em cima da
classe Negociacao.
Podemos agora fazer o processo inverso. Dado um XML que representa um bean da nossa classe Negociacao,
queremos popular esse bean. O cdigo novamente extremamente simples:
Obviamente no teremos um XML dentro de um cdigo Java. O exemplo aqui meramente ilustrativo (til
em um teste!). Os atributos no existentes ficaro como null no objeto, como o caso aqui do atributo data,
ausente no XML.
O XStream possui uma sobrecarga do mtodo fromXML que recebe um InputStream como argumento, outro
que recebe um Reader.
JAXB ou XStream?
A vantagem do JAXB ser uma especificao do Java, e a do XStream ser mais flexvel e permitir
trabalhar com classes imutveis.
@XStreamAlias
@XStreamAlias(negociacao)
public class Negociacao {
}
stream.autodetectAnnotations(true);
Ou ento, se precisarmos processar as anotaes de apenas uma nica classe, basta indic-la,
como abaixo:
stream.processAnnotations(Negociacao.class);
Note que trabalhar com as anotaes, portanto, no nos economiza linhas de cdigo. Sua prin-
cipal vantagem manter as configuraes centralizadas e, assim, se houver mais de uma parte
na sua aplicao responsvel por gerar XMLs de um mesmo modelo, no corremos o risco de ter
XMLs incompatveis.
2) Vamos pr o XStream no nosso projeto. V na pasta Caelum no seu Desktop e entre em 22. Localize o
arquivo do XStream:
Esse o mesmo arquivo que voc encontra para download no site do XStream, na verso minimal.
3) Copie o JAR do XStream 1.4 para a pasta lib/ do Argentum e, pelo Eclipse, entre na pasta lib e d refresh
(F5) nela.
Ento, selecione o JAR, clique com o boto direito e v em Build Path, Add to build path. A partir de
agora o Eclipse considerar as classes do XStream para esse nosso projeto.
4) Vamos, finalmente, implementar a leitura do XML, delegando o trabalho para o XStream. Criamos a
classe LeitorXML dentro do pacote br.com.caelum.argentum.reader:
package br.com.caelum.argentum.reader;
// imports...
5) Crie um teste de unidade LeitorXMLTest pelo Eclipse para testarmos a leitura do XML. Com o cursor na
classe LeitorXML, faa Ctrl + N e digite JUnit Test Case:
Para no ter de criar um arquivo XML no sistema de arquivos, podemos usar um truque interessante:
coloque o trecho do XML em uma String Java, e passe um ByteArrayInputStream, convertendo nossa
String para byte atravs do mtodo getBytes():
@Test
public void carregaXmlComUmaNegociacaoEmListaUnitaria() {
String xmlDeTeste = ...; // o XML vai aqui!
6) Um teste de nada serve se no tiver suas verificaes. Assim, no esquea de verificar valores esperados
como:
Zero negociaes;
8) (importante, conceitual) E o que falta agora? Testar nosso cdigo com um XML real?
muito comum sentirmos a vontade de fazer um teste maior": um teste que realmente abre um
InputStreamReader, passa o XML para o LeitorXML e depois chama a CandlestickFactory para que-
brar as negociaes em candles.
Esse teste seria um chamado teste de integrao - no de unidade. Se crissemos esse teste e ele falhasse,
seria muito mais difcil detectar o ponto de falha!
Pensar em sempre testar as menores unidades possveis nos fora a pensar em classes menos dependentes
entre si, isto , com baixo acoplamento. Por exemplo: poderamos ter criado um LeitorXML que interna-
mente chamasse a fbrica e devolvesse diretamente uma List<Candlestick>. Mas isso faria com que o
nosso teste do leitor de XML testasse muito mais que apenas a leitura de XML (j que estaria passando
pela CandlestickFactory).
Captulo 4 - Trabalhando com XML - Discusso em aula: Onde usar XML e o abuso do mesmo - Pgina 63
Captulo 5
Experincia sem teoria cegueira, mas teoria sem experincia mero jogo intelectual."
Immanuel Kant
Dessa forma, precisamos ainda quebrar a lista que contm todas as negociaes em partes menores, com
negociaes de um dia apenas, e usar o outro mtodo para gerar cada Candlestick. Essas, devem ser arma-
zenadas em uma nova lista para serem devolvidas.
...caso contrrio:
gera a candle;
O algoritmo no trivial e, ainda, ele depende de uma verificao que o Java no nos d prontamente: se
continua no mesmo dia. Isto , dado que eu sei qual a dataAtual, quero verificar se a negociao pertence a
esse mesmo dia.
Verificar uma negociao do mesmo dia que um Calendar qualquer exige algumas linhas de cdigo, mas
veja que, mesmo antes de implement-lo, j sabemos como o mtodo isMesmoDia dever se comportar em
diversas situaes:
Sempre que vamos comear a desenvolver uma lgica, intuitivamente, j pensamos em seu comportamento.
Fazer os testes automatizados para tais casos , portanto, apenas colocar nosso pensamento em forma de
cdigo. Mas faz-lo incrementalmente, mesmo antes de seguir com a implementao o princpio do que
chamamos de Test Driven Design (TDD).
Um dos principais benefcio dessa tcnica que, como os testes so escritos antes da implementao do
trecho a ser testado, o programador no influenciado pelo cdigo j feito - assim, ele tende a escrever testes
melhores, pensando no comportamento em vez da implementao.
Lembremos: os testes devem mostrar (e documentar) o comportamento do sistema, e no o que uma im-
plementao faz.
Alm disso, nota-se que TDD traz baixo acoplamento, o que timo j que classes muito acopladas so
difceis de testar. Como criaremos os testes antes, desenvolveremos classes menos acopladas, isto , menos
dependentes de outras muitas, separando melhor as responsabilidades.
O TDD tambm uma espcie de guia: como o teste escrito antes, nenhum cdigo do sistema escrito
por acharmos que vamos precisar dele. Em sistemas sem testes, comum encontrarmos centenas de linhas
que jamais sero invocadas, simplesmente porque o desenvolvedor achou que algum um dia precisaria
daquele determinado mtodo.
Imagine que voc j tenha um sistema com muitas classes e nenhum teste: provavelmente, para iniciar a
criao de testes, muitas refatoraes tero de ser feitas, mas como modificar seu sistema garantindo o funci-
onamento dele aps as mudanas quando no existem testes que garantam que seu sistema tenha o compor-
tamento desejado? Por isso, crie testes sempre e, de preferncia, antes da implementao da funcionalidade.
TDD uma disciplina difcil de se implantar, mas depois que voc pega o jeito e o hbito adquirido, pode-
mos ver claramente as diversas vantagens dessa tcnica.
1) Queremos ento, em nossa classe de factory, pegar uma srie de negociaes e transformar em uma lista
de candles. Para isso vamos precisar que uma negociao saiba identificar se do mesmo dia que a
dataAtual.
Para saber, conforme percorremos todas as negociaes, se a negociao atual ainda aconteceu na mesma
data que estamos procurando, vamos usar um mtodo na classe Negociacao que faz tal verificao.
Esse cdigo no vai compilar de imediato, j que no temos esse mtodo na nossa classe. No Eclipse,
aperte Ctrl + 1 em cima do erro e escolha Create method isMesmoDia.
E qual ser uma implementao interessante? Que tal simplificar usando o mtodo equals de Calendar?
Captulo 5 - Test Driven Design - TDD - Exerccios: Identificando negociaes do mesmo dia - Pgina 66
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
2) Nosso teste passou de primeira! Vamos tentar mais algum teste? Vamos testar datas iguais em horas
diferentes, crie o mtodo a seguir na classe NegociacaoTest:
@Test
public void comHorariosDiferentesEhNoMesmoDia() {
// usando GregorianCalendar(ano, mes, dia, hora, minuto)
Calendar manha = new GregorianCalendar(2011, 10, 20, 8, 30);
Calendar tarde = new GregorianCalendar(2011, 10, 20, 15, 30);
Lembre que um Calendar possui um timestamp, isso quer dizer que alm do dia, do ms e do ano, h
tambm informaes de hora, segundos etc. A implementao que compara os dias ser:
public boolean isMesmoDia(Calendar outraData) {
return
data.get(Calendar.DAY_OF_MONTH) == outraData.get(Calendar.DAY_OF_MONTH);
}
Altere o mtodo isMesmoDia na classe Negociacao e rode os testes anteriores. Passamos agora?
3) O prximo teste a implementarmos ser o que garante que para dia igual, mas ms diferente, a data no
a mesma. Quer dizer: no basta comparar o campo referente ao dia do ms, ainda necessrio que seja
o mesmo ms!
4) Finalmente, o ltimo teste a implementarmos ser o que garante que para dia e meses iguais, mas anos
diferentes, a data no a mesma. Siga o mesmo procedimento para desenvolver com TDD:
Captulo 5 - Test Driven Design - TDD - Exerccios: Identificando negociaes do mesmo dia - Pgina 67
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Feito esse processo, seu mtodo isMesmoDia na classe Negociacao deve ter ficado bem parecido com isso:
public boolean isMesmoDia(Calendar outraData) {
return
this.data.get(Calendar.DAY_OF_MONTH) == outraData.get(Calendar.DAY_OF_MONTH)
&& this.data.get(Calendar.MONTH) == outraData.get(Calendar.MONTH)
&& this.data.get(Calendar.YEAR) == outraData.get(Calendar.YEAR);
}
@Test
public void paraNegociacoesDeTresDiasDistintosGeraTresCandles() {
Calendar hoje = Calendar.getInstance();
Assert.assertEquals(3, candles.size());
Assert.assertEquals(40.5, candles.get(0).getAbertura(), 0.00001);
Assert.assertEquals(42.3, candles.get(0).getFechamento(), 0.00001);
Assert.assertEquals(48.8, candles.get(1).getAbertura(), 0.00001);
Assert.assertEquals(49.3, candles.get(1).getFechamento(), 0.00001);
Assert.assertEquals(51.8, candles.get(2).getAbertura(), 0.00001);
Assert.assertEquals(52.3, candles.get(2).getFechamento(), 0.00001);
}
A chamada ao mtodo constroiCandles no compila pois o mtodo no existe ainda. Ctrl + 1 e Create
method.
Criar a List<Candlestick>;
Quando achar uma negociao de um novo dia, cria um Candlestick novo e adiciona;
O cdigo talvez fique um pouco grande. Ainda bem que temos nosso teste!
public List<Candlestick> constroiCandles(List<Negociacao> todasNegociacoes) {
List<Candlestick> candles = new ArrayList<Candlestick>();
return candles;
}
Rode o teste!
Aqui temos diversas opes. Uma delas , caso alguma Negociacao venha em ordem diferente da cres-
cente, lanamos uma exception, a IllegalStateException.
2) Vamos criar um gerador automtico de arquivos para testes da bolsa. Ele vai gerar 30 dias de candle e
cada candle pode ser composto de 0 a 19 negociaes. Esses preos podem variar.
public class GeradorAleatorioDeXML {
public static void main(String[] args) throws IOException {
Calendar data = Calendar.getInstance();
Random random = new Random(123);
List<Negociacao> negociacoes = new ArrayList<Negociacao>();
Se voc olhar o resultado do XML, ver que, por usarmos o mesmo objeto Calendar em vrios lugares, o
XStream coloca referncias no prprio XML evitando a cpia do mesmo dado. Mas talvez isso no seja
to interessante na prtica, pois mais comum na hora de integrar sistemas, passar um XML simples com
todos os dados.
A opo XStream.NO_REFERENCES serve para indicar ao XStream que no queremos que ele crie referncias
a tags que j foram serializadas iguaizinhas. Voc pode passar esse argumento para o mtodo setMode do
XStream. Faa o teste sem e com essa opo para entender a diferena.
1) Faa com que uma lista de Negociacao seja ordenvel pela data das negociaes.
Ento poderemos, logo no incio do mtodo, ordenar todas as negociaes com Collections.sort e no
precisamos mais verificar se os negociaes esto vindo em ordem crescente!
Perceba que mudamos uma regra de negcio, ento teremos de refletir isso no nosso teste unitrio que
estava com expected=IllegalStateException.class no caso de vir em ordem errada. O resultado agora
com essa modificao tem de dar o mesmo que com as datas crescentes.
Nenhum homem uma ilha isolada; cada homem uma partcula do continente, uma parte da terra
John Donne
No mercado de bolsa de valores comum o uso de aplicaes que permitem aos seus usurios analisar o
mercado, e at mesmo comprar e vender aes em tempo real. Mas como possvel analisar o mercado se
no temos acesso aos dados da Bovespa?
A integrao e a comunicao com o sistema da Bovespa se faz necessria para que possamos receber dados
sempre atualizados. Geralmente essa comunicao se d pelo prprio protocolo da web, o HTTP, com o
formato difundido e j estudado XML. Essa integrao e comunicao entre aplicaes possui o nome de
Web Service.
Podemos testar essa URL facilmente dentro do navegador, basta copiar e colar na barra de endereo. Ao
executar, o navegador recebe como resposta o XML de negcios que j conhecemos, por exemplo:
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Na prpria API do Java temos classes que tornam possvel essa tarefa. Como o caso da classe URL que nos
permite referenciar um recurso na Web, seja ele um arquivo ou at mesmo um diretrio.
Conhecendo a URL falta agora que uma requisio HTTP seja feita para ela. Faremos isso atravs do m-
todo openConnection que nos devolve um URLConnection. Entretanto, como uma requisio HTTP se faz
necessria, usaremos uma subclasse de URLConnection que a HttpURLConnection.
Dessa conexo pediremos um InputStream que ser usado pelo nosso LeitorXML.
Dessa forma j temos em mos a lista de negociaes que era o nosso objetivo principal. Resta agora en-
capsularmos este cdigo em alguma classe, para que no seja necessrio repeti-lo toda vez que precisamos
receber os dados da negociao. Vamos implementar a classe ClienteWebService e nela deixar explcito qual
o caminho da aplicao que a conexo ser feita.
Por ltimo, e no menos importante, declararemos um mtodo que retorna uma lista de negociaes, justa-
mente o que usaremos no projeto.
Nossa classe ainda no compila, pois tanto o construtor de URL quanto os mtodos de HttpURLConnection
lanam excees que so do tipo IOException. Vamos tratar o erro e fechar a conexo que foi aberta pelo
mtodo getInputStream, em um bloco finally.
...
public List<Negociacao> getNegociacoes() {
try {
URL url = new URL(URL_WEBSERVICE);
connection = (HttpURLConnection)url.openConnection();
InputStream content = connection.getInputStream();
return new LeitorXML().carrega(content);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
connection.disconnect();
}
}
...
Dessa forma conseguimos nos comunicar com um Web Service e consumir os dados disponibilizados por
ele atravs de um XML. Esta uma prtica bastante utilizada pelo mercado e estudada com mais aprofunda-
mento no curso FJ-31 | Curso Java EE avanado e Web Services.
HttpClient
Existe uma biblioteca capaz de lidar com dados de uma forma simples e mais especfica do que
utilizar diretamente a API do Java. Para trabalhar com o protocolo HTTP h a biblioteca Http-
Client que faz parte do Apache Software Foundation:
http://hc.apache.org/httpcomponents-client-ga/index.html
Com ela ganhamos uma API que fornece toda funcionalidade do protocolo HTTP e podera-
mos us-la para chamar o Web Service. Segue um pequeno exemplo usando o HttpClient para
executar uma requisio do tipo GET:
Por definio um Web Service alguma lgica de negcio acessvel usando padres da Inter-
net. O mais comum usar HTTP como protocolo de comunicao e XML para o formato que
apresenta os dados - justamente o que praticaremos aqui. Mas nada impede o uso de outros
formatos.
Uma tentativa de especificar mais ainda o XML dos Web Services so os padres SOAP e WSDL.
Junto com o protocolo HTTP, eles definem a base para comunicao de vrios servios no
mundo de aplicaes Enterprise. O SOAP e WSDL tentam esconder toda comunicao e ge-
rao do XML, facilitando assim o uso para quem no conhece os padres Web. No treinamento
FJ-31 veremos os detalhes sobre publicao e a criao de clientes baseados no Web Services
SOAP/WSDL.
Outro formato bastante popular nos Web Services o JSON. JSON parecido com XML, mas
um pouco menos verboso e fcil de usar com JavaScript. JSON ganhou popularidade atravs das
requisies AJAX e conquistou o seu espao nos Web Services tambm. Alm de ser bastante
difundido no desenvolvimento mobile por ser mais leve no trfego via rede.
2) Agora vamos criar o mtodo getNegociacoes(), que retorna a nossa lista de negociaes:
public class ClienteWebService {
Captulo 6 - Acessando um Web Service - Exerccios: Nosso cliente Web Service - Pgina 77
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
connection = (HttpURLConnection)url.openConnection();
3) No podemos esquecer de colocar o try/catch para tratar possveis erros e logo em seguida fechar a
conexo:
public class ClienteWebService {
try {
URL url = new URL(URL_WEBSERVICE);
connection = (HttpURLConnection)url.openConnection();
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
connection.disconnect();
}
}
}
Captulo 6 - Acessando um Web Service - Discusso em aula: Como testar o cliente do web service? - Pgina 78
Captulo 7
Durante muitos anos, os usurios se habituaram com aplicaes Desktop. Este tipo de aplicao instalada
no computador local e acessa diretamente um banco de dados ou gerenciador de arquivos. As tecnologias
tpicas para criar uma aplicao Desktop so Delphi, VB (Visual Basic) ou, no mundo Java, Swing.
Para o desenvolvedor, a aplicao Desktop construda com uma srie de componentes que a plataforma de
desenvolvimento oferece para cada sistema operacional. Esses componentes ricos e muitas vezes sofisticados
esto associados a eventos ou procedimentos que executam lgicas de negcio.
Problemas de validao de dados so indicados na prpria tela sem que qualquer informao do formulrio
seja perdida. De uma forma natural, esses componentes lembram-se dos dados do usurio, inclusive entre
telas e aes diferentes.
Nesse tipo de desenvolvimento so utilizados diversos componentes ricos, como por exemplo, calendrios,
menus diversos ou componentes drag and drop (arrastar e soltar). Eles ficam associados a eventos, ou aes,
e guardam automaticamente seu estado, j que mantm os valores digitados pelo usurio.
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Note que, aqui, estamos chamando de cliente a aplicao que est rodando na mquina do usurio.
Para piorar, as regras de negcio rodam no computador do usurio. Isso faz com que seja muito mais difcil
depurar a aplicao, j que no costumamos ter acesso to fcil maquina onde a aplicao est instalada.
Em geral, enfrentamos problemas de manuteno e gerenciabilidade.
Para resolver problemas como esse, surgiram as aplicaes baseadas na web. Nessa abordagem h um ser-
vidor central onde a aplicao executada e processada e todos os usurios podem acess-la atravs de um
cliente simples e do protocolo HTTP.
Um navegador web, como Firefox ou Chrome, que far o papel da aplicao cliente, interpretando HTML,
CSS e JavaScript -- que so as tecnologias que ele entende.
Enquanto o usurio usa o sistema, o navegador envia requisies (requests) para o lado do servidor (server
side), que responde para o computador do cliente (client side). Em nenhum momento a aplicao est salva
no cliente: todas as regras da aplicao esto no lado do servidor. Por isso, essa abordagem tambm foi
chamada de cliente magro (thin client).
Isso facilita bastante a manuteno e a gerenciabilidade, pois temos um lugar central e acessvel onde a apli-
cao executada. Contudo, note que ser preciso conhecer HTML, CSS e JavaScript, para fazer a interface
com o usurio, e o protocolo HTTP para entender a comunicao pela web. E, mais importante ainda, no
h mais eventos, mas sim um modelo bem diferente orientado a requisies e respostas. Toda essa base
precisar ser conhecida pelo desenvolvedor.
Comparando as duas abordagens, podemos ver vantagens e desvantagens em ambas. No lado da aplicao
puramente Desktop, temos um estilo de desenvolvimento orientado a eventos, usando componentes ricos,
porm com problemas de manuteno e gerenciamento. Do outro lado, as aplicaes web so mais fceis
de gerenciar e manter, mas precisamos lidar com HTML, conhecer o protocolo HTTP e seguir o modelo
requisio/resposta.
Em vez de desenvolver puramente para desktop, uma tendncia mesclar os dois estilos, aproveitando as van-
tagens de cada um. Seria um desenvolvimento Desktop para a web, tanto central quanto com componentes
ricos, aproveitando o melhor dos dois mundos e abstraindo o protocolo de comunicao. Essa justamente
a ideia dos frameworks web baseados em componentes.
No mundo Java h algumas opes como JavaServer Faces (JSF), Apache Wicket, Vaadin, Tapestry ou GWT
da Google. Todos eles so frameworks web baseados em componentes.
Alm disso o estado dos componentes sempre guardado automaticamente (como veremos mais frente),
criando a caracterstica Stateful. Isso nos permite, por exemplo, criar formulrios de vrias pginas e navegar
nos vrios passos dele com o estado das telas sendo mantidos.
Separa as camadas
Outra caracterstica marcante na arquitetura do JSF a separao que fazemos entre as camadas de apresen-
tao e de aplicao. Pensando no modelo MVC, o JSF possui uma camada de visualizao bem separada do
conjunto de classes de modelo.
O JSF ainda tem a vantagem de ser uma especificao do Java EE, isto , todo servidor de aplicaes Java tem
que vir com uma implementao dela e h diversas outras disponveis.
A implementao mais famosa do JSF e tambm a implementao de referncia, a Oracle Mojarra dis-
ponvel em http://javaserverfaces.java.net/. Outra implementao famosa a MyFaces da Apache Software
Foundation em http://myfaces.apache.org/.
No h componentes sofisticados dentro da especificao e isso proposital: uma especificao tem que ser
estvel e as possibilidades das interfaces com o usurio crescem muito rapidamente. A especificao trata do
que fundamental, mas outros projetos suprem o que falta.
Para atender a demanda dos desenvolvedores por componentes mais sofisticados, h vrias extenses do
JSF que seguem o mesmo ciclo e modelo da especificao. Exemplos dessas bibliotecas so PrimeFaces,
RichFaces e IceFaces. Todas elas definem componentes JSF que vo muito alm da especificao.
Cada biblioteca oferece ShowCases na web para mostrar seus componentes e suas funcionalidades. Voc
pode ver o showcase do PrimeFaces no endereo http://www.primefaces.org.
Na sua demo online, podemos ver uma lista de componentes disponveis, como inputs, painis, botes diver-
sos, menus, grficos e componentes drag & drop, que vo muito alm das especificaes, ainda mantendo a
facilidade de uso:
Para a definio da interface do projeto Argentum usaremos Oracle Mojarra com PrimeFaces, uma combi-
nao muito comum no mercado.
Preparao do ambiente
Nossa aplicao Argentum precisa de uma interface web. Para isso vamos preparar uma aplicao web comum
que roda dentro de um Servlet Container. Qualquer implementao de servlet container seria vlida e, no
curso, usaremos o Apache Tomcat 7. Uma outra boa opo seria o Jetty.
O JSF segue o padro arquitetural MVC (Model-View-Controller) e faz o papel do Controller da aplicao. Para
comear a us-lo, preciso configurar a servlet do JSF no web.xml da aplicao. Esse Servlet responsvel
por receber as requisies e deleg-las ao JSF. Para configur-lo basta adicionar as seguintes configuraes
no web.xml:
<servlet>
<servletname>FacesServlet</servletname>
<servletclass>javax.faces.webapp.FacesServlet</servletclass>
<loadonstartup>1</loadonstartup>
</servlet>
<servletmapping>
<servletname>FacesServlet</servletname>
<urlpattern>*.xhtml</urlpattern>
</servletmapping>
Ao usar o Eclipse com suporte a JSF 2 essa configurao no web.xml j feita automaticamente durante a
criao de um projeto.
Alm disso, h um segundo XML que o arquivo de configurao relacionado com o mundo JSF, o
faces-config.xml.
Como o JSF na verso dois encoraja o uso de anotaes em vez de configuraes no XML, este arquivo torna-
se pouco usado. Ele era muito mais importante na primeira verso do JSF. Neste treinamento, deixaremos
ele vazio:
<facesconfig
xmlns=http://java.sun.com/xml/ns/javaee
xmlns:xsi=http://www.w3.org/2001/XMLSchemainstance
xsi:schemaLocation=http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/webfacesconfig_2_0.xsd
version=2.0>
</facesconfig>
Agora j temos as informaes necessrias para criar nosso primeiro projeto utilizando JSF.
Captulo 7 - Introduo ao JSF e Primefaces - Exerccios: Instalando o Tomcat e criando o projeto - Pgina 86
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
d) Na tela que abre, marque o checkbox com JavaServer Faces 2.0 e clique d ok:
Captulo 7 - Introduo ao JSF e Primefaces - Exerccios: Instalando o Tomcat e criando o projeto - Pgina 87
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
e) De volta tela de criao do projeto, clique em Next. Nessa tela, faremos como no incio do curso: re-
moveremos a source folder padro (src) e adicione as source folders src/main/java e src/test/java.
f) D Next mais duas vezes at chegar tela de JSF Capabilities. Nessa tela, escolha a opo Disable
Library Configuration para indicarmos para o Eclipse que ns mesmos copiaremos os JARs do JSF.
Ainda nessa tela, na parte URL Mapping Patterns, remova o mapeamento /faces/* e adicione um novo
mapeamento como *.xhtml
Captulo 7 - Introduo ao JSF e Primefaces - Exerccios: Instalando o Tomcat e criando o projeto - Pgina 88
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
3) O prximo passo configurar o Tomcat no Eclipse, para que possamos control-lo mais facilmente.
a) Dentro do Eclipse, abra a view Servers. Para isso, pressione ctrl + 3, digite Servers e escolha a view. Ela
ser aberta na parte inferior do seu Eclipse.
b) Dentro da aba Servers clique com o boto direito do mouse e escolha New -> Server. Se no quiser
usar o mouse, voc pode fazer ctrl+3 New server.
c) Dentro da Janela New Server escolha Apache Tomcat v7.0 Server e clique em Next.
Captulo 7 - Introduo ao JSF e Primefaces - Exerccios: Instalando o Tomcat e criando o projeto - Pgina 89
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
d) O prximo passo dizermos ao Eclipse em qual diretrio instalamos o Tomcat. Clique no boto
Browse... e escolha a pasta na qual voc descompactou o Tomcat.
e) Clique em Next e, na prxima tela, selecione o projeto fj22-argentum-web no box Available (da es-
querda), pressione o boto Add > (mover para o box Configured da direita) e depois Finish.
Captulo 7 - Introduo ao JSF e Primefaces - Exerccios: Instalando o Tomcat e criando o projeto - Pgina 90
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
f) Clique em Finish.
4) Por fim, precisamos importar do projeto anterior as classes como Negociacao ou Candlestick. J o te-
mos pronto na pasta /caelum/cursos/22/, com o nome de modelo-argentum.zip. Precisamos apenas
import-lo:
Para import-lo, use ctrl + 3 Archive File e escolha a opo Import (Archive file).
Note que, com esse import, trouxemos tambm os jars da implementao Mojarra do JSF e do Pri-
mefaces, que usaremos daqui pra frente.
Captulo 7 - Introduo ao JSF e Primefaces - Exerccios: Instalando o Tomcat e criando o projeto - Pgina 91
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Para casa...
Se voc est fazendo esse exerccio em casa, certifique-se que seu projeto anterior est funcio-
nando corretamente e simplesmente copie os pacotes dele para o novo.
Alm disso, no zip da aula ainda h os jars do JSF e do PrimeFaces, que usaremos a seguir. Nesta
verso da apostila estamos usando as verses 2.x.x e 3.5.x, respectivamente. Links para o down-
load:
JSF: https://javaserverfaces.java.net/download.html
Primefaces: http://primefaces.org/downloads.html
5) Nossas classes de teste (src/test/java) ainda apresentam problemas relacionados ao JUnit. Falta adicion-lo
ao Build Path.
Abra a classe CandlestickFactoryTest e d ctrl + 1 na anotao @Test. Escolha a opo Add JUnit 4 library
to the build path.
6) Finalmente, para evitar confuses mais para a frente, feche o projeto que fizemos nos outros dias de curso.
Clique com o boto direito no fj22-argentum-base e escolha a opo Close project
Vale relembrar uma diferena fundamental entre as duas formas de desenvolvimento para a web. A aborda-
gem action based, como no SpringMVC e no VRaptor, focam seu funcionamento nas classes que contm as
lgicas. A view meramente uma camada de apresentao do que foi processado no modelo.
Enquanto isso, o pensamento component based adotado pelo JSF leva a view como a pea mais importante
-- a partir das necessidades apontadas pelos componentes da view que o modelo chamado e populado
com dados.
As tags que representam os componentes do JSF esto em duas taglibs principais (bibliotecas de tags): a core
e a html.
A taglib html contm os componentes necessrios para montarmos nossa tela gerando o HTML adequado.
J a core possui diversos componentes no visuais, como tratadores de eventos ou validadores. Por ora,
usaremos apenas os componentes da h:html
<html xmlns=http://www.w3.org/1999/xhtml
xmlns:h=http://java.sun.com/jsf/html>
</html>
Como todo arquivo HTML, todo o cabealho deve estar dentro da tag head e o que ser renderizado no
navegador deve ficar dentro da tag body. Uma pgina padro para ns seria algo como:
<html ...>
<head>
<! cabealho aqui >
</head>
<body>
<! informaes a serem mostradas >
</body>
</html>
Quando estamos lidando com o JSF, no entanto, precisamos nos lembrar de utilizar preferencialmente as
tags do prprio framework, j que, medida que utilizarmos componentes mais avanados, o JSF preci-
sar gerenciar os prprios body e head para, por exemplo, adicionar CSS e javascript que um componente
requisitar.
Assim, usando JSF preferiremos utilizar as tags estruturais do HTML que vm da taglib http://java.sun.com/
jsf/html, nosso html vai ficar mais parecido com esse:
<html ...>
<h:head>
<! cabealho aqui >
</h:head>
<h:body>
<! informaes a serem mostradas >
</h:body>
</html>
<h:head>
<title>Argentum Web</title>
</h:head>
<h:body>
<h:outputText value =Ol JSF! />
</h:body>
</html>
Captulo 7 - Introduo ao JSF e Primefaces - Interagindo com o modelo: Managed Beans - Pgina 94
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Exemplos dessas interaes, no caso do h:outputText: mostrar informaes vindas de um banco de dados,
informaes do sistema, horrio de acesso, etc.
Para mostrar tais informaes, precisaremos executar um cdigo Java e certamente no faremos isso na
camada de visualizao: esse cdigo ficar separado da view, em uma classe de modelo. Essas classes de
modelo que interagem com os componentes do JSF so os Managed Beans.
Estes, so apenas classezinhas simples que com as quais o JSF consegue interagir atravs do acesso a seus
mtodos. Nada mais so do que POJOs anotados com @ManagedBean.
POJO um termo criado por Martin Fowler, Rebecca Parsons e Josh Mackenzie que serve para
definir um objeto simples. Segundo eles, o termo foi criado pois ningum usaria objetos simples
nos seus projetos pois no existia um nome extravagante para ele.
Se quisermos, por exemplo, mostrar quando foi o acesso do usurio a essa pgina, podemos criar a seguinte
classe:
@ManagedBean
public class OlaMundoBean {
E, bem semelhantemente forma padro nas JSPs vistas no treinamento de Java para a Web, acessaremos o
getter atravs da Expression Language. Existe apenas uma pequena diferena: para chamar os mtodos no
JSF, em vez do cifro ($), usaremos a cerquilha (#).
Ao fazer colocar o cdigo acima, estamos dizendo que h uma classe gerenciada pelo JSF chamada OlaMun-
doBean que tem um mtodo getHorario -- e que o retorno desse mtodo ser mostrado na pgina. uma
forma extremamente simples e elegante de ligar a view a mtodos do model.
A boa notcia que no JSF no ser muito diferente! Se para mostrar dados na pgina usamos a tag
h:outputText, para trazer dados do usurio para dentro da aplicao, usaremos a tag h:inputText. Ela
far a ligao entre o atributo do seu bean e o valor digitado no campo.
Note que a ideia a mesma de antes: como o JSF precisar interagir com os dados desse componente, no
podemos usar a tag HTML que faria o mesmo trabalho. Em vez disso, usaremos a taglib de HTML provida
pelo prprio JSF, indicando como a informao digitada ser guardada no bean.
Apenas com esse cdigo, j podemos ver o texto Digite seu nome e o campo de texto onde o usurio digitar.
Sabemos, no entanto, que no faz sentido ter apenas um campo de texto! preciso ter tambm um boto
para o usurio confirmar que acabou de digitar o nome e um formulrio para agrupar todas essas tags.
Esse um pequeno ponto de divergncia entre o HTML puro e o JSF. Em um simples formulrio HTML,
configuramos a action dele na prpria tag form e o papel do boto apenas o de mandar executar a ao j
configurada.
Para formulrios extremamente simples, isso o bastante. Mas quando queremos colocar dois botes com
aes diferentes dentro de um mesmo formulrio, temos que recorrer a um JavaScript que far a chamada
correta.
Como dito antes, no entanto, o JSF tem a proposta de abstrair todo o protocolo HTTP, o JavaScript e o CSS.
Para ter uma estrutura em que o formulrio marcado apenas como um agregador de campos e cada um
dos botes internos pode ter funes diferentes, a estratgia do JSF foi a de deixar seu form como uma tag
simples e adicionar a configurao da ao ao prprio boto.
<h:form>
<h:outputLabel for=nome value=Digite seu nome:/>
<h:inputText id=nome value=#{olaMundoBean.nome}/>
<h:commandButton value=Ok action=#{olaMundoBean.digaOi}/>
</h:form>
Quando o usurio clica no boto Ok, o JSF chama o setter do atributo nome do OlaMundoBean e, logo em
seguida, chama o mtodo digaOi. Repare que esta ordem importante: o mtodo provavelmente depender
dos dados inseridos pelo usurio.
Note, tambm, que teremos um novo mtodo no managed bean chamado digaOi. Os botes sempre esto
atrelados a mtodos porque, na maior parte dos casos, realmente queremos executar alguma ao alm da
chamada do setter. Essa ao pode ser a de disparar um processo interno, salvar no banco ou qualquer outra
necessidade.
No entanto, muitas vezes no gostaramos de mostrar um campo enquanto ele no estiver pre-
enchido e, felizmente, o JSF tem uma forma bastante simples de s mostrar um h:outputText
na tela apenas se a informao estiver preenchida! Basta usar o atributo rendered:
Implemente nosso primeiro cdigo JSF com apenas uma sada de texto:
<h:body>
<h:outputText value=Ola Mundo />
</h:body>
</html>
3) Verifique o cdigo fonte gerado pela pgina. Repare que ele no nada mais que simples HTML. Para
isso, na maior parte dos navegadores, use ctrl + U.
Repare no uso das tags <h:head>, <h:body> e <h:outputText>: elas no aparecem no html gerado! Sua
funo apenas indicar para o JSF como gerar o cdigo HTML necessrio para o exemplo funcionar.
4) Alm de usar mensagens fixas, poderamos fazer com que a mensagem seja devolvida de uma classe
responsvel por prover objetos para uma view: um dos chamados ManagedBeans. Vamos comear criando
essa classe contendo apenas a mensagem inicial.
Crie uma classe chamada OlaMundoBean, com apenas o atributo mensagem j inicializada, seu getter e no
esquea de anotar a classe com @ManagedBean
@ManagedBean
public class OlaMundoBean {
5) Alteremos o arquivo xhtml, ento, para que ele use a mensagem Quem voc? que escrevemos hard-coded
na classe OlaMundoBean. Usaremos a Expression Language especfica do JSF para isso, que capaz de pegar
informaes de qualquer classe configurada como um ManagedBean.
Ateno! No esquea da tag h:form em volta do formulrio. Lembre-se que, sem ela, os botes no
funcionam.
...
<h:body>
<h:form>
<h:outputText value=#{olaMundoBean.mensagem} /><br />
<h:inputText value=#{olaMundoBean.nome} />
<h:commandButton action=#{olaMundoBean.nomeFoiDigitado}
value=Ok/>
</h:form>
</h:body>
7) Essa alterao, no entanto, no suficiente. Se voc rodar o servidor agora, notar que a pgina, que
antes funcionava, agora lana uma ServletException informando que Property nome not found on type
br.com.caelum.argentum.bean.OlaMundoBean.
Isto , falta adicionarmos o atributo nome e seu getter pgina, como fizemos com a mensagem, no outro
exerccio. Adicione classe OlaMundoBean o atributo e seu getter.
@ManagedBean
public class OlaMundoBean {
...
private String nome;
8) Agora sim podemos ver a mensagem, o campo de texto e o boto. Contudo, ao apertar o boto, levamos
uma javax.el.PropertyNotFoundException informando que nome um atributo no altervel.
Faltou adicionarmos o setter do atributo OlaMundoBean, para que o JSF possa preench-lo! Alm disso,
o boto chamar o mtodo nomeFoiDigitado, que tambm no existe ainda.
Complete a classe com o setter faltante e o mtodo nomeFoiDigitado, reinicie o servidor e teste!
@ManagedBean
public class OlaMundoBean {
// ...tudo o que j existia aqui
9) (Opcional) Para entender melhor o ciclo de execuo de cada chamada ao JSF, adicione
System.out.println("nome do mtodo") a cada um dos mtodos da sua aplicao e veja a ordem das
chamadas pelo console do Eclipse.
At poderamos usar a tabela que vem na taglib padro do JSF, mas ela bastante limitada e no tem pr-
definies de estilo. Isto , usando a taglib padro, teremos sim uma tabela no HTML, mas ela ser mostrada
da forma mais feia e simples possvel.
J falamos, contudo, que a proposta do JSF abstrair toda a complexidade relativa web -- e isso inclui CSS,
formataes, JavaScript e tudo o mais. Ento, em apoio s tags bsicas, algumas bibliotecas mais sofisticadas
surgiram. As mais conhecidas delas so PrimeFaces, RichFaces e IceFaces.
Taglibs como essas oferecem um visual mais bacana j pr-pronto e, tambm, diversas outras facilidades. Por
exemplo, uma tabela que utilize as tags do Primefaces j vem com um estilo bonito, possibilidade de colocar
cabealhos nas colunas e at recursos mais avanados como paginao dos registros.
O componente responsvel por produzir uma tabela baseada em um modelo se chama dataTable. Ele fun-
ciona de forma bem semelhante ao for do Java 5 ou o forEach da JSTL: itera em uma lista de elementos
atribuindo cada item na varivel definida.
<html xmlns=http://www.w3.org/1999/xhtml
xmlns:h=http://java.sun.com/jsf/html
xmlns:p=http://primefaces.org/ui>
<h:head>
<title>Argentum</title>
</h:head>
<h:body>
<p:dataTable var=negociacao value=#{argentumBean.negociacoes}>
</p:dataTable>
</h:body>
</html>
O cdigo acima chamar o mtodo getNegociacoes da classe ArgentumBean e iterar pela lista devolvida
atribuindo o objeto varivel negociacao. Ento, para cada coluna que quisermos mostrar, ser necessrio
apenas manipular a negociao do momento.
E, intuitivamente o bastante, cada coluna da tabela ser representada pela tag p:column. Para mostrar o
valor, voc pode usar a tag que j vimos antes, o h:outputText. Note que as tags do Primefaces se integram
perfeitamente com as bsicas do JSF.
Falta ainda implementar a classe que cuidar de devolver essa lista de negociaes. O cdigo acima sugere
que tenhamos uma classe chamada ArgentumBean, gerenciada pelo JSF, que tenha um getter de negociaes
que pode, por exemplo, trazer essa lista direto do ClienteWebService que fizemos anteriormente:
@ManagedBean
public class ArgentumBean {
Da forma acima, o exemplo j funciona e voc ver a lista na pgina. No entanto, nesse exemplo simples o JSF
chamar o mtodo getNegociacoes duas vezes durante uma mesma requisio. Isso no seria um problema
se ele fosse um getter padro, que devolve uma referncia local, mas note como nosso getNegociacoes vai
buscar a lista diretamente no web service. Isso faz com que, para construir uma simples pgina, tenhamos
que esperar a resposta do servio... duas vezes!
No JSF, o comportamento padro diz que um objeto do ManagedBean dura por uma requisio. Em outras
palavras, o escopo padro dos beans no JSF o de requisio. Isso significa que um novo ArgentumBean
ser criado a cada vez que um usurio chamar a pgina da listagem. E, para cada chamada a essa pgina,
precisamos buscar a lista de negociaes no servio apenas uma vez. A resposta para esse problema, ento,
bastante simples e apareceu logo no incio do aprendizado do Java orientado a objetos.
Basta colocar a chamada do web service naquele bloco de cdigo que chamado apenas na criao do objeto,
isto , no construtor. Ao armazenar a listagem em um atributo, o getter de negociaes passa a simplesmente
devolver a referncia, evitando as mltiplas chamadas a cada requisio.
@ManagedBean
public class ArgentumBean {
public ArgentumBean() {
ClienteWebService cliente = new ClienteWebService();
this.negociacoes = cliente.getNegociacoes();
}
Juntando as informaes dessa seo, j conseguimos montar a listagem de negociaes com os dados vindos
do web service. E o processo ser muito frequentemente o mesmo para as diversas outras telas: criamos a
pgina usando as tags do Primefaces em complemento s bsicas do JSF, implementamos a classe que cuidar
da lgica por trs da tela e a anotamos com @ManagedBean.
A forma clssica de resolver esse problema seria atravs de um getter que traria a data formatada por um
SimpleDateFormat. Mas, assim como a JSTL vista no curso de Java para a Web, o JSF tambm tem uma tag
Captulo 7 - Introduo ao JSF e Primefaces - Formatao de Data com JSF - Pgina 102
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
para formatar valores, nmeros e, claro, datas. Essas tags e muitas outras, so parte da biblioteca fundamental
de tags lgicas do JSF e, para us-las, ser necessrio importar tal taglib.
Assim como as bibliotecas de tags de HTML e do Primefaces, para utilizar essas ser necessrio declar-las
no namespace da sua pgina.
Da, podemos facilmente mudar a forma padro de exibio usando o componente de formatao
f:convertDateTime que define um pattern para a data. importante lembrar que, internamente, o
f:convertDateTime acaba fazendo uma chamada ao SimpleDateFormat e, assim, s podemos formatar ob-
jetos do tipo java.util.Date com ele. Por essa razo, chamaremos o mtodo getTime que devolve a repre-
sentao em Date do Calendar em questo. Mais uma vez podemos omitir a palavra get com expression
language. Segue a tabela completa:
<html xmlns=http://www.w3.org/1999/xhtml
xmlns:f=http://java.sun.com/jsf/core
xmlns:h=http://java.sun.com/jsf/html
xmlns:p=http://primefaces.org/ui>
<h:body>
<p:dataTable var=negociacao value=#{argentumBean.negociacoes}>
O Eclipse vai gerar um arquivo com um pouco de informaes a mais, mas ainda muito parecido com o
seguinte, onde mudamos o title:
<html xmlns=http://www.w3.org/1999/xhtml>
<head>
<title>Argentum Web</title>
</head>
Captulo 7 - Introduo ao JSF e Primefaces - Exerccios: p:dataTable para listar as Negociaes do Web Service - Pgina 103
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
<body>
</body>
</html>
2) Como vamos usar o JSF nesse arquivo e j temos at mesmo o JAR primefaces-3.x.jar adicionado ao pro-
jeto (veja em WebContent/WEB-INF/lib) basta declarar os namespaces das taglibs do JSF e do Primefaces,
que usaremos no exerccio.
Alm disso, para que os componentes consigam incluir seu CSS nossa pgina, altere as tags head e body
de forma a usar suas verses gerenciadas pelo JSF:
<html xmlns=http://www.w3.org/1999/xhtml
xmlns:h=http://java.sun.com/jsf/html
xmlns:f=http://java.sun.com/jsf/core
xmlns:p=http://primefaces.org/ui>
<h:head>
<title>Argentum Web</title>
</h:head>
<h:body>
</h:body>
</html>
3) Agora, dentro do h:body, vamos comear a montar nossa tabela de negociaes. O componente que
usaremos para isso o p:datatable, do Primefaces. Ele precisar da lista de negociaes e, assim como
um forEach, uma varivel para que cada coluna seja preenchida.
<p:dataTable var=negociacao value=#{argentumBean.negociacoes}>
</p:dataTable>
4) Esse cdigo acima diz que o componente dataTable do Primefaces chamar o mtodo getNegociacoes()
da classe ArgentumBean e, para cada linha da tabela, disponibilizar a negociao da vez na varivel
negociacao.
O problema que o managed bean ArgentumBean ainda no existe e, claro, nem o mtodo
getNegociacoes() dela. E como cada vez que a pgina index.xhtml for requisitada ela far algumas
chamadas ao getNegociacoes, faremos a chamada ao webservice no construtor e, a cada chamada ao
getter, apenas devolveremos a referncia mesma lista.
a) Crie a classe ArgentumBean com ctrl + N Class, no pacote br.com.caelum.argentum.bean e anote ela
com @ManagedBean.
@ManagedBean
public class ArgentumBean {
Captulo 7 - Introduo ao JSF e Primefaces - Exerccios: p:dataTable para listar as Negociaes do Web Service - Pgina 104
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
b) Adicione o construtor que faa a chamada ao webservice atravs do ClienteWebservice, guarde a lista
em um atributo e crie o getter que o componente chamar.
@ManagedBean
public class ArgentumBean {
public ArgentumBean() {
negociacoes = new ClienteWebService().getNegociacoes();
}
5) Agora, nossa pgina j no d erro, mas nada mostrado na tela, quando a acessamos. Falta indicarmos
quais colunas queremos na nossa tabela -- no nosso caso: preo, quantidade, volume e data. Em cada
coluna, adicionaremos um ttulo e cada uma delas tambm mostrar o valor de texto.
Para criar a coluna com o ttulo, usaremos o componente p:column e, como j fizemos antes, para mostrar
o valor necessrio, usaremos a h:outputText.
<p:dataTable var=negociacao value=#{argentumBean.negociacoes}>
<p:column headerText=Preo>
<h:outputText value=#{negociacao.preco}/>
</p:column>
<p:column headerText=Quantidade>
<h:outputText value=#{negociacao.quantidade}/>
</p:column>
<p:column headerText=Volume>
<h:outputText value=#{negociacao.volume}/>
</p:column>
<p:column headerText=Data>
<h:outputText value=#{negociacao.data}/>
</p:column>
</p:dataTable>
Captulo 7 - Introduo ao JSF e Primefaces - Exerccios: p:dataTable para listar as Negociaes do Web Service - Pgina 105
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
7) As informaes de preo, quantidade e volume esto legveis, mas a data das negociaes est mostrando
um monte de informaes que no nos interessam. Na verdades, o que precisamos na coluna data de
informaes de dia, ms, ano e, no mximo, horrio de cada movimentao.
Adicione a tag f:convertDateTime coluna da data. Essa tag modificar o comportamento da
h:outputText para mostr-lo formatado de acordo com o padro passado. Note que a tag h:outputText
passar a ser fechada depois da formatao da data:
...
<p:column headerText=Data>
<h:outputText value=#{negociacao.data.time}>
<f:convertDateTime pattern=dd/MM/yyyy/>
</h:outputText>
</p:column>
...
Muitos dados
Por exemplo, quando um programa traz uma quantidade muito grande de dados, isso pode causar uma
pgina pesada demais para o usurio que provavelmente nem olhar com ateno todos esses dados.
Uma soluo clssica para resultados demais mostr-los aos poucos, apenas conforme o usurio indicar
que quer ver os prximos resultados. Estamos, claro, falando da paginao dos resultados e o componente
de tabelas do Primefaces j a disponibiliza!
Para habilitar a paginao automtica, basta adicionar o atributo paginator="true" sua p:dataTable e
definir a quantidade de linhas por pgina pelo atributo rows. A definio da tabela de negociaes para
paginao de 15 em 15 resultados ficar assim:
Captulo 7 - Introduo ao JSF e Primefaces - Para saber mais: paginao e ordenao - Pgina 106
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Essa pequena mudana j traz uma visualizao mais legal para o usurio, mas estamos causando um pro-
blema silencioso no servidor. A cada vez que voc chama uma pgina de resultados, a cada requisio, o
ArgentumBean recriado e perdemos a lista anterior. Assim, na criao da nova instncia de ArgentumBean,
seu construtor chamado e acessamos novamente o webservice.
Como recebemos a lista completa do webservice, podamos aproveitar a mesma lista para todas as pginas
de resultado e, felizmente, isso tambm bastante simples.
O comportamento padro de um ManagedBean durar apenas uma requisio. Em outras palavras, o escopo
padro de um ManagedBean de request. Com apenas uma anotao podemos alterar essa durao. Os trs
principais escopos do JSF so:
RequestScoped: o escopo padro. A cada requisio um novo objeto do bean ser criado;
ViewScoped: escopo da pgina. Enquanto o usurio estiver na mesma pgina, o bean mantido. Ele
s recriado quando acontece uma navegao em s, isto , um boto abre uma pgina diferente ou
ainda quando acessamos novamente a pgina atual.
SessionScoped: escopo de sesso. Enquanto a sesso com o servidor no expirar, o mesmo objeto do
ArgentumBean atender o mesmo cliente. Esse escopo bastante usado, por exemplo, para manter o
usurio logado em aplicaes.
No nosso caso, o escopo da pgina resolve plenamente o problema: enquanto o usurio no recarregar a
pgina usaremos a mesma listagem. Para utiliz-lo, basta adicionar ao bean a anotao @ViewScoped. No
exemplo do Argentum:
@ManagedBean
@ViewScoped
public class ArgentumBean {
...
Sempre que um ManagedBean possuir o escopo maior que o escopo de requisio, ele dever implementar
a interface Serializable:
@ManagedBean
@ViewScoped
public class ArgentumBean implementes Serializable {
...
Captulo 7 - Introduo ao JSF e Primefaces - Para saber mais: paginao e ordenao - Pgina 107
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Outra situao clssica que aparece quando lidamos com diversos dados precisarmos v-los de diferentes
formas em situaes diversas.
Considere um sistema que apresenta uma tabela de contatos. Se quisermos encontrar um contato especfico
nela, melhor que ela esteja ordenada pelo nome. Mas caso precisemos pegar os contatos de todas as pessoas
de uma regio, melhor que a tabela esteja ordenada, por exemplo, pelo DDD.
Essa ideia de ordenao extremamente til e muito presente em aplicaes. Como tal, essa funcionali-
dade tambm est disponvel para tabelas do Primefaces. Apenas, como podemos tornar diversar colunas
ordenveis, essa configurao fica na tag da coluna.
Para tornar uma coluna ordenvel, preciso adicionar um simples atributo sortBy tag h:column corres-
pondente. Esse atributo torna o cabealho dessa coluna em um elemento clicvel e, quando clicarmos nele,
chamar a ordenao.
Contudo, exatamente pela presena de elementos clicveis, ser necessrio colocar a tabela dentro de uma
estrutura que comporte botes em HTML: um formulrio. E, como quem configurar o que cada clique vai
disparar o JSF, ser necessrio usar o formulrio da taglib de HTML dele. Resumidamente, precisamos
colocar a tabela inteira dentro do componente h:form.
Se quisssemos tornar ordenveis as colunas da tabela de negociaes, o resultado final seria algo como:
<h:form id=listaNegociacao>
<p:dataTable var=negociacao value=#{argentumBean.negociacoes}>
Se permitirmos ordenar por qualquer coluna do modelo Negociacao, teremos um resultado bem atraente:
Captulo 7 - Introduo ao JSF e Primefaces - Para saber mais: paginao e ordenao - Pgina 108
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Note que no foi necessrio adicionar cdigo algum classe ArgentumBean! Note tambm que at possvel
usar ambas as funcionalidades na mesma tabela. E essas so apenas algumas das muitas facilidades que o
p:dataTable oferece. Vale a pena verificar o showcase e documentao no site do Primefaces.
2) Para evitar chamar o webservice a cada vez que pedimos os prximos resultados paginados, adicione a
anotao @ViewScoped classe ArgentumBean:
@ManagedBean
@ViewScoped
public class ArgentumBean {
...
}
3) Como estamos utilizando um escopo maior do que o escopo de requisio, nosso ManagedBean precisa
implementar a interface Serializable. Adicione a implementao da interface Serializable classe
ArgentumBean:
@ManagedBean
@ViewScoped
Captulo 7 - Introduo ao JSF e Primefaces - Exerccio opcional: adicione paginao e ordenao tabela - Pgina 109
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
4) Tambm ser necessrio implementar a interface Serializable na classe Negociacao, pois ela utilizada
pela classe ArgentumBean:
public class Negociacao implements Serializable {
...
}
5) Deixe as colunas ordenveis, use o atributo sortBy em cada atributo. Por exemplo, para a coluna que
mostra o preo da negociao:
<p:column sortBy=#{negociacao.preco} headerText=Preo >
<h:outputText value=#{negociacao.preco} />
</p:column>
Repare que usamos a expression language #{negociacao.preco} do JSF dentro do sortBy para definir o
valor a ordenar.
6) Como estamos permitindo a ordenao das colunas da nossa tabela, temos que colocar nossa
p:dataTable dentro de um h:form:
<h:form id=listaNegociacao>
<p:dataTable var=negociacao value=#{argentumBean.negociacoes}>
Captulo 7 - Introduo ao JSF e Primefaces - Exerccio opcional: adicione paginao e ordenao tabela - Pgina 110
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
importante saber que diferente da tag form no HTML, o h:form sempre envia uma requisio
HTTP do tipo POST. Ele nem nos d a possibilidade de escolher usar requisies GET.
Isso ocorre porque o JSF tenta abstrair o mundo HTTP e assim fica mais perto do desenvolvi-
mento Desktop tradicional. Ele esconde do desenvolvedor o fato de que uma URL est sendo
chamada. Em vez disso, para o desenvolvedor, como se botes efetivamente chamassem mto-
dos ou eventos dentro de um Managed Bean.
A deciso automtica pelo POST foi a forma encontrada para abstrair o HTTP.
Captulo 7 - Introduo ao JSF e Primefaces - Exerccio opcional: adicione paginao e ordenao tabela - Pgina 111
Captulo 8
A estrela da manh, Doji, da figura abaixo, um exemplo de figura sempre muito buscada pelos analistas:
Ela indica um padro de reverso. Dizem que quando o preo de abertura e fechamento praticamente igual
(a estrela), essa uma forte indicao de que o mercado se inverta, isto , se estava em uma grande baixa,
tender a subir e, se estava em uma grande alta, tender a cair.
Baseada nessas ideias, surgiu a Anlise Tcnica Grafista: uma escola econmica que tem como objetivo
avaliar o melhor momento para compra e venda de aes atravs da anlise histrica e comportamental do
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
ativo na bolsa.
Essa forma de anlise dos dados gerados sobre dados das negociaes (preo, volume, etc), usa grficos na
busca de padres e faz anlise de tendncias para tentar prever o comportamento futuro de uma ao.
A anlise tcnica surgiu no incio do sculo 20, com o trabalho de Charles Dow e Edward Jones. Eles criaram
a empresa Dow Jones & Company e foram os primeiros a inventarem ndices para tentar prever o comporta-
mento do mercado de aes. O primeiro ndice era simplesmente uma mdia ponderada de 11 ativos famosos
da poca, que deu origem ao que hoje conhecido como Dow-Jones.
A busca de padres nos candlesticks uma arte. Atravs de critrios subjetivos e formao de figuras, ana-
listas podem determinar, com algum grau de acerto, como o mercado se comportar dali para a frente.
comum, na mesma visualizao, termos uma combinao de grficos, indicadores e at dos candles:
Diversos livros so publicados sobre o assunto e os principais homebrokers fornecem softwares que traam
esses indicadores e muitos outros. Alm disso, voc encontra uma lista com os indicadores mais usados e
como calcul-los em: http://stockcharts.com/school/doku.php?id=chart_school:technical_indicators
Vamos ver as duas primeiras, a mdia mvel simples e a mdia mvel ponderada.
A mdia mvel simples calcula a mdia aritmtica de algum dos valores das candlesticks do papel para um
determinado intervalo de tempo -- em geral, o valor de fechamento. Basta pegar todos os valores, somar e
dividir pelo nmero de dias.
A figura a seguir mostra duas mdias mveis simples: uma calculando a mdia dos ltimos 50 dias e outra
dos ltimos 200 dias. O grfico do valor das aes da antiga Sun Microsystems em 2001.
Repare que a mdia mvel mais curta, a de 50 dias, responde mais rpido aos movimentos atuais da ao,
mas pode gerar sinais pouco relevantes a mdio prazo.
Usualmente, estamos interessados na mdia mvel dos ltimos N dias e queremos definir esse dia inicial. Por
exemplo, para os dados de fechamento abaixo:
DIA FECHAMENTO
dia 1: 31
dia 2: 32
dia 3: 33
dia 4: 34
dia 5: 33
dia 6: 35
dia 7: 34
dia 8: 33
Vamos fazer as contas para que o indicador calcule a mdia para os 3 dias anteriores ao dia que estamos
interessados. Por exemplo: se pegamos o dia 6, a mdia mvel simples para os ltimos 3 dias a soma do
dia 4 ao dia 6: (34 + 33 + 35) / 3 = 34. A mdia mvel do dia 3 para os ltimos 3 dias 2: (31 + 32 + 33) / 3. E
assim por diante.
O grfico anterior das mdias mveis da Sun pega, para cada dia do grfico, a mdia dos 50 dias anteriores.
Outra mdia mvel muito famosa a ponderada. Ela tambm leva em conta os ltimos N dias a partir da data
a ser calculada. Mas, em vez de uma mdia aritmtica simples, faz-se uma mdia ponderada onde damos
mais peso para o valor mais recente e vamos diminuindo o peso dos valores conforme movemos para valores
mais antigos.
DIA FECHAMENTO
dia 1: 11
dia 2: 12
dia 3: 14
dia 4: 18
dia 5: 15
dia 6: 13
dia 7: 12
dia 8: 16
Vamos calcular a mdia mvel para os ltimos 3 dias, onde hoje tem peso 3, ontem tem peso 2 e anteontem
tem peso 1. Se calcularmos a mdia mvel ponderada para o dia 6 temos: (13*3 + 15*2 + 18*1) / 6 = 14.50.
A mdia ponderada nos d uma viso melhor do que est acontecendo no momento com a cotao da minha
ao, mostrando com menos importncia os resultados atrasados, portanto menos relevantes para minhas
decises de compra e venda atuais. Essa mdia, contudo, no to eficiente quando estudamos uma srie a
longo prazo.
Para encapsular a lista de candles e aproximar a nomenclatura do cdigo utilizada pelo cliente no dia a
dia, vamos criar a classe SerieTemporal no pacote br.com.caelum.argentum.modelo:
public class SerieTemporal {
a ser calculada e a SerieTemporal que prover os candles. Ento, o mtodo devolver a mdia simples
dos fechamentos dos dois dias anteriores e o atual.
A ideia passarmos para o mtodo calcula a SerieTemporal e o dia para o qual queremos calcular a mdia
mvel simples. Por exemplo, se passarmos que queremos a mdia do dia 6 da srie, ele deve calcular a
mdia dos valores de fechamento dos dias 6, 5 e 4 (j que nosso intervalo de 3 dias).
Como essa uma lgica um pouco mais complexa, comearemos essa implementao pelos testes.
3) Seguindo a ideia do TDD, faremos o teste antes mesmo de implementar a lgica da mdia. Assim como
voc j vem fazendo, use o ctrl + N -> JUnit Test Case para criar a classe de teste MediaMovelSimplesTest
na source folder src/test/java, pacote br.com.caelum.argentum.indicadores.
Ento, crie um teste para verificar que a mdia calculada corretamente para a sequncia de fechamentos
1, 2, 3, 4, 3, 4, 5, 4, 3.
Note que, para fazer tal teste, ser necessrio criar uma srie temporal com candles cujo fechamento
tenha tais valores. Criaremos uma outra classe para auxiliar nesses testes logo em seguida. Por hora, no
se preocupe com o erro de compilao da 5a. linha do cdigo abaixo:
1 public class MediaMovelSimplesTest {
2
3 @Test
4 public void sequenciaSimplesDeCandles() throws Exception {
5 SerieTemporal serie =
6 GeradorDeSerie.criaSerie(1, 2, 3, 4, 3, 4, 5, 4, 3);
7 MediaMovelSimples mms = new MediaMovelSimples();
8
4) Ainda necessrio fazer esse cdigo compilar! Note que, pelo que escrevemos, queremos chamar um
mtodo esttico na classe GeradorDeSerie que receber diversos valores e devolver a srie com Candles
respectivas.
Deixe que o Eclipse o ajude a criar essa classe: use o ctrl + 1 e deixe que ele crie a classe para voc
e, ento, adicione a ela o mtodo criaSerie, usando o recurso de varargs do Java para receber diversos
doubles.
Varargs
A notao double... valores (com os trs pontinhos mesmo!) que usaremos no mtodo a
seguir indicao do uso de varargs. Esse recurso est presente desde o Java 5 e permite que
chamemos o mtodo passando de zero a quantos doubles quisermos! Dentro do mtodo, esses
argumentos sero interpretados como um array.
Varargs vieram para oferecer uma sintaxe mais amigvel nesses casos. Antigamente, quando
queramos passar um nmero varivel de parmetros de um mesmo tipo para um mtodo, era
necessrio construir um array com esses parmetros e pass-lo como parmetro.
Agora que ele compila, rode a classe de teste. Ele falha, j que a implementao padro simplesmente
devolve zero!
5) Volte classe principal MediaMovelSimples e implemente agora a lgica de negcio do mtodo calcula,
que j existe. O mtodo deve ficar parecido com o que segue:
Repare que iniciamos o for com posicao e iteramos com i--, retrocedendo nas posies enquanto elas
forem maiores que os trs dias de intervalo. Isso significa que estamos calculando a mdia mvel apenas
dos ltimos 3 dias.
Mais para frente, existe um exerccio opcional para parametrizar esse valor.
6) Crie a classe MediaMovelPonderada anloga a MediaMovelSimples. Essa classe d peso 3 para o dia atual,
peso 2 para o dia anterior e o peso 1 para o dia antes desse. O cdigo interno muito parecido com o da
mdia mvel simples, s precisamos multiplicar sempre pela quantidade de dias passados.
Repare que o peso comea valendo 3, o tamanho do nosso intervalo, para o dia atual e vai reduzindo
conforme nos afastamos do dia atual, demonstrando a maior importncia dos valores mais recentes.
A diviso por 6 no final a soma dos pesos para o intervalo de 3 dias: (3 + 2 + 1 = 6).
@Test
public void sequenciaSimplesDeCandles() {
SerieTemporal serie =
GeradorDeSerie.criaSerie(1, 2, 3, 4, 5, 6);
MediaMovelPonderada mmp = new MediaMovelPonderada();
8) (opcional) Crie um teste de unidade em uma nova classe SerieTemporalTest, que verifique se essa classe
pode receber uma lista nula. O que no deveria poder.
Aproveite o momento para pensar quais outros testes poderiam ser feitos para essa classe.
8.5 Refatorao
"Refatorao uma tcnica controlada para reestruturar um trecho de cdigo existente, alterando sua estrutura
interna sem modificar seu comportamento externo. Consiste em uma srie de pequenas transformaes que
preservam o comportamento inicial. Cada transformao (chamada de refatorao) reflete em uma pequena
mudana, mas uma sequncia de transformaes pode produzir uma significante reestruturao. Como cada
refatorao pequena, menos provvel que se introduza um erro. Alm disso, o sistema continua em pleno
funcionamento depois de cada pequena refatorao, reduzindo as chances do sistema ser seriamente danificado
durante a reestruturao. -- Martin Fowler
Em outras palavras, refatorao o processo de modificar um trecho de cdigo j escrito, executando peque-
nos passos (baby-steps) sem modificar o comportamento do sistema. uma tcnica utilizada para melhorar
a clareza do cdigo, facilitando a leitura ou melhorando o design do sistema.
Note que para garantir que erros no sero introduzidos nas refatoraes, bem como para ter certeza de
que o sistema continua se comportando da mesma maneira que antes, a presena de testes fundamental.
Com eles, qualquer erro introduzido ser imediatamente apontado, facilitando a correo a cada passo da
refatorao imediatamente.
Algumas das refatoraes mais recorrentes ganharam nomes que identificam sua utilidade (veremos algumas
nas prximas sees). Alm disso, Martin Fowler escreveu o livro Refactoring: Improving the Design of
Existing Code, onde descreve em detalhes as principais.
Algumas so to corriqueiras, que o prprio Eclipse inclui um menu com diversas refatoraes que ele
Seja no Package Explorer ou na classe aberta no editor, coloque o cursor sobre o nome da classe e use
o atalho alt + shift + R, que renomeia. Esse atalho funciona para classes e tambm para mtodos,
variveis, etc.
2) No mtodo calcula da classe MediaMovelSimples, temos uma varivel do tipo Candle que s serve para
que peguemos o fechamento desse objeto. Podemos, ento, deixar esse mtodo uma linha menor fazendo
o inline dessa varivel!
Na linha 4 do mtodo abaixo, coloque o cursor na varivel c e use o alt + shift + I. (Alternativamente,
use ctrl + 1 Inline local variable)
1 public double calcula(int posicao, SerieTemporal serie) {
2 double soma = 0.0;
3 for (int i = posicao; i > posicao 3; i) {
4 Candle c = serie.getCandle(i);
5 soma += c.getFechamento();
6 }
7 return soma / 3;
8 }
No meio desse cdigo, contudo, h um pequeno bloco de cdigo que se repete duas vezes, dentro e fora
do for:
Candle candleDoDia = constroiCandleParaData(dataAtual, negociacoesDoDia);
candles.add(candleDoDia);
Se encontramos cdigos iguais pelo nosso cdigo, as boas prticas de orientao a objetos nos dizem para
isolar ento essa parte repetida em um novo mtodo que, alm de poder ser chamado vrias vezes, ainda
tem um nome que ajuda a compreender o algoritmo final.
Repare como a IDE resolve os parmetros e ainda substitui as chamadas ao cdigo repetido pela chamada
ao novo mtodo.
// ...
for (Negociacao negociacao : negociacoes) {
volume += negociacao.getVolume();
Uma forma de deixar o cdigo mais limpo e evitar chamadas desnecessrias seria extrair para uma varivel
local.
Para isso, usaremos a refatorao Extract Local Variable atravs do Eclipse. Selecione a primeira chamada
para negociacao.getPreco() e pressione alt + shift + L.
Um box vai aparecer perguntando o nome da varivel que ser criada, mantenha o nome aconselhado
pelo Eclipse e pressione OK.
// ...
for (Negociacao negociacao : negociacoes) {
volume += negociacao.getVolume();
5) (Opcional) Aproveite e mude os nomes das outras classes que usam a palavra Candlestick: a Factory e
os Testes.
Refatoraes disponveis
Para quem est comeando com a usar o Eclipse, a quantidade de atalhos pode assustar. Note,
contudo, que os atalhos de refatorao comeam sempre com alt + shift!
Para ajudar um pouco, comece memorizando apenas o atalho que mostra as refatoraes dispo-
nveis dado o trecho de cdigo selecionado: alt + shift + T.
H, contudo, refatoraes bem mais complexas que afetam diversas classes e podem mudar o design da
aplicao. Algumas refatoraes ainda mais complexas chegam a modificar at a arquitetura do sistema! Mas,
quanto mais complexa a mudana para chegar ao resultado final, mais importante quebrar essa refatorao
em pedaos pequenos e rodar os testes a cada passo.
Nos prximos captulos faremos refatoraes que flexibilizam nosso sistema e tornam muito mais fcil tra-
balhar com os indicadores tcnicos que vimos mais cedo.
etc...
Captulo 8 - Refatorao: os Indicadores da bolsa - Discusso em aula: quando refatorar? - Pgina 125
Captulo 9
Grficos comprovadamente ajudam no entendimento mais abrangente dos dados e so mais fceis de analisar
do que nmeros dentro de uma tabela. simples reconhecer padres de imagens, por exemplo na anlise
tcnica de valores da bolsa.
Exemplos de grficos
O Primefaces j possui diversos componentes para grficos: possvel utiliz-lo para desenhar grficos de
linha, de barra, de pizza, de rea, grficos para atualizao dinmica e at para Candles, entre outros. Tambm
possvel exportar e animar grficos.
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Nosso projeto est configurado e j podemos decidir qual grfico utilizar. Para facilitar a deciso e ao mesmo
tempo ver as possibilidades e tipos de grficos disponveis, o showcase do Primefaces nos ajudar muito:
http://www.primefaces.org/showcase/index.xhtml
Nele encontramos o resultado final e tambm o cdigo utilizado para a renderizao. Vamos programar
usando o componente p:chart que deve mostrar os valores de abertura ou de fechamento da SerieTemporal.
Captulo 9 - Grficos interativos com Primefaces - Grficos com o Primefaces - Pgina 127
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Podemos ver que o componente recebe os dados (model) atravs da Expression Language que chama o Ma-
naged Bean #{chartView.lineModel2}.
9.3 Documentao
A documentao do Primefaces est disponvel na internet e na forma de um guia do usurio em PDF. Ela
far parte do dia-a-dia do desenvolvedor, que a consultar sempre que necessrio:
http://www.primefaces.org/documentation.html
No showcase tambm h um exemplo do uso do Managed Bean, porm para maiores informaes funda-
mental ter acesso ao Javadoc e documentao da biblioteca para saber quais classes, atributos e mtodos
utilizar.
JSF e CSS
O Primefaces ajuda o desenvolvedor atravs de seu suporte a temas, mas nem sempre ele sufi-
ciente, inclusive quando h uma equipe de designers responsvel em determinar a apresentao
da aplicao.
Apesar de trabalharmos com componentes, no final o que enviado para o cliente puro HTML.
Assim, quem conhece CSS pode aplicar estilos para sobrescrever o visual da aplicao.
A Caelum oferece o curso Desenvolvimento Web com HTML, CSS e JavaScript, para aque-
les que querem aprender a criar interfaces Web com experincia rica do usurio, estruturao
correta e otimizaes SEO.
Da forma como est, no entanto, no h nada a ser mostrado no grfico. Ainda falta indicarmos para o
componente que os dados, o modelo do grfico, ser disponibilizado por nosso ManagedBean. Em outras
palavras, faltou indicarmos que o model desse grfico ser produzido em argentumBean.modeloGrafico.
Apenas, ser necessrio informar ao componente quais so os dados a serem plotados no grfico em questo.
Esses dados representam o modelo do grfico e devem ser disponibilizados como o model para o p:chart
em um objeto do tipo org.primefaces.model.chart.ChartModel.
Essa a classe principal do modelo e h classes filhas especializadas dela como LineChartModel,
PieChartModel ou BubbleChartModel. No JavaDoc podemos ver todas as filhas da ChartModel e ainda no
showcase possvel ver o ManagedBean responsvel por cada modelo de grfico. Assim, saberemos qual delas
devemos usar de acordo com o grfico escolhido:
Javadoc: http://www.primefaces.org/docs/api/5.1/org/primefaces/model/chart/ChartModel.html
No nosso projeto, utilizaremos o LineChartModel, j que queremos plotar pontos em um grfico de linha.
Um LineChartModel recebe uma ou mais ChartSeries e cada ChartSeries representa uma linha no grfico
do componente p:chart. Uma ChartSeries, por sua vez, contm todos os pontos de uma linha do grfico,
isto , os valores X e Y que sero ligados pela linha do grfico.
Captulo 9 - Grficos interativos com Primefaces - Definio do modelo do grfico - Pgina 129
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Uma ChartSeries recebe no construtor a legenda da linha que ela representa (label) e, atravs do mtodo set,
passamos os valores de cada ponto nos eixos horizontal e vertical, respectivamente. No exemplo acima, os va-
lores colocados so fixos, mas na nossa implementao do Argentum, claro, iteraremos pela SeriaTemporal
calculando os indicadores sobre ela.
Isto , uma vez que temos a SerieTemporal, nosso cdigo para plotar a mdia mvel simples do fechamento
em uma ChartSeries ser semelhante a este:
Conseguir a srie temporal um problema pelo qual j passamos antes. Relembre que a SerieTemporal
apenas um wrapper de uma lista de Candles. E a lista de Candles gerada pelo CandlestickFactory
resumindo uma lista com muitas Negociacoes.
Se procurarmos o local no nosso cdigo onde pegamos a lista de negociaes do web service, vamos notar
que isso acontece no construtor da ArgentumBean. Seu cdigo completo ficaria assim;
public ArgentumBean() {
this.negociacoes = new ClienteWebService().getNegociacoes();
List<Candle> candles = new CandleFactory().constroiCandles(negociacoes);
SerieTemporal serie = new SerieTemporal(candles);
Captulo 9 - Grficos interativos com Primefaces - Definio do modelo do grfico - Pgina 130
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Note, no entanto, que esse trecho de cdigo est com responsabilidades demais: ele busca as negociaes no
web service, cria a srie temporal, plota um indicador e disponibiliza o modelo do grfico. E, pior ainda, esse
cdigo ainda est no construtor do ArgentumBean!
Com todo esse cdigo no construtor do bean, teramos um cdigo mais sujo, pouco coeso e muito difcil de
testar. O que acontece aqui que no estamos separando responsabilidades o bastante e nem encapsulando
a lgica de gerao de grfico corretamente.
Os princpios de orientao a objetos e as boas prticas de programao vm ao nosso socorro aqui. Vamos
encapsular a maneira como o modelo do grfico criado na classe GeradorModeloGrafico.
Essa classe deve ser capaz de gerar o ChartModel para nosso grfico de linhas, com os pontos plotados pelos
indicadores com base nos valores de uma srie temporal. Isto , nosso GeradorModeloGrafico precisa receber
a SerieTemporal sobre a qual plotar os indicadores.
Se quisermos restringir o grfico a um perodo menor do que o devolvido pelo web service, uma boa re-
cebermos as posies de incio e fim que devem ser plotadas. Esse intervalo tambm serve para que no
tentemos calcular a mdia da posio zero, por exemplo -- note que, como a mdia dos trs ltimos valo-
res, tentaramos pegar as posies 0, -1 e -2, o que causaria uma IndexOutOfBoundsException.
Como essas informaes so fundamentais para qualquer grfico que plotemos, o gerador do modelo do
grfico receber tais informaes no construtor. Alm delas, teremos tambm o objeto do LineChartModel,
que guardar as informaes do grfico.
Captulo 9 - Grficos interativos com Primefaces - Isolando a API do Primefaces: baixo acoplamento - Pgina 131
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
this.serie = serie;
this.comeco = comeco;
this.fim = fim;
this.modeloGrafico = new LineChartModel();
}
Repare como o cdigo que usa o GeradorModeloGrafico no possui nada que o ligue ao ChartModel especi-
ficamente. O dia em que precisarmos mudar o grfico a ser plotado ou mesmo mudar a tecnologia que gerar
o grfico, s precisaremos alterar a classe GeradorModeloGrafico. Relembre o conceito: esse o poder do
encapsulamento!
E nossa classe no se limitar a isso: ela encapsular tudo o que for relacionado ao grfico. Por exemplo, para
criar o grfico, precisamos ainda de um mtodo que plote os pontos calculados por um indicador, como
o plotaMediaMovelSimples abaixo. Ele passa por cada posio do comeco ao fim da serie, chamando o
clculo da mdia mvel simples.
Por fim, ainda precisaremos de um mtodo getModeloGrafico que devolver o modelo para o ArgentumBean,
j que o componente p:chart que precisar desse objeto preenchido. Repare que o retorno do tipo
ChartModel, super classe do LineChartModel. boa prtica deixar nossa classe a mais genrica possvel
para funcionar com qualquer tipo de mtodo.
Captulo 9 - Grficos interativos com Primefaces - Isolando a API do Primefaces: baixo acoplamento - Pgina 132
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
O item 34 do Effective Java discorre sobre preferir referenciar objetos pela sua interface, em vez
de pelo seu prprio exato, sempre que este for relevante para o restante do sistema.
O livro tambm menciona que, na falta de uma interface adequada, uma superclasse pode ser
utilizada, o que nosso caso com a superclasse abstrata ChartModel. Referir-se a um objeto da
forma mais genrica possvel uma boa ideia, j que isso faz com que futuras mudanas limitem-
se ao mximo classe que as encapsula.
Veja como fica o programa dentro do ArgentumBean e note que essa classe apenas delega para a outra toda
a parte de criao do grfico:
public ArgentumBean() {
this.negociacoes = new ClienteWebService().getNegociacoes();
List<Candle> candles = new CandleFactory().constroiCandles(negociacoes);
SerieTemporal serie = new SerieTemporal(candles);
GeradorModeloGrafico geradorGrafico =
new GeradorModeloGrafico(serie, 2, serie.getUltimaPosicao());
geradorGrafico.plotaMediaMovelSimples();
this.modeloGrafico = geradorGrafico.getModeloGrafico();
}
Note que, para quem usa o GeradorModeloGrafico nem d para saber como ele gera o modelo. um cdigo
encapsulado, flexvel, pouco acoplado e elegante: usa boas prticas da Orientao a Objetos.
Captulo 9 - Grficos interativos com Primefaces - Isolando a API do Primefaces: baixo acoplamento - Pgina 133
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
A factory usada pelo GeradorDeSerie dos testes. A ideia que criar um objeto SerieTemporal diretamente
complicado. Ento criaram um mtodo de fbrica que encapsula essas complicaes e j devolve o objeto
prontinho para uso.
O padro Builder o que estamos usando na classe GeradorModeloGrafico. Queremos encapsular a criao
complicada do modelo e que pode mudar depois com o tempo. Entra a o objeto construtor da nossa classe
Builder: seu nico objetivo descrever os passos para criao do nosso objeto final (o grfico) e encapsular
a complexidade disso.
Captulo 9 - Grficos interativos com Primefaces - Para saber mais: Design Patterns Factory Method e Builder - Pgina 134
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
JFreeChart
Alm do fato de ser livre, possui a vantagem de ser bastante robusta e flexvel. possvel us-la
para desenhar grficos de pontos, de barra, de torta, de linha, grficos financeiros, gantt charts,
em 2D ou 3D e muitos outros. Consegue dar sada em JPG, PNG, SVG, EPS e at mesmo exibir
em componentes Swing.
http://www.jfree.org/jfreechart/
Existe um livro oficial do JFreeChart escrito pelos desenvolvedores com exemplos e explicaes
detalhadas de vrios grficos diferentes. Ele pago e pode ser obtido no site oficial. Alm disso,
h muitos tutoriais gratuitos na internet.
Use os recursos do Eclipse para escrever esse cdigo! Abuse do ctrl + espao, do ctrl + 1 e do ctrl
+ shift + O.
Captulo 9 - Grficos interativos com Primefaces - Exerccios: Grficos com Primefaces - Pgina 135
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
2) Agora que j temos uma classe que criar o modelo do grfico, falta us-la para renderizar o grfico na
tela usando a tag do Primefaces. Abra a pgina index.xhtml que se encontra na pasta WebContent.
Na pgina procure o componente h:body. Logo depois da abertura da tag h:body e antes do h:form da
lista de negociaes, adicione o componente p:chart:
<p:chart type=line model=#{argentumBean.modeloGrafico} />
3) Na classe ArgentumBean, procure o construtor. nele que criaremos uma SerieTemporal baseada na lista
de negociaes do Web Service. Depois usaremos o GeradorModeloGrafico para criar o modelo grfico:
public ArgentumBean() {
this.negociacoes = new ClienteWebService().getNegociacoes();
List<Candle> candles = new CandleFactory().constroiCandles(negociacoes);
SerieTemporal serie = new SerieTemporal(candles);
GeradorModeloGrafico geradorGrafico =
new GeradorModeloGrafico(serie, 2, serie.getUltimaPosicao());
geradorGrafico.plotaMediaMovelSimples();
this.modeloGrafico = geradorGrafico.getModeloGrafico();
}
Captulo 9 - Grficos interativos com Primefaces - Exerccios: Grficos com Primefaces - Pgina 136
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
4) Voc deve estar vendo um erro de compilao na ltima linha do seu construtor. Ele acontece porque
faltou criarmos um novo atributo que representa o modelo do grfico. Use o ctrl + 1 para criar o atributo
e, ao mesmo tempo, fazer o import da classe.
private ChartModel modeloGrafico;
Gere tambm o getter para este atributo, para que o componente p:chart consiga pegar o modelo do
grfico quando necessitar.
Para isso, na classe ArgentumBean, escreva getM e aperte ctrl + espao. O Eclipse sugerir o getter para o
atributo modeloGrafico.
Captulo 9 - Grficos interativos com Primefaces - Exerccios: Grficos com Primefaces - Pgina 137
Captulo 10
Esses indicadores, similarmente MediaMovelSimples, devem calcular o valor de uma posio do grfico
baseado na SerieTemporal que ele atende.
Se tivermos esses indicadores todos, precisaremos que o GeradorModeloGrafico consiga plotar cada um des-
ses grficos. Terminaremos com uma crescente classe GeradorModeloGrafico com mtodos extremamente
parecidos:
this.modeloGrafico.addSeries(chartSerie);
this.modeloGrafico.setLegendPosition(w);
this.modeloGrafico.setTitle(Indicadores);
}
//...
}
O problema que cada vez que criarmos um indicador tcnico diferente, um novo mtodo dever ser criado
na classe GeradorModeloGrafico. Isso uma indicao clssica de acoplamento no sistema.
Como resolver esses problemas de acoplamento e de cdigo parecidssimo nos mtodos? Ser que consegui-
mos criar um nico mtodo para plotar e passar como argumento qual indicador tcnico queremos plotar
naquele momento?
Note que a diferena entre os mtodos est apenas no new do indicador escolhido e na legenda do grfico. O
restante precisamente igual.
Captulo 10 - Aplicando Padres de projeto - Nossos indicadores e o design pattern Strategy - Pgina 139
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
A orientao a objetos nos d a resposta: polimorfismo! Repare que nossos dois indicadores possuem a
mesma assinatura de mtodo, parece at que eles assinaram o mesmo contrato. Vamos definir ento a inter-
face Indicador:
Na hora de desenhar os grficos, chamaremos sempre o plotaIndicador, passando como parmetro qual-
quer classe que seja um Indicador:
A ideia de usar uma interface comum ganhar polimorfismo e poder trocar os indicadores. Nosso mtodo
plota qualquer Indicador, isto , quando criarmos ou removermos uma implementao de indicador, no
precisaremos mexer no GeradorModeloGrafico: ganhamos flexibilidade e aumentamos a coeso. Podemos
ainda criar novos indicadores que implementem a interface e pass-los para o grfico sem que nunca mais
mexamos na classe GeradorModeloGrafico.
Por exemplo, imagine que queremos um grfico simples que mostre apenas os preos de fechamento. Pode-
mos considerar a evoluo dos preos de fechamento como um Indicador:
Captulo 10 - Aplicando Padres de projeto - Nossos indicadores e o design pattern Strategy - Pgina 140
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Temos agora vrios indicadores diferentes, cada um com sua prpria estratgia de clculo do valor, mas
todos obedecendo a mesma interface: dada uma srie temporal e a posio a ser calculada, eles devolvem
o valor do indicador. Note que o plotaIndicador no recebe dados, mas sim a forma de manipular esses
dados, a estratgia para trat-los. Esse o design pattern chamado de Strategy.
Design Patterns
Design Patterns so aquelas solues catalogadas para problemas clssicos de orientao a ob-
jetos, como este que temos no momento: encapsular e ter flexibilidade.
A fbrica de Candles apresentada em outro captulo e o mtodo que nos auxilia a criar sries
para testes na GeradorDeSerie so exemplos, respectivamente, dos padres Abstract Factory e
Factory Method. No caso que estamos estudando agora, o Strategy est nos ajudando a deixar a
classe GeradorModeloGrafico isolada das diferentes formas de clculo dos indicadores.
Abra a classe MediaMovelSimples e use o ctrl + 3 Extract interface. Selecione o mtodo calcula e d o
nome da interface de Indicador:
Captulo 10 - Aplicando Padres de projeto - Exerccios: refatorando para uma interface e usando bem os testes - Pgina 141
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Effective Java
3) Vamos criar tambm uma classe para, por exemplo, ser o indicador do preo de fechamento, o
IndicadorFechamento, no pacote br.com.caelum.argentum.indicadores, que implementa a interface
Indicador.
Note que, ao adicionar o trecho implements Indicador classe, o Eclipse mostra um erro de compilao.
Usando o ctrl + 1, escolha a opo Add unimplemented methods para que ele crie toda a assinatura do
mtodo calcula.
@Override
public double calcula(int posicao, SerieTemporal serie) {
return serie.getCandle(posicao).getFechamento();
}
}
Captulo 10 - Aplicando Padres de projeto - Exerccios: refatorando para uma interface e usando bem os testes - Pgina 142
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
@Override
public double calcula(int posicao, SerieTemporal serie) {
return serie.getCandle(posicao).getAbertura();
}
}
Ignore o erro e, quando essa refatorao terminar, remova a linha que declarava o indicador. Seu mtodo
terminar assim:
public void plotaIndicador(Indicador indicador) {
LineChartSeries chartSeries = new LineChartSeries(indicador.toString());
6) Repare que estamos chamando o mtodo toString() do indicador no mtodo plotaIndicador(). Va-
mos sobrescrev-lo em todos os indicadores criados.
Sobrescreva na classe MediaMovelSimples:
Captulo 10 - Aplicando Padres de projeto - Exerccios: refatorando para uma interface e usando bem os testes - Pgina 143
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
No esquea de fazer os testes para essa nova verso e alterar os testes j existentes para usar esse clculo
novo. Os testes j existentes que ficarem desatualizados aparecero com erros de compilao.
2) Toda refatorao deve ser acompanhada dos testes para garantir que no quebramos nada! Rode os testes
e veja se as mudanas feitas at agora mudaram o comportamento do programa.
A maior parte do cdigo seria a mesma e no estamos reaproveitando cdigo - copiar e colar cdigo no
reaproveitamento, uma forma de nos dar dor de cabea no futuro ao ter que manter 2 cdigos idnticos em
lugares diferentes.
Queremos calcular mdias mveis de fechamento, abertura, volume, etc, sem precisar copiar essas classes de
mdia. Na verdade, o que queremos calcular a mdia mvel baseado em algum outro indicador. J temos
a classe IndicadorFechamento e trivial implementar outros como IndicadorAbertura, IndicadorMinimo,
etc.
A MediaMovelSimples um Indicador que vai depender de algum outro Indicador para ser calculada (por
exemplo o IndicadorFechamento). Queremos chegar em algo assim:
Repare na flexibilidade desse cdigo. O clculo de mdia fica totalmente independente do dado usado e, toda
vez que criarmos um novo indicador, j ganhamos a mdia mvel desse novo indicador de brinde. Vamos
fazer ento nossa classe de mdia receber algum outro Indicador:
Captulo 10 - Aplicando Padres de projeto - Indicadores mais elaborados e o Design Pattern Decorator - Pgina 145
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
this.outroIndicador = outroIndicador;
}
@Override
public double calcula(int posicao, SerieTemporal serie) {
double soma = 0.0;
for (int i = posicao; i > posicao 3; i) {
soma += outroIndicador.calcula(i, serie);
}
return soma / 3;
}
Nossa classe MediaMovelSimples recebe um outro indicador que modifica um pouco os valores de sada -
ele complementa o algoritmo da mdia! Passar um objeto que modifica um pouco o comportamento do seu
uma soluo clssica para ganhar em flexibilidade e, como muitas solues clssicas, ganhou um nome
nos design patterns de Decorator.
Tambm um composite!
Note que, agora, nossa MediaMovelSimples um Indicador e tambm tem um outro Indicador.
J vimos antes outro tipo que se comporta da mesma forma, voc se lembra?
Para isso, crie o construtor padro (sem parmetros) da MediaMovelSimples usando o atalho de sua pre-
ferncia:
Captulo 10 - Aplicando Padres de projeto - Exerccios: Indicadores mais espertos e o Design Pattern Decorator - Pgina 146
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
2) Modifique o construtor usando o atalho alt + shift + C para adicionar o parmetro do tipo Indicador
chamado outroIndicador e com valor padro new IndicadorFechamento().
Agora, com o cursor sobre o parmetro outroIndicador, faa ctrl + 1 e guarde esse valor em um novo
atributo, selecionando assign parameter to new field.
4) Lembre que toda refatorao deve ser acompanhada dos testes correspondentes. Mas ao usar a refatorao
do Eclipse no construtor da nossa classe MediaMovelSimples, a IDE evitou que quebrssemos os testes j
passando o IndicadorFechamento como parmetro padro para todos eles!
Agora, rode os testes novamente e tudo deve continuar se comportando exatamente como antes da refa-
torao. Caso contrrio, nossa refatorao no foi bem sucedida e seria bom reverter o processo todo.
Isto , faa ela tambm receber um outroIndicador no construtor e delegar a chamada a esse indicador
no seu mtodo calcula, assim como fizemos com a MediaMovelSimples.
Captulo 10 - Aplicando Padres de projeto - Exerccios: Indicadores mais espertos e o Design Pattern Decorator - Pgina 147
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Captulo 10 - Aplicando Padres de projeto - Exerccios: Indicadores mais espertos e o Design Pattern Decorator - Pgina 148
Captulo 11
A API de Reflection
At agora, ao acessar a aplicao pelo navegador, o grfico e a tabela de negociaes sero gerados automa-
ticamente. No h nenhuma forma de personalizar o grfico, como por exemplo a opo de ver apenas um
dos indicadores por vez.
Vamos melhorar a interface e adicionar um formulrio que oferece para o usurio as seguintes opes:
H informao demais nesse grfico e isso o torna menos til. Seria muito mais interessante se o usurio
pudesse escolher quais indicadores ele quer ver e mandar plotar apenas estes no grfico. Uma das formas
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
possveis para isso seria colocarmos as opes para que ele decida e um boto que disparar a gerao do
grfico. Nossa tela ficar parecida com:
Parece bom? Felizmente, colocar tais botes na tela uma tarefa bastante simples! Como diversas aplicaes
tm a necessidade desses botes, esses componentes j existem e us-los ser bem semelhante ao que j
vnhamos fazendo desde nossos primeiros exemplos com JSF.
Tais componentes so, inclusive, to comuns que existem tanto na implementao do JSF quanto no Prime-
faces e nas outras bibliotecas semelhantes. Esse um dilema comum quando trabalhamos com JSF: usar a
implementao padro ou a do Primefaces.
Essa escolha usualmente cai para a utilizao da biblioteca, j que seus componentes j vm com um estilo
uniforme e, como j vimos antes, frequentemente adicionam funcionalidades interessantes aos componentes.
Sabendo disso, daremos preferncia para os componentes do Primefaces, embora isso traga alguns efeitos
colaterais. Fique atento s particularidades em destaque no decorrer desse captulo.
Para que o usurio escolha qual grfico ele quer plotar, ser necessrio que ele consiga interagir com a tela,
isto , precisamos de um componente de input de dados. H diversos deles disponveis no Primefaces: http:
//www.primefaces.org/showcase/index.xhtml
Como temos opes pr-definidas para as mdias e para os indicadores bsicos, usaremos um componente
de select. Voc pode descobr-los at de dentro do Eclipse, no index.xhtml: basta abrir a tag <p:select e
usar o ctrl + espao!
Para replicar a tela do screenshot acima, usaremos o componente com cara de boto que permite escolher
apenas uma opo, o p:selectOneButton. E, como qualquer select, precisamos tambm indicar quais so
os itens que serviro de opo.
Marcamos, atravs do value, que esse componente est ligado ao atributo nomeMedia da classe ArgentumBean.
Quando o usurio escolher o boto desejado, o itemValue ser atribudo a esse atributo.
Semelhantemente, queremos outra listagem de indicadores possveis, mas agora com nossos indicadores
bsicos:
Finalmente, tambm precisamos que o usurio indique que terminou de escolher e mande efetivamente gerar
tal grfico. E a forma mais natural de fazer isso atravs de um boto com uma determinada ao -- em
outras palavras, a action desse componente indica o mtodo que ser chamado quando o usurio apertar o
boto:
Note que esse boto do Primefaces muito mais atraente do que o boto padro que usamos no
olaMundo.xhtml. A folha de estilos do Primefaces realmente superior, mas no s isso que muda!
Os botes do Primefaces no so apenas bonitos. Eles tambm trabalham por padro com cha-
madas via AJAX, em vez de recarregar a tela toda. Isso interessante quando temos telas com-
plexas, com diversas informaes e o apertar de um boto altera somente um pedao dela.
Contudo, exatamente porque nossa chamada ser executada via AJAX, no haver navegao e
os outros componentes da tela no sero recarregados, a menos que explicitamente indiquemos
que tal boto deve recarregar um componente.
No nosso caso, queremos que apertar boto Gerar grfico regere o modelo do grfico e recarregue tal com-
ponente na tela, ento ainda necessrio alterar o p:commandButton para que ele atualize o grfico. Para isso,
precisamos indicar ao boto que ele ser tambm responsvel por atualizar o componente do grfico. Para
ligar um componente ao outro, usaremos um id.
Note o : (dois pontos). Isso indica para o boto que ele partir da tag raiz da pgina procurando algum
componente com id grafico. E, para que isso funcione, tambm necessrio que o componente do grfico
tenha tal id.
Lembre-se tambm que sempre que temos botes, precisamos que eles estejam dentro de um componente
h:form. Fora deste componente, os botes no funcionam. Outro detalhe aqui que, por padro, o Pri-
mefaces coloca cada label, select e boto em uma linha. Esse comportamento timo para formulrios mais
padro, mas se quisermos mostrar tudo em uma linha s ainda podemos utilizar um panelGrid com 5 colunas
para acomodar os 5 componentes desse menu.
<h:form>
<h:panelGrid columns=5>
<h:outputLabel value=Media Mvel: />
<p:selectOneButton value=#{argentumBean.nomeMedia}>
<f:selectItem itemLabel=Simples itemValue=MediaMovelSimples />
<f:selectItem itemLabel=Ponderada itemValue=MediaMovelPonderada />
</p:selectOneButton>
E o ManagedBean?
Semelhantemente proposta do JSF, focamos apenas nos novos componentes e todas as alteraes propostas
nesse captulo esto limitadas a alteraes no index.xhtml.
</h:panelGrid>
</h:form>
2) Agora, dentro do h:panelGrid, precisamos colocar nossos selects das mdias e dos indicadores bsicos,
juntamente com as respectivas legendas dos campos:
<h:outputLabel value=Media Mvel: />
<p:selectOneButton value=#{argentumBean.nomeMedia}>
<f:selectItem itemLabel=Simples itemValue=MediaMovelSimples />
<f:selectItem itemLabel=Ponderada itemValue=MediaMovelPonderada />
</p:selectOneButton>
3) Suba o TomCat agora e verifique que recebemos uma ServletException. Ela nos informa que ainda no
temos a propriedade nomeMedia no ArgentumBean. Precisamos criar os atributos necessrios para que
esses componentes funcionem corretamente.
Ateno: se seu ArgentumBean no estiver anotado com @ViewScoped, anote-o. A explicao dos escopos
est no exerccio opcional de paginao e ordenao, no captulo de Introduo ao JSF.
Captulo 11 - A API de Reflection - Exerccios: permitindo que o usurio escolha o grfico - Pgina 153
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
4) Reinicie o TomCat e veja os selects na tela. Falta pouco! De volta ao index.xhtml coloque o boto no
mesmo formulrio, logo aps os selects. Coloque tambm o id=grafico no componente p:chart que j
existe, para fazer com que o clique no boto atualize tambm esse componente.
<p:commandButton value=Gerar grfico update=:grafico
action=#{argentumBean.geraGrafico}/>
</h:panelGrid>
</h:form>
5) J possvel ver a tela, mas ao clicar no boto de gerar o grfico, nada acontece. Na verdade, no Console do
Eclipse possvel ver que uma exceo foi lanada porque o mtodo que o boto chama, o geraGrafico,
ainda no existe.
Esse mtodo ter que, a partir da lista de negociaes, criar as Candles, a Srie Temporal, mandar plotar
um indicador ao grfico e disponibilizar o modelo atualizado para o grfico. Note, no entanto, que nosso
construtor j faz todo esse trabalho!
Basta fazermos uma simples refatorao Extract method nessas linhas! Selecione tais linhas do construtor
da ArgentumBean e use ctrl + 3 extract method indicando que o novo mtodo deve se chamar geraGrafico
e deve ser pblico.
6) Finalmente, para verificarmos que estamos recebendo informaes corretas sobre qual indicador plotar
Captulo 11 - A API de Reflection - Exerccios: permitindo que o usurio escolha o grfico - Pgina 154
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
no momento que o mtodo geraGrafico chamado, vamos imprimir essas informaes no console com
um simples syso.
Teste os botes e mande gerar o grfico. Ateno! O grfico ainda no ser gerado corretamente! Falta
implementarmos essa parte no bean. Olhando no Console do Eclipse, contudo, note que nosso syso j
mostra que os atributos que escolhero qual indicador plotar j foi escolhido corretamente!
No entanto, ainda no estamos usando essa informao para plotar o indicador escolhido pelo usurio -
ainda estamos plotando a mdia mvel simples do fechamento em todos os casos. Essa informao est
hard-coded no geraGrafico
GeradorModeloGrafico geradorGrafico =
new GeradorModeloGrafico(serie, 2, serie.getUltimaPosicao());
geradorGrafico.plotaIndicador(
new MediaMovelSimples(new IndicadorFechamento()));
this.modeloGrafico = geradorGrafico.getModeloGrafico();
}
Note que as informaes de qual indicador o usurio quer plotar j esto preenchidas nos atributos nomeMedia
e nomeIndicadorBase, mas esses atributos so meramente Strings passadas pelo componente de select.
Poderamos, ento, usar um conjunto de if/else para decidir qual indicador usar:
if (IndicadorAbertura.equals(nomeIndicadorBase))
return new MediaMovelSimples(new IndicadorAbertura());
if (IndicadorFechamento.equals(nomeIndicadorBase))
return new MediaMovelSimples(new IndicadorFechamento());
} else if (MediaMovelPonderada.equals(nomeMedia)) {
// varios outros ifs
fcil ver que essa uma soluo extremamente deselegante. Nesse pequeno trecho escrevemos quatro ifs
e isso um sinal de mal design. Pense agora no teste para esse trecho de cdigo: esse mtodo sozinho tem
quatro caminhos possveis de se percorrer. Esse nmero tambm chamado de complexidade ciclomtica.
Quatro no um nmero ruim, mas note que, ao adicionar um novo indicador bsico ou uma nova
mdia, esse nmero aumentar de forma multiplicativa. O nmero de caminhos ser sempre igual
quantidadeDeMedias * quantidadeDeIndicadoresBase.
Complexidade Ciclomtica
Essa mtrica expe o nmero de caminhos diferentes que uma execuo pode percorrer em um
mtodo. O problema de uma complexidade ciclomtica alta que: quanto maior esse nmero
for, mais testes sero necessrios para garantir o funcionamento esperado.
Para maiores detalhes sobre essa mtrica consulte no blog da caelum esse artigo: http://blog.
caelum.com.br/medindo-a-complexidade-do-seu-codigo/
Embora seja aceitvel para um nmero bem pequeno de indicadores, conforme nosso sistema evolui fun-
damental que encontremos um jeito melhor de conseguir um objeto de Indicador a partir das Strings que j
temos.
Nesse caso a API de reflection cai com uma luva. Com ela podemos escrever o cdigo que cria objetos ou
chamar mtodos sem conhecer as classes antecipadamente, justamente o que precisamos para montar as
indicadores.
Mas existem algumas raras situaes onde essa garantia do compilador no nos ajuda. Isto , existem situ-
aes em que precisamos de caractersticas dinmicas. Por exemplo, imagine permitir que, dado um nome
de mtodo que o usurio passar, ns o invocaremos em um objeto. Ou ainda, que, ao recebermos o nome de
uma classe enquanto executando o programa, possamos criar um objeto dela!
Nas prximas sees, voc vai conhecer um pouco desse recurso avanado e muito poderoso que, embora
possua diversas qualidades, aumenta bastante a complexidade do nosso cdigo e por essa razo deve ser
usado de forma sensata.
O XStream foi construdo para funcionar com qualquer tipo de XML e objeto. Com um pouco de ponderao
fica bvio que no h um new para cada objeto possvel e imaginvel dentro do cdigo do XStream. Mas
como ele consegue instanciar um objeto da minha classe e popular os atributos, tudo sem precisar ter new
Negociacao() escrito dentro dele?
O java.lang.reflect um pacote do Java que permite criar instncias e chamadas em tempo de execuo,
sem precisar conhecer as classes e objetos envolvidos no momento em que escrevemos nosso cdigo (tempo
de compilao). Esse dinamismo necessrio para resolvermos determinadas tarefas que s descobrimos
serem necessrias ao receber dados, isto , em tempo de execuo.
De volta ao exemplo do XStream, ele s descobre o nome da nossa classe Negociacao quando rodamos o
programa e selecionamos o XML a ser lido. Enquanto escreviam essa biblioteca, os desenvolvedores do
XStream no tinham a menor ideia de que um dia o usaramos com a classe Negociacao.
Mas nem mesmo precisamos de um objeto para conseguir as informaes da sua classe. Diretamente com o
nome da classe tambm podemos fazer o seguinte:
Ou ainda, se tivermos o caminho completo da classe, conseguimos recuperar tal classe at atravs de uma
String:
Java 5 e Generics
A partir do Java 5, a classe Class tipada e recebe o tipo da classe que estamos trabalhando. Isso
melhora alguns mtodos, que antes recebiam Object e agora trabalham com um tipo T qualquer,
parametrizado pela classe.
A partir de um Class podemos listar, por exemplo, os nomes e valores dos seus atributos:
A sada ser:
preco
quantidade
data
getPreco
getQuantidade
getData
getVolume
isMesmoDia
Assim como podemos descobrir mtodos e atributos, o mesmo aplica para construtores. Para, por exemplo,
descobrir o construtor da classe MediaMovelSimples:
interface br.com.caelum.argentum.indicadores.Indicador
possvel fazer muito mais. Investigue a API de reflection usando ctrl + espao a partir das classes Method,
Constructor e Fields no Eclipse e pelo JavaDoc.
Para a mdia o trabalho um pouco maior, j que precisamos passar um Indicador como parmetro na
instanciao do objeto. Isso pode ser at mais complexo se houver outros indicadores na classe em questo.
Nesse caso, no basta fazer a chamada ao mtodo newInstance(), j que este s consegue instanciar objetos
quando o construtor padro existe.
Por outro lado, j sabemos como descobrir o construtor a partir de um Class. A boa notcia que existe
como criarmos uma instncia a partir de um Constructor, pelo mesmo mtodo newInstance() que passa a
receber parmetros.
Veja o cdigo:
Repare que esse cdigo funciona com qualquer indicador ou mdia que siga a conveno de passar o nome
da classe no itemValue do select e a conveno de pacote.
Se errarmos alguma dessas informaes, no entanto, diversos erros podem acontecer e por isso que
o cdigo acima pode lanar diversas excees: InstantiationException, IllegalAccessException,
ClassNotFoundException, NoSuchMethodException, InvocationTargetException.
Como essas excees so todas checked, seria necessrio declar-las todas com um throws na assinatura do
mtodo defineIndicador, o que pode no ser desejvel. Podemos, ento, apelar para um try/catch que
encapsule tais excees em uma unchecked para que ela continue sendo lanada, mas no suje a assinatura
do mtodo com as tantas excees. Essa uma prtica um tanto comum, hoje em dia, e linguagens mais
novas chegam a nem ter mais as checked exceptions.
2) Use o ctrl + 1 e escolha a opo Create method defineIndicador. O Eclipse gerar o esqueleto do mtodo
para ns e, agora, falta preench-lo.
private Indicador defineIndicador() {
String pacote = br.com.caelum.argentum.indicadores.;
Class<?> classeIndicadorBase = Class.forName(pacote + nomeIndicadorBase);
Indicador indicadorBase = (Indicador) classeIndicadorBase.newInstance();
3) O cdigo acima ainda no compila! As diversas excees que a API de reflection lana ainda precisam
ser tratadas. Com a ajuda do Eclipse, envolva todo esse trecho de cdigo com um try/catch que pega
qualquer Exception e a encapsula em uma RuntimeException.
private Indicador defineIndicador() {
try {
String pacote = br.com.caelum.argentum.indicadores.;
Class<?> classeIndicadorBase = Class.forName(pacote + nomeIndicadorBase);
Indicador indicadorBase = (Indicador) classeIndicadorBase.newInstance();
4) Vamos aproveitar e adicionar um comportamento padro para quando o usurio no tiver escolhido
qual grfico ele quer ainda. Antes mesmo do bloco de try/catch, podemos adicionar o comportamento
padro de, se os indicadores no estiverem escolhidos, devolvemos por padro a Mdia Mvel Simples
do Fechamento.
private Indicador defineIndicador() {
if (nomeIndicadorBase == null || nomeMedia == null)
return new MediaMovelSimples(new IndicadorFechamento());
try {
//...
5) Reinicie o TomCat e acesse o Argentum para testar o funcionamento dessa nova modificao no sistema.
Tudo deve estar funcionando!
Alm disso, nosso mtodo defineIndicador um mtodo privado na ArgentumBean e isso o torna extrema-
mente difcil de testar.
Podemos, por exemplo, extrair essa lgica de definio do indicador para uma classe completamente
nova, que tivesse essa nica responsabilidade. Assim, nosso mtodo geraGrafico instanciaria um
IndicadorFactory, que devolveria o indicador correto:
Assim, o mtodo defineIndicador() passar a ser pblico e, portanto, muito mais facilmente testvel e
muito mais coeso - seguindo um dos princpios SOLID: mais especificamente, o princpio da responsabili-
dade nica
2) (Opcional) Traga para essa classe o mtodo defineIndicador, alterando ele para pblico, agora que
ele est em outra classe. Lembre-se, tambm, de arrumar erros de compilao que surgirem na classe
ArgentumBean.
3) (Opcional) Crie testes para a IndicadorFactory. Um desses testes deve verificar o comportamento
quando no passamos o nome de uma das classes. Outro, poderia motivar a melhoria do tratamento
das excees para algo mais descritivo.
Podemos fazer isso adicionando mais um campo no formulrio, sendo que este ser um campo de texto, e
para isso devemos utilizar a tag <h:inputText> do JSF, ou ento a tag <p:inputText> do PrimeFaces:
Tambm ser necessrio adicionar mais um atributo do tipo String classe ArgentumBean, bem como seu
getter e setter.
Outra mudana que precisamos fazer passar o ttulo digitado pelo usurio para o GeradorModeloGrafico.
Podemos passar esta informao pelo construtor, ao instanciarmos o objeto GeradorModeloGrafico:
geradorGrafico.plotaIndicador(defineIndicador());
this.modeloGrafico = geradorGrafico.getModeloGrafico();
}
//restante do cdigo
E por fim no mtodo plotaIndicador devemos atribuir o ttulo do grfico ao objeto LineChartModel:
Captulo 12 - Apndice Testes de interface com Selenium - Validao com JSF - Pgina 164
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
O JSF vem nos socorrer. Se quisermos tornar o preenchimento do ttulo obrigatrio, basta adicionarmos
o atributo required="true" no componente p:inputText. A mesma coisa vlida para o h:inputText da
especificao.
Quando o formulrio for submetido com o ttulo em branco, o JSF automaticamente gerar uma mensa-
gem avisando ao usurio que o campo deve ser preenchido. O problema que ainda no definimos qual
componente ser utilizado para mostrar essa mensagem.
O PrimeFaces possui o componente p:messages que exibe para o usurio as mensagens geradas pelo JSF,
em nosso caso, as de validao. O objetivo aqui fazer com que a mensagem de preenchimento obrigatrio,
inclusive outras mensagens que possam ser geradas, seja exibida para o usurio:
....
<h:form>
<p:messages autoUpdate=true />
....
O atibuto autoUpdate="true" indica ao PrimeFaces que este componente deve ser atualizado automatica-
mente em caso de requisies AJAX.
Pronto, quando o formulrio for submetido com o campo ttulo em branco o JSF exibir automaticamente a
mensagem de validao:
Captulo 12 - Apndice Testes de interface com Selenium - Validao com JSF - Pgina 165
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Temos que testar o nosso cdigo, mas em uma aplicao web fica difcil testar a camada de apresentao,
o resultado final. Como testar a compatibilidade entre browsers diferentes de maneira automatizada? Em
geral, como testar se a pgina renderizada tem o resultado desejado?
Para isso ser possvel, existem algumas ferramentas que permitem tal trabalho, simulando a interao de um
usurio com a aplicao. Esse o caso do Selenium que, com a assistncia do JUnit, pode facilitar o trabalho
de escrever tais testes.
A primeira coisa que uma pessoa faz para testar a aplicao abrir um browser. Com Selenium, precisamos
apenas da linha abaixo:
Nesse caso, abrimos o Firefox. A ideia aqui igual ao mundo JDBC onde o Driver abstrai detalhes sobre o
funcionamento do banco de dados. Em nosso caso o driver se preocupa com a comunicao com o navega-
dor.
H outros drivers disponveis para Chrome, Internet Explorer, Safari e at para Android ou iPhone. O que
precisa mudar apenas a implementao concreta da interface WebDriver, por exemplo:
Captulo 12 - Apndice Testes de interface com Selenium - Introduo aos testes de aceitao - Pgina 166
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
HtmlUnitDriver
H uma outra implementao do WebDriver disponvel que nem precisa abrir um navegador.
Ela se chama HtmlUnitDriver e simula o navegador em memria. Isso muito mais rpido mas
no testa a compatibilidade do navegador fidedignamente:
Essa alternativa bastante utilizada em ambientes de integrao que fazem uso de um cloud, j
que no temos disponveis um browser para teste.
O prximo passo indicar qual pgina queremos abrir atravs do navegador. O driver possui um mtodo
navigate().to() que recebe a URL:
driver.navigate().to(http://localhost:8080/fj22argentumweb/index.xhtml);
Com a pgina aberta, faremos a insero de um valor em branco no campo titulo. Para isso, precisamos da
referncia deste elemento em nosso cdigo, o que feito pelo mtodo findElement.
Este mtodo recebe como parmetro um critrio de busca. A classe By possui uma srie de mtodos estticos.
Pesquisaremos pelo id:
driver.navigate().to(http://localhost:8080/fj22argentumweb/index.xhtml);
Agora que temos o elemento, podemos preench-lo com o texto que quisermos atravs do mtodo sendKeys.
Em nosso caso, deixaremos o campo em branco passando uma string vazia:
driver.navigate().to(http://localhost:8080/fj22argentumweb/index.xhtml);
titulo.sendKeys();
Quando o formulrio for submetido e o campo titulo estiver em branco, esperamos que o sistema mostre
a mensagem Erro de Validao.
Captulo 12 - Apndice Testes de interface com Selenium - Como funciona? - Pgina 167
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Antes de testarmos se tudo esta correto, precisamos submeter o formulrio. O objeto WebElement possui o
mtodo submit que faz exatamente isso:
driver.navigate().to(http://localhost:8080/fj22argentumweb/index.xhtml);
titulo.sendKeys();
titulo.submit();
Para termos certeza de que o sistema esta validando, pediremos ao Selenium que procure pelo texto Erro
de Validao. Primeiro, precisamos evocar o mtodo getPageSource, que nos permite procurar por algo no
cdigo da pgina, e logo em seguida o mtodo contains, que retorna true ou false:
driver.navigate().to(http://localhost:8080/fj22argentumweb/index.xhtml);
titulo.sendKeys();
titulo.submit();
Por fim, aps o formulrio ter sido submetido, precisamos saber se tudo saiu conforme o planejado, o que
pode ser feito atravs do mtodo esttico assertTrue da classe Assert, que recebe como parmetro um
boolean que indica a presena ou no do texto procurado pelo mtodo contains:
driver.navigate().to(http://localhost:8080/fj22argentumweb/index.xhtml);
titulo.sendKeys();
titulo.submit();
Assert.assertTrue(existeMensagem);
Captulo 12 - Apndice Testes de interface com Selenium - Como funciona? - Pgina 168
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Pronto, podemos verificar no prprio Eclipse se o teste passou se ele estiver verde. Se algo der errado, como
de costume, a cor vermelha ser utilizada.
driver.navigate().to(http://localhost:8080/fj22argentumweb/index.xhtml);
titulo.sendKeys();
titulo.submit();
Assert.assertTrue(existeMensagem);
driver.close();
@Before
public void setUp() {
driver = new FirefoxDriver();
}
Este mtodo ser invocado antes de cada teste, sempre abrindo uma nova janela. Analogamente, existe a
anotao @After, que indica que o mtodo ser invocado aps cada teste. Agora, precisamos fechar essas
janelas:
@After
public void tearDown() {
driver.close();
}
Captulo 12 - Apndice Testes de interface com Selenium - Trabalhando com diversos testes de aceitao - Pgina 169
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
commons-exec-1.1.jar
commons-logging-1.1.3.jar
gson-2.3.jar
guava-18.0.jar
httpclient-4.3.4.jar
httpcore-4.3.2.jar
selenium-java-2.44.0.jar
1) Primeiramente devemos alterar nossa pgina adicionando o campo para o ttulo. Adicione o campo de
texto logo aps a abertura da tag <h:panelGrid> no arquivo index.xhtml:
<h:panelGrid columns=5>
<h:outputLabel value=Ttulo Grfico: />
<p:inputText id=titulo value=#{argentumBean.titulo} required=true/>
2) Como adicionamos mais um campo no formulrio, altere a quantidade de colunas para 6 no componente
<h:panelGrid>:
<h:panelGrid columns=6>
3) Para facilitar a localizao do campo ttulo nos testes, vamos atribuir um id ao componente <h:form>
<h:form id=dadosGrafico>
<h:panelGrid columns=6>
4) Devemos agora alterar a classe ArgentumBean adicionando o atributo titulo, juntamente como seu getter
e setter:
@ManagedBean
@ViewScoped
public class ArgentumBean implements Serializable {
Captulo 12 - Apndice Testes de interface com Selenium - Para saber mais: Configurando o Selenium em casa - Pgina 170
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
//restante do cdigo
5) Ainda na classe ArgentumBean vamos alterar o mtodo geraGrafico, passando o ttulo como parmetro
para o construtor do GeradorModeloGrafico:
public void geraGrafico() {
List<Candle> candles = new CandleFactory().constroiCandles(this.negociacoes);
SerieTemporal serie = new SerieTemporal(candles);
//restante do cdigo
6) Agora na classe GeradorModeloGrafico vamos alterar o construtor para receber o ttulo como parmetro,
e atribu-lo a um novo atributo:
public class GeradorModeloGrafico {
Captulo 12 - Apndice Testes de interface com Selenium - Exerccios: Testes de aceitao com Selenium - Pgina 171
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
modeloGrafico:
8) Agora vamos colocar os jars do Selenium no nosso projeto, eles se encontram na pasta
Desktop/caelum/22/selenium-jars/:
Para adicion-los ao projeto, crie uma nova pasta chamada lib-teste na raiz do projeto e copie os jars
para dentro dela.
Captulo 12 - Apndice Testes de interface com Selenium - Exerccios: Testes de aceitao com Selenium - Pgina 172
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
9) Crie a classe usando ctrl + N Class, chamada GeraGraficoTest no source folder src/test/java e dentro do
pacote br.com.caelum.argentum.aceitacao:
10) A classe ter dois atributos. O primeiro com a URL da pgina que queremos testar e o segundo o Web-
Driver, o objeto que nos permite manipular o navegador.
public class GeraGraficoTest {
@Test
public void testeAoGerarGraficoSemTituloUmaMensagemEhApresentada() {
}
}
12) Usaremos o WebDriver para abrir uma nova janela do Firefox e acessar a URL do projeto, e usaremos o
mtodo driver.close() para fechar a janela
public class GeraGraficoTest {
Captulo 12 - Apndice Testes de interface com Selenium - Exerccios: Testes de aceitao com Selenium - Pgina 173
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
@Test
public void testeAoGerarGraficoSemTituloUmaMensagemEhApresentada() {
driver = new FirefoxDriver();
driver.navigate().to(URL);
driver.close();
}
}
13) Estamos testando se a mensagem de erro aparece quando submetemos um formulrio com o ttulo. Para
isso, primeiro precisamos capturar o elemento do ttulo em um WebElement. Como estamos trabalhando
com JSF, devemos lembrar que ele concatena o id do formulrio com o id dos inputs. Por conseguinte,
devemos procurar o elemento pelo id dadosGrafico:titulo
public class GeraGraficoTest {
@Test
public void testeAoGerarGraficoSemTituloUmaMensagemEhApresentada() {
driver = new FirefoxDriver();
driver.navigate().to(URL);
WebElement titulo = driver.findElement(By.id(dadosGrafico:titulo));
titulo.sendKeys();
titulo.submit();
Assert.assertTrue(existeMensagem);
driver.close();
}
}
14) Vemos que usamos driver = new FirefoxDriver() para abrir uma janela (um WebDriver) do navega-
dor, e driver.close() para fechar a janela. Caso formos escrever mais testes, precisaremos abrir e fechar
Captulo 12 - Apndice Testes de interface com Selenium - Exerccios: Testes de aceitao com Selenium - Pgina 174
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
o navegador novamente. Para podermos reaproveitar esse cdigo, podemos coloc-los em blocos sepa-
rados e usar as anotaes @Before, para execut-lo antes de cada mtodo, e @After, para execut-lo aps
cada mtodo.
public class GeraGraficoTest {
@Before
public void setUp() {
driver = new FirefoxDriver();
}
@After
public void tearDown() {
driver.close();
}
@Test
public void testeAoGerarGraficoSemTituloUmaMensagemEhApresentada() {
driver.navigate().to(URL);
WebElement titulo = driver.findElement(By.id(dadosGrafico:titulo));
titulo.sendKeys();
titulo.submit();
Assert.assertTrue(existeMensagem);
}
}
Captulo 12 - Apndice Testes de interface com Selenium - Exerccios: Testes de aceitao com Selenium - Pgina 175
ndice Remissivo
anotaes, 37
Calendar, 13
Candlestick, 5, 8
datas, 13
Design patterns, 141
Factory pattern, 13
final, 9
h:form, 108
JUnit, 35
Negociao, 8
Reflection, 157
static import, 51
Tail, 6
TDD, 65
Test driven design, 65
testes de unidade, 34
testes unitrios, 34
176