Você está na página 1de 189

Cursos Caelum

Conhea mais da Caelum.


Cursos Online
www.caelum.com.br/online
Blog Caelum
blog.caelum.com.br
Newsletter
www.caelum.com.br/newsletter
Facebook
www.facebook.com/caelumbr
Twitter
twitter.com/caelum
Casa do Cdigo
Livros para o programador
www.casadocodigo.com.br
Conhea alguns de nossos cursos
FJ-11:
Java e Orientao a
objetos
FJ-26:
Laboratrio Web com JSF2 e
CDI
FJ-16:
Laboratrio Java com Testes,
XML e Design Patterns
FJ-19:
Preparatrio para Certificao
de Programador Java
FJ-21:
Java para Desenvolvimento
Web
FJ-31:
Java EE avanado e
Web Services
FJ-91:
Arquitetura e Design de
Projetos Java
RR-71:
Desenvolvimento gil para Web
2.0 com Ruby on Rails
RR-75:
Ruby e Rails avanados: lidando
com problemas do dia a dia
Mais de 8000 alunos treinados;
Reconhecida nacionalmente;
Contedos atualizados para o mercado e para sua carreira;
Aulas com metodologia e didtica cuidadosamente preparadas;
Ativa participao nas comunidades Java, Rails e Scrum;
Salas de aula bem equipadas;
Instrutores qualicados e experientes;
Apostilas disponveis no site.
Para mais informaes e outros cursos, visite: caelum.com.br/cursos
FJ-25:
Persistncia com JPA2 e
Hibernate
Sobre esta apostila
Esta apostila da Caelumvisa 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 nal do ndice.
Baixe sempre a verso mais nova em: www.caelum.com.br/apostilas
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

Sumrio
: Tornando-se um desenvolvedor pragmtico :
. O que realmente importante? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. A importncia dos exerccios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Tirando dvidas e referncias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Para onde ir depois? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
i O modelo da bolsa de valores, datas e objetos imutveis {
. A bolsa de valores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Candlesticks: O Japo e o arroz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. O projeto Tail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. O projeto Argentum: modelando o sistema . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Trabalhando com dinheiro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Palavra chave nal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Imutabilidade de objetos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Trabalhando com datas: Date e Calendar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Exerccios: o modelo do Argentum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Resumo dirio das Negociaes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Exerccios: fbrica de Candlestick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Exerccios opcionais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Testes Automatizados o
. Nosso cdigo est funcionando corretamente? . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Exerccios: testando nosso modelo sem frameworks . . . . . . . . . . . . . . . . . . . . . . . . .
. Denindo melhor o sistema e descobrindo mais bugs . . . . . . . . . . . . . . . . . . . . . . . .
. Testes de Unidade . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. JUnit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Anotaes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. JUnit, convenes e anotao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Exerccios: migrando os testes do main para JUnit . . . . . . . . . . . . . . . . . . . . . . . . . .
. Vale a pena testar classes de modelo? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Exerccios: novos testes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Para saber mais: Import Esttico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Mais exerccios opcionais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Discusso em aula: testes so importantes? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
{ Trabalhando com XML :
. Os dados da bolsa de valores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. O formato XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Lendo XML com Java de maneira difcil, o SAX . . . . . . . . . . . . . . . . . . . . . . . . . . .
i
. XStream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Exerccios: Lendo o XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Discusso em aula: Onde usar XML e o abuso do mesmo . . . . . . . . . . . . . . . . . . . . . .
Test Driven Design - TDD o
. Separando as candles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Vantagens do TDD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Exerccios: Identicando negociaes do mesmo dia . . . . . . . . . . . . . . . . . . . . . . . .
. Exerccios: Separando os candles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Exerccios opcionais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
o Acessando um Web Service ,i
. Integrao entre sistemas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Consumindo dados de um Web Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Criando o cliente Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Exerccios: Nosso cliente Web Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Discusso em aula: Como testar o cliente do web service? . . . . . . . . . . . . . . . . . . . . .
, Introduo ao JSF e Primefaces ,8
. Interfaces grcas para o usurio - GUI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. O cliente gordo e o desenvolvimento Desktop . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. O desenvolvimento Web e o protocolo HTTP . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Mesclar desenvolvimento Desktop e Web . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Especicao e implementao do JSF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Introduo ao JSF com Mojarra e PrimeFaces . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Preparao do ambiente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Exerccios: Instalando o Tomcat e criando o projeto . . . . . . . . . . . . . . . . . . . . . . . . .
. A primeira pgina com JSF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Exerccios: Os primeiros componentes JSF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Listagem de Negociaes com Primefaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Cdigo atrs da tela - Managed Beans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Formatao de Data com JSF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Paginao e Ordenao das negociaes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Exerccios: p:dataTable para listar as Negociaes do Web Service . . . . . . . . . . . . . . . . .
. O Padro Model View Controller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8 Refatorao: os Indicadores da bolsa :o8
. Anlise Tcnica da bolsa de valores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Indicadores Tcnicos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. As mdias mveis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Exerccios: criando indicadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Refatorao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Exerccios: Primeiras refatoraes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
ii
. Refatoraes maiores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Discusso em aula: quando refatorar? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Grhcos interativos com Primefaces :i
. Por que usar grcos? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Exemplos de Grcos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Utilizando o Primefaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Propriedades para personalizar o grco . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Denio do modelo do grco . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Isolando a API do Primefaces: baixo acoplamento . . . . . . . . . . . . . . . . . . . . . . . . . .
. Para saber mais: Design Patterns Factory Method e Builder . . . . . . . . . . . . . . . . . . . .
. Exerccios: Grcos com Primefaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
:o Aplicando Padres de projeto :o
. Nossos indicadores e o design pattern Strategy . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Exerccios: refatorando para uma interface e usando bem os testes . . . . . . . . . . . . . . . .
. Exerccios opcionais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Indicadores mais Elaborados e o Design Pattern Decorator . . . . . . . . . . . . . . . . . . . . .
. Exerccios: Indicadores mais espertos e o Design Pattern Decorator . . . . . . . . . . . . . . .
:: Formulrios com JSF :{o
. Melhorando a Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Componentes de entrada . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Submetendo o formulrio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Validao com JSF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Organizao dos componentes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Exerccios: Executando lgica e validando entrada . . . . . . . . . . . . . . . . . . . . . . . . . .
. ComboBox para selecionar os indicadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Exerccios: Completando o Formulrio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
:i API de Reection :8
. Montando os indicadores dinamicamente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Introduo a Reection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Por que Reection? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Constructor, Field e Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Melhorando nosso ArgentumBean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Exerccios: Plotando indicadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
: Apndice Testes de interface com Selenium :,i
. Introduo ao teste de aceitao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Como funciona? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Trabalhando com diversos testes de aceitao . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Para saber mais: Congurando o Selenium em casa . . . . . . . . . . . . . . . . . . . . . . . . .
iii
. Exerccios: Teste com Selenium . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
ndice Remissivo :8o
Verso: :o.o.o
iv
C
Tornando-se um desenvolvedor pragmtico
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
Por que fazer esse curso?
:.: Oqcv v nvntmvN1v :mvon1nN1v:
Voc j passou pelo FJ- e, quem sabe, at pelo FJ-. Agora chegou a hora de codicar bastante para pegar
os truques e hbitos que so os grandes diferenciais do programador Java experiente.
Pragmtico aquele que se preocupa com as questes prticas, menos focado em ideologias e tentando
colocar a teoria pra andar.
Esse curso temcomo 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
emsi no so os pontos mais importantes do aprendizado neste momento, mas simas 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 anco.
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////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 inuenciaram muito na elabo-
rao do contedo que queremos transmitir a vocs. Todos os cinco so:
Eective Java, Joshua Bloch 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 enfren-
tar os principais problemas e limitaes da linguagem. Uma excelente leitura, dividido em mais de
tpicos de a 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.
DesignPatterns, ErichGamma et al Livro de Erich Gamma, por muito tempo lder do projeto Eclipse
na IBM, e mais outros trs autores, o que justica terem o apelido de Gang of Four (GoF). Uma ex-
celente 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:Evite herana, prera composio e Programe voltado s interfaces
e no implementao.
Refactoring, Martin Fowler Livro do cientista chefe da oughtWorks. 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 emvez de polimorsmo, entre dezenas de outros. Durante
o curso, faremos diversos refactoring clssicos utilizando do Eclipse, muito mais que o bsico rename.
Pragmatic Programmer, AndrewHunt As melhores prticas para ser umbomdesenvolvedor: desde
o uso de versionamento, ao bom uso do logging, debug, nomenclaturas, como consertar bugs, etc.
e mythical man-month, Frederick Brooks Um livro que fala dos problemas que encontramos
no dia a dia do desenvolvimento de soware, numa abordagem mais gerencial. Aqui h, inclusive, o
clssico artigo No Silver Bullet, que arma 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.
:.i A :mvon1XNc:n oos vxvncc:os
um tanto desnecessrio debater sobre a importncia de fazer exerccios, porm neste curso especco eles
so vitais: como ele focado em boas prticas, alguma parte da teoria no est no texto - e passado no
decorrer de exerccios.
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 grco de candlesticks, utilizando diversas APIs do Java SE e
at mesmo bibliotecas externas.
Captulo - Tornando-se um desenvolvedor pragmtico - A importncia dos exerccios - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
:. T:nnNoo ov:ons v nvvvnINc:ns
Para tirar dvidas dos exerccios, ou de Java em geral, recomendamos o frum do site do GUJ (http://www.
guj.com.br/), onde sua dvida ser respondida prontamente.
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/
:.{ Pnnn oNov :n ovvo:s:
Se voc se interessou pelos testes, design e automao, recomendamos os cursos online de testes da Caelum:
http://www.caelum.com.br/curso/online/testes-automatizados/
O FJ- 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- aborda Hibernate e JPA e o FJ- envolve JSF , Facelets e CDI. Ambos vo passar por tecnologias
hoje bastante utilizadas no desenvolvimento server side para web, e j na verso do Java EE .
Captulo - Tornando-se um desenvolvedor pragmtico - Tirando dvidas e referncias - Pgina
C
O modelo da bolsa de valores, datas e objetos
imutveis
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- 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:
Eective Java, do Joshua Bloch, e Design Patterns: Elements of Reusable Object-Oriented Soware, de Erich
Gamma e outros (conhecido Gang of Four).
i.: A notsn ov vntonvs
Poucas atividades humanas exercem tanto fascnio quanto o mercado de aes, assunto abordado exaus-
tivamente em lmes, livros e em toda a cultura contempornea. Somente em novembro de , o total
movimentado pela BOVESPA foi de R , bilhes. Destes, o volume movimentado por aplicaes home
broker foi de R , bilhes.
Neste curso, abordaremos esse assunto que, hoje emdia, chega a ser cotidiano desenvolvendo uma aplicao
que interpreta os dados de um XML, trata e modela eles em Java e mostra grcos pertinentes.
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
i.i CnNotvs1:cs: O JnvXo v o nnnoz
Yodoya Keian era um mercador japons do sculo . Ele se tornou rapidamente muito rico, dadas as suas
habilidades de transporte e precicao do arroz, uma mercadoria em crescente produo em consumo no
pas. Sua situao social de mercador no permitia que ele fosse to rico dado o sistema de castas da poca e,
logo, o governo conscou todo seu dinheiro e suas posses. Depois dele, outros vieram e tentaram esconder
suas origens como mercadores: muitos tiveram seus lhos executados e seu dinheiro conscado.
Apesar da triste histria, foi em Dojima, no jardim do prprio Yodoya Keian, que nasceu a bolsa de arroz
do Japo. L eram negociados, precicados e categorizados vrios tipos de arroz. Para anotar os preos do
arroz, desenhava-se guras no papel. Essas guras 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 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.
Para calcular as informaes necessrias para a construo de um Candlestick, so necessrios os dados de
todos as negociaes (trades) de um dia. Uma Negociao possui trs informaes: o preo pelo qual foi
comprado, a quantidade de ativos e a data em que ele foi executado.
Voc pode ler mais sobre a histria dos candles em: http://www.candlestickforum.com/PPF/Parameters/_
_/candlestick.asp
Captulo - O modelo da bolsa de valores, datas e objetos imutveis - Candlesticks: O Japo e o arroz - Pgina
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 minutos, ou uma semana, depen-
dendo se voc est analisando o ativo para curto, mdio ou longo prazo.
i. Ovno)v1o Tn:t
A ideia do projeto Tail (Technical Analysis Indicator Library) nasceu quando um grupo de alunos da Uni-
versidade de So Paulo procurou o professor doutor Alfredo Goldman para orient-los no desenvolvimento
de um soware para o projeto de concluso de curso.
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 deniu o tema: o desenvolvimento de um soware open source de anlise tcnica
grasta (veremos o que a anlise tcnica em captulos posteriores).
O soware est disponvel no SourceForge:
http://sourceforge.net/projects/tail/
Captulo - O modelo da bolsa de valores, datas e objetos imutveis - O projeto Tail - Pgina
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.
Objetivos do projeto Tail:
Implementar os componentes bsicos da anlise tcnica grasta: 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;
Implementar um algoritmo genrico para determinar um momento apropriado de compra e venda de
um ativo, atravs da escolha da melhor estratgia aplicada a uma srie temporal;
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 grca, 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, como objetivo de ser facilmente escalvel e de simples entendimento;
Utilizar prticas de XP, adaptando-as conforme as necessidades do grupo.
Manter a cobertura de testes superior a ;
Analisar o funcionamento do sistema de coorientao, como objetivo estend-lo para projetos futuros.
Captulo - O modelo da bolsa de valores, datas e objetos imutveis - O projeto Tail - Pgina
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, iago Garutti ies, Paulo Silveira (mestre em Geometria Computacional pela USP e diretor da Cae-
lum), Julian Monteiro (mestre emsistemas distribudos pela USP e doutor pelo INRIA, emSophia Antipolis,
Frana) e Danilo Sato (mestre em Metodologias geis pela USP e Lead Consultant na oughtWorks).
Esse projeto foi a primeira parceria entre a Caelum e a USP, onde a Caelum patrocinou o trabalho de con-
cluso de curso dos 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/
i.{ Ovno)v1o AncvN1cm: moovtnNoo o s:s1vmn
Oprojeto Tail bastante ambicioso. Temcentenas de recursos, emespecial o de sugesto de quando comprar
e de quando vender aes. O interessante durante o desenvolvimento do projeto Tail foi que muitos dos
bons princpios de orientao a objetos, engenharia de soware, design patterns e Programao eXtrema se
encaixaram muito bem - por isso, nos inspiramos fortemente nele como base para o FJ-.
Queremos modelar diversos objetos do nosso sistema, entre eles teremos:
Negociao - guardando preo, quantidade e data;
Candlestick - guardando as informaes do Candle, alm do volume de dinheiro negociado;
SerieTemporal - que guarda um conjunto de candles.
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:
Resumir Negociacoes em Candlesticks.Nossa base sero as negociaes. Precisamos converter uma
lista de negociaes em uma lista de Candles.
Converter Candlesticks em SerieTemporal.Dada uma lista de Candle, precisamos criar uma srie
temporal.
Utilizar indicadores tcnicosPara isso, implementar um pequeno framework de indicadores e criar
alguns deles de forma a facilitar o desenvolvimento de novos.
Gerar grcosEmbutveis e interativos na interface grca em Java, dos indicadores que criamos.
Para comear a modelar nosso sistema, precisamos entender alguns recursos de design de classes que ainda
no foram discutidos no FJ-. 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.
Captulo - O modelo da bolsa de valores, datas e objetos imutveis - O projeto Argentum: modelando o sistema - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
i. TnnnntnnNoo como:Nnv:no
At agora, no paramos muito para pensar nos tipos das nossas variveis e j ganhamos o costume de auto-
maticamente atribuir valores a variveis double. Essa , contudo, uma prtica bastante perigosa!
O problema do double que no possvel especicar 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:
double cem = 100.0;
double tres = 3.0;
double resultado = cem / tres;
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.
Leia mais sobre ela na prpria documentao do Java.
i.o Pntnvnn cnnvv v:Nnt
A palavra chave final tem vrias utilidades. Em uma classe, dene que a classe nunca poder ter uma lha,
isso , no pode ser estendida. A classe String, por exemplo, final.
Como modicador de mtodo, final indica que aquele mtodo no pode ser reescrito. Mtodos muito
importantes costumam ser denidos assim. Claro que isso no necessrio declarar caso sua classe j seja
final.
Ao usarmos como modicador 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 modicado:
class Negociacao {
private final double valor;
// getters e setters?
}
Captulo - O modelo da bolsa de valores, datas e objetos imutveis - Trabalhando com dinheiro - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Esse cdigo no compila, nem mesmo com um setter, pois o valor nal 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 {
private final double valor;
public Negociacao(double valor) {
this.valor = valor;
}
// podemos ter um getter, mas nao um setter aqui!
}
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 sejamdeclaradas 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 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 nais e tambm marcarmos a prpria
classe como nal para que ela crie apenas objetos imutveis.
i., Imc1nn:t:onov ov on)v1os
Evvvc1:vv Jnvn
Item : Minimize mutabilidade
Para que uma classe seja imutvel, ela precisa ter algumas caractersticas:
Nenhum mtodo pode modicar seu estado;
A classe deve ser final;
Os atributos devem ser privados;
Os atributos devem ser final, apenas para legibilidade de cdigo, j que no h mtodos que modi-
cam o estado do objeto;
Captulo - O modelo da bolsa de valores, datas e objetos imutveis - Imutabilidade de objetos - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
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:
Qual seria a motivao de criar uma classe de tal maneira?
On)v1os voovmcomvnn1:tnnn scns comvos:ovs
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.
Isso pode ser encarado como o famoso design pattern Flyweight.
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!
String palavra = "supercalifragilisticexpialidocious";
String inicio = palavra.substring(0, 5);
String proximas = palavra.substring(5, 10);
String outras = palavra.substring(10, 15);
String resto = palavra.substring(15);
Esses objetos tambm so ideais para usar como chave de tabelas de hash.
Tnnvno snvv1v
Uma das principais vantagens da imutabilidade em relao a concorrncia. Simplesmente no precisamos
nos preocupar em relao a isso: como no h mtodo que mude o estado do objeto, ento no h como
fazer duas modicaes acontecerem concorrentemente!
Captulo - O modelo da bolsa de valores, datas e objetos imutveis - Imutabilidade de objetos - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
On)v1os mn:s s:mvtvs
Uma classe imutvel mais simples de dar manuteno. Como no h chances de seu objeto ser modicado,
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 modicao.
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.
i.8 TnnnntnnNoo comon1ns: Dn1v v CntvNonn
Se voc fez o FJ- conosco, j teve que lidar com as converses entre Date e Calendar para pegar a entrada
de data de um texto digitado pelo usurio e convert-lo para um objeto que representa datas em Java.
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 //.
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 . pelo
Calendar, para haver suporte correto internacionalizao e localizao do sistema de datas.
CntvNonn: vvotcXo oo Dn1v
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.
Asubclasse 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.
Para obter um Calendar que encapsula o instante atual (data e hora), usamos o mtodo esttico
getInstance() de Calendar.
Captulo - O modelo da bolsa de valores, datas e objetos imutveis - Trabalhando com datas: Date e Calendar - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Calendar agora = Calendar.getInstance();
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 congurado na mquina.
Evvvc1:vv Jnvn
Item : Considere utilizar Factory com mtodos estticos em vez de construtores
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):
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
No exemplo acima, o dia da semana representa a quinta-feira.
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 emCalendar. Omais 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
Captulo - O modelo da bolsa de valores, datas e objetos imutveis - Trabalhando com datas: Date e Calendar - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
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:
Calendar c1 = new GregorianCalendar(2005, Calendar.OCTOBER, 12);
Calendar c2 = new GregorianCalendar(2005, Calendar.DECEMBER, 25);
System.out.println(c1.after(c2));
Analogamente, o mtodo before verica 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.
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 vericar 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:
public int diferencaEmDias(Calendar c1, Calendar c2) {
long m1 = c1.getTimeInMillis();
long m2 = c2.getTimeInMillis();
return (int) ((m2 - m1) / (24*60*60*1000));
}
Captulo - O modelo da bolsa de valores, datas e objetos imutveis - Trabalhando com datas: Date e Calendar - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Rvtnc:oNnNoo Dn1v v CntvNonn
Voc pode pegar umDate de umCalendar e vice-versa atravs dos mtodos getTime e setTime presentes na
classe Calendar:
Calendar c = new GregorianCalendar(2005, Calendar.OCTOBER, 12);
Date d = c.getTime();
c.setTime(d);
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).
Pnnn snnvn mn:s: Ctnssvs Dvvnvcn1vo v o JoonT:mv
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 denitivamente 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 comcdigos existen-
tes, o Java mantm as funcionalidades problemticas ainda na plataforma, mesmo que uma soluo melhor
exista.
Mas como desencorajar cdigos novos a usaremfuncionalidades antigas e no mais recomendadas? Aprtica
no Java para isso marc-las como deprecated. Isso indica aos programadores que no devemos mais us-las
e que futuramente, emuma verso mais nova do Java, podemsair da API (embora isso nunca tenha ocorrido
na prtica).
Antes do Java , para falar que algo era deprecated, usava-se um comentrio especial no Javadoc. A partir
do Java , a anotao @Deprecated foi adicionada plataforma e garante vericaes 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 especicao do Java, baseadas na excelente biblioteca JodaTime.
Para mais informaes: http://blog.caelum.com.br////jsr--date-and-time-api/ http://jcp.org/en/
jsr/detail?id=
i. Exvncc:os: o moovto oo AncvN1cm
) Vamos criar o projeto fj22-argentum no Eclipse, j com o foco em usar a IDE melhor: use o atalho ctrl
+ N, que cria novo... e comece a digitar Java Project:
Captulo - O modelo da bolsa de valores, datas e objetos imutveis - Exerccios: o modelo do Argentum - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
) Na janela que abrir em sequncia, preencha o nome do projeto como ii-argentum e clique em Next:
) Na prxima tela, podemos denir uma srie de conguraes do projeto (que tambm podem ser feitas
depois, atravs do menu Build path -> Congure 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.
Nessa tela, remova o diretrio src da lista de diretrios fonte:
Captulo - O modelo da bolsa de valores, datas e objetos imutveis - Exerccios: o modelo do Argentum - Pgina
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:
) Agora basta clicar em Finish. A estrutura nal de seu projeto deve estar parecida com isso:
Captulo - O modelo da bolsa de valores, datas e objetos imutveis - Exerccios: o modelo do Argentum - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
) Crie a classe usando ctrl + N Class, chamada Negociacao e dentro do pacote
br.com.caelum.argentum.modelo:
) Transforme a classe em hnal e j declare os trs atributos que fazem parte de uma negociao da bolsa de
valores (tambm como nal):
public final class Negociacao {
private final double preco;
private final int quantidade;
private final Calendar data;
}
Captulo - O modelo da bolsa de valores, datas e objetos imutveis - Exerccios: o modelo do Argentum - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
No esquea de importar o Calendar!
) 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 + e comece a digitar constructor. Ele vai
mostrar uma lista das opes que contm essa palavra: escolha a Generate constructor using elds.
Alternativamente, tecle ctrl + 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.
Pronto! Mande gerar. O seguinte cdigo que ser gerado:
public Negociacao(double preco, int quantidade, Calendar data) {
this.preco = preco;
this.quantidade = quantidade;
this.data = data;
}
Captulo - O modelo da bolsa de valores, datas e objetos imutveis - Exerccios: o modelo do Argentum - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
) Agora, vamos gerar os getters dessa classe. Faa ctrl + e comece a digitar getter, as opes aparecero e
basta voc escolher generate getters and setters. sempre bom praticar os atalhos do ctrl + .
Selecione os getters e depois Finish:
) Verique sua classe. Ela deve estar assim:
public final class Negociacao {
private final double preco;
private final int quantidade;
private final Calendar data;
public Negociacao(double preco, int quantidade, Calendar data) {
this.preco = preco;
this.quantidade = quantidade;
this.data = data;
}
public double getPreco() {
return preco;
}
public int getQuantidade() {
return quantidade;
}
public Calendar getData() {
Captulo - O modelo da bolsa de valores, datas e objetos imutveis - Exerccios: o modelo do Argentum - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
return data;
}
}
) 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.
Adicione o mtodo getVolume na classe Negociacao:
public double getVolume() {
return preco * quantidade;
}
Repare que um mtodo que parece ser um simples getter pode (e deve muitas vezes) encapsular regras de
negcio e no necessariamente reetem um atributo da classe.
) Siga o mesmo procedimento para criar a classe Candlestick. Use o ctrl + N Class para isso, marque-a
como hnal e adicione os seguintes atributos hnais, 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;
}
) Use o ctrl + para gerar o construtor com os seis atributos. Ateno ordem dos parmetros no cons-
trutor:
Captulo - O modelo da bolsa de valores, datas e objetos imutveis - Exerccios: o modelo do Argentum - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
) Gere tambm os seis respectivos getters, usando o ctrl + .
A classe nal deve car parecida com a que segue:
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;
public Candlestick(double abertura,double fechamento,double minimo,
double maximo, double volume, Calendar data) {
this.abertura = abertura;
this.fechamento = fechamento;
this.minimo = minimo;
this.maximo = maximo;
this.volume = volume;
this.data = data;
}
public double getAbertura() {
return abertura;
}
public double getFechamento() {
return fechamento;
}
public double getMinimo() {
Captulo - O modelo da bolsa de valores, datas e objetos imutveis - Exerccios: o modelo do Argentum - Pgina
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;
}
}
) (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;
}
public boolean isBaixa() {
return this.abertura > this.fechamento;
}
i.:o Rvscmo o:Kn:o ons Nvcoc:novs
Agora que temos as classes que representamnegociaes na bolsa de valores (Negociacao) e resumos dirios
dessas negociaes (Candlestick), falta apenas fazer a ao de resumir as negociaes de um dia em uma
candle.
A regra um tanto simples: dentre uma lista de negociaes, precisamos descobrir quais so os valores a
preencher na Candlestick:
Abertura: preo da primeira negociao do dia;
Fechamento: preo da ltima negociao do dia;
Mnimo: preo da negociao mais barata do dia;
Mximo: preo da negociao mais cara do dia;
Volume: quantidade de dinheiro que passou em todas as negociaes nesse dia;
Data: a qual dia o resumo se refere.
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 vemordenada por tempo. Dessa forma, a abertura e o fechamento
Captulo - O modelo da bolsa de valores, datas e objetos imutveis - Resumo dirio das Negociaes - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
so triviais: basta recuperar o preo , respectivamente, da primeira e da ltima negociaes do dia!
J mnimo, mximo e volume precisam que todos os valores sejam vericados. Dessa forma, precisamos
passar por cada negociao da lista vericando 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 especicado! Basta passarmos essas ideias para cdigo. Para isso,
lembremos, voc pode usar alguns atalhos que j vimos antes:
Ctrl + N: cria novo(a)...
Ctrl + espao: autocompleta
Ctrl + :: resolve pequenos problemas de compilao e atribui objetos a variveis.
Emqcv ctnssv cotocnn:
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 ca
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-.
i.:: Exvncc:os: vKnn:cn ov CnNotvs1:c
) Como o resumo de Negociacoes em um Candlestick um processo complicado, vamos encapsular sua
construo atravs de uma fbrica, assim como vimos a classe Calendar, porm o mtodo de fabricao
car numa classe a parte, o que tambm muito comum. Vamos criar a classe CandlestickFactory
dentro do pacote br.com.caelum.argentum.modelo:
Captulo - O modelo da bolsa de valores, datas e objetos imutveis - Exerccios: fbrica de Candlestick - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Depois de cri-la, adicione a assinatura do mtodo constroiCandleParaData como abaixo:
public class CandlestickFactory {
// ctrl + 1 para adicionar o return automaticamente
public Candlestick constroiCandleParaData(Calendar data,
List<Negociacao> negociacoes) {
}
}
) Calcularemos o preo mximo e mnimo percorrendo todas as negociaes e achando os valores corre-
tos. Para isso, usaremos variveis temporrias e, dentro do for, vericaremos se o preo da negociao
atual bate ou mximo. Se no bater, veremos se ele menor que o mnimo. Calculamos o volume so-
mando o volume de cada negociao em uma varivel. Podemos pegar o preo de abertura atravs de
negociacoes.get(0) e o de fechamento por negociacoes.get(negociacoes.size() - 1).
public class CandlestickFactory {
public Candlestick constroiCandleParaData(Calendar data,
List<Negociacao> negociacoes) {
double maximo = negociacoes.get(0).getPreco();
double minimo = negociacoes.get(0).getPreco();
double volume = 0;
Captulo - O modelo da bolsa de valores, datas e objetos imutveis - Exerccios: fbrica de Candlestick - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
// digite foreach e d um ctrl + espao para ajudar a
// criar o bloco abaixo!
for (Negociacao negociacao : negociacoes) {
volume += negociacao.getVolume();
if (negociacao.getPreco() > maximo) {
maximo = negociacao.getPreco();
} else if (negociacao.getPreco() < minimo) {
minimo = negociacao.getPreco();
}
}
double abertura = negociacoes.get(0).getPreco();
double fechamento = negociacoes.get(negociacoes.size()-1).getPreco();
return new Candlestick(abertura, fechamento, minimo, maximo,
volume, data);
}
}
) Vamos testar nosso cdigo, criando negociaes e calculando o Candlestick, nalmente. Crie a classe
TestaCandlestickFactory no pacote br.com.caelum.argentum.testes
public class TestaCandlestickFactory {
public static void main(String[] args) {
Calendar hoje = Calendar.getInstance();
Negociacao negociacao1 = new Negociacao(40.5, 100, hoje);
Negociacao negociacao2 = new Negociacao(45.0, 100, hoje);
Negociacao negociacao3 = new Negociacao(39.8, 100, hoje);
Negociacao negociacao4 = new Negociacao(42.3, 100, hoje);
List<Negociacao> negociacoes = Arrays.asList(negociacao1, negociacao2,
negociacao3, negociacao4);
CandlestickFactory fabrica = new CandlestickFactory();
Candlestick candle = fabrica.constroiCandleParaData(
hoje, negociacoes);
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());
Captulo - O modelo da bolsa de valores, datas e objetos imutveis - Exerccios: fbrica de Candlestick - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
}
}
O mtodo asList da classe java.util.Arrays cria uma lista dada uma array. Mas no passamos
nenhuma 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.
Evvvc1:vv Jnvn
Item : Conhea e use as bibliotecas!
A sada deve ser parecida com:
40.5
42.3
39.8
45.0
16760.0
i.:i Exvncc:os ovc:oNn:s
)
Evvvc1:vv Jnvn
Item : 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.
) Umdouble segue uma regra bemdenida emrelao a contas e arredondamento, e para ser rpido e caber
em bits, no tem preciso innita. A classe BigDecimal pode oferecer recursos mais interessantes em
um ambiente onde as casas decimais so valiosas, como um sistema nanceiro. Pesquise a respeito.
Captulo - O modelo da bolsa de valores, datas e objetos imutveis - Exerccios opcionais - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
) O construtor da classe Candlestick simplesmente muito grande. Poderamos usar uma factory, porm
continuaramos passando muitos argumentos para um determinado mtodo.
Quando construir umobjeto complicado, ou confuso, costumamos usar o padro Builder para resolver
isso. Builder uma classe que ajudar voc a construir um determinado objeto em uma srie de passos,
independente de ordem.
Evvvc1:vv Jnvn
Item : Considere usar um builder se o construtor tiver muitos parmetros!
A ideia que possamos criar um candle da seguinte maneira:
CandleBuilder builder = new CandleBuilder();
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));
Candlestick candle = builder.geraCandle();
Os setters aqui possuem nomes mais curtos e expressivos. Mais ainda: utilizando o padro de projeto
uent 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();
Para isso, a classe CandleBuilder deve usar o seguinte idiomismo:
public class CandleBuilder {
private double abertura;
// outros 5 atributos
public CandleBuilder comAbertura(double abertura) {
this.abertura = abertura;
return this;
}
// outros 5 setters que retornam this
Captulo - O modelo da bolsa de valores, datas e objetos imutveis - Exerccios opcionais - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
public Candlestick geraCandle() {
return new Candlestick(abertura, fechamento, minimo, maximo,
volume, data);
}
}
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 uent interface e
mtodos auxiliares.
Usos vnmosos ov FtcvN1 IN1vnvncv v DSLs
Fluent interfaces so muito usadas no Hibernate, por exemplo. O jQuery, uma famosa biblioteca
de efeitos javascript, popularizou-se por causa de sua uent interface. O JodaTime e o JMock so
dois excelentes exemplos.
So muito usadas (e recomendadas) na construo de DSLs, Domain Specic Languages. Martin
Fowler fala bastante sobre uent interfaces nesse timo artigo:
http://martinfowler.com/bliki/FluentInterface.html
Captulo - O modelo da bolsa de valores, datas e objetos imutveis - Exerccios opcionais - Pgina
C
Testes Automatizados
Apenas duas coisas so innitas: o universo e a estupidez humana. E eu no tenho certeza do primeiro.
Albert Einstein
.: Nosso coo:co vs1K vcNc:oNnNoo connv1nmvN1v:
Escrevemos uma quantidade razovel de cdigo no captulo anterior, meia dzia de classes. Elas funcionam
corretamente? Tudo indica que sim, at criamos um pequeno main para vericar isso e fazer as perguntas
corretas.
Pode parecer que o cdigo funciona, mas ele tem muitas falhas. Olhemos com mais cuidado.
.i Exvncc:os: 1vs1nNoo Nosso moovto svmvnnmvwons
) Ser que nosso programa funciona para um determinado dia que ocorrer apenas uma nica negociao?
Vamos escrever o teste, e ver o que acontece:
public class TestaCandlestickFactoryComUmaNegociacaoApenas {
public static void main(String[] args) {
Calendar hoje = Calendar.getInstance();
Negociacao negociacao1 = new Negociacao(40.5, 100, hoje);
List<Negociacao> negociacoes = Arrays.asList(negociacao1);
CandlestickFactory fabrica = new CandlestickFactory();
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Candlestick candle = fabrica.constroiCandleParaData(hoje, negociacoes);
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?
) Mais um teste: as aes menos negociadas podem car dias sem nenhuma operao acontecer. O que
nosso sistema gera nesse caso?
Vamos ao teste:
public class TestaCandlestickFactorySemNegociacoes {
public static void main(String[] args) {
Calendar hoje = Calendar.getInstance();
List<Negociacao> negociacoes = Arrays.asList();
CandlestickFactory fabrica = new CandlestickFactory();
Candlestick candle = fabrica.constroiCandleParaData(hoje, negociacoes);
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?
) ArrayIndexOutOfBoundsException certamente uma pssima exceo para indicar que no teremos
Candle.
Captulo - Testes Automatizados - Exerccios: testando nosso modelo sem frameworks - Pgina
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 signicado especial. Devolver null deve ser sempre
a ltima opo.
Vamos retornar umCandlestick que possui umvolume zero. Para corrigir o erro, vamos alterar o cdigo
do nosso CandlestickFactory.
Poderamos usar um if logo de cara para vericar 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 minimo com um valor bem grande, assim quando
percorrermos o for qualquer valor j vai ser logo minimo. Mesmo com maximo, que deve ter um valor
bem pequeno.
Mas quais valores colocar? Quanto um nmero pequeno o suciente? Ou um nmero grande o su-
ciente? Na classe Double, encontramos constantes que representam os maiores e menores nmeros exis-
tentes.
Altere o mtodo constroiCandleParaData da classe CandlestickFactory:
double maximo = Double.MIN_VALUE;
double minimo = Double.MAX_VALUE;
Alm disso, devemos vericar se negociacoes est vazia na hora de calcular o preo de abertura e
fechamento. Altere novamente o mtodo:
double abertura = negociacoes.isEmpty() ? 0 : negociacoes.get(0).getPreco();
double fechamento = negociacoes.isEmpty() ? 0 :
negociacoes.get(negociacoes.size() - 1).getPreco();
Pronto! Rode o teste, deve vir tudo zero e nmeros estranhos para mximo e mnimo!
) 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!
O teste com apenas uma negociao retorna .E como valor mnimo agora! Mas
deveria ser .. Ainda bem que lembramos de rodar essa classe, e que percebemos que esse nmero est
diferente do que deveria ser.
Vamos sempre conar em nossa memria?
) (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);
Captulo - Testes Automatizados - Exerccios: testando nosso modelo sem frameworks - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Negociacao negociacao3 = new Negociacao(49.8, 100, hoje);
Negociacao negociacao4 = new Negociacao(53.3, 100, hoje);
E com uma sequncia decrescente, funciona? Por qu?
. Dvv:N:Noo mvtnon o s:s1vmn v ovsconn:Noo mn:s nccs
Segue uma lista de dvidas pertinentes ao Argentum. Algumas dessas perguntas voc no saber respon-
der, porque no denimos muito bem o comportamento de alguns mtodos e classes. Outras voc saber
responder.
De qualquer maneira, crie um cdigo curto para testar cada uma das situaes, em um main apropriado.
) Uma negociao da Petrobras a 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?
) Uma negociao com data nula vlida? Posso dar new Negociacao(10, 5, null)? Deveria poder?
) Um candle realmente imutvel? No podemos mudar a data de um candle de maneira alguma?
) 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?
) Como geramos um candle de um dia que no houve negociao? O que acontece?
) E se a ordemdas negociaes passadas ao CandlestickFactory no estiver na ordemcrescente das datas?
Devemos aceitar? No devemos?
) E se essas Negociaes forem de dias diferentes que a data passada como argumento para a factory?
.{ Tvs1vs ov UN:onov
Testes de unidade so testes que testam apenas uma classe ou mtodo, vericando se seu comportamento
est de acordo com o desejado. Em testes de unidade, vericamos a funcionalidade da classe e/ou mtodo
em questo passando o mnimo possvel por outras classes ou dependncias do nosso sistema.
UN:onov
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.
Captulo - Testes Automatizados - Denindo melhor o sistema e descobrindo mais bugs - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Emtestes 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
modicou 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 denimos o resultado
que esperamos. Se o resultado for igual ao que denimos como esperado, o teste passa. Caso contrrio, falha.
A1vNXo
Muitas vezes, principalmente quandoestamos iniciandono mundo dos testes, comumcriarmos
alguns testes que testam muito mais do que o necessrio, mais do que apenas a unidade. Tais
testes se transformamemverdadeiros testes de integrao (esses simso responsveis por testar
o sistemas como um todo).
Portanto, lembre-se sempre: testes de unidade testam apenas unidades!
. JUN:1
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 armao: 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 comumcomando
apenas. Com isso voc ganha a conana 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.
UsnNoo o JUN:1 - coNv:ccnnNoo Ctnssvn1n v svc JAR No Ect:vsv
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)
Captulo - Testes Automatizados - JUnit - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
aqui que o Classpath entra histria: nele que denimos 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.
H algumas formas de congurarmos o classpath:
Congurando uma varivel de ambiente (desaconselhado);
Passando como argumento em linha de comando (trabalhoso);
Utilizando ferramentas como Ant e Maven (veremos mais a frente);
Deixando o eclipse congurar por voc.
No Eclipse, muito simples:
) Clique com o boto direito em cima do nome do seu projeto.
) Escolha a opo Properties.
) Na parte esquerda da tela, selecione a opo Java Build Path.
E, nessa tela:
) Java Build Path onde voc congura o classpath do seu projeto: lista de locais denidos que, por
padro, s vm com a mquina virtual congurada;
) 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 grcos em captulos posteriores.
.o ANo1novs
Anotao a maneira de escrever metadados na prpria classe, isto , conguraes ou outras informaes
pertinentes a essa classe. Esse recurso foi introduzido no Java .. 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 conguraes 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.
Captulo - Testes Automatizados - Anotaes - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
@Deprecated indica que ummtodo no deve ser mais utilizado por algummotivo e decidiramno 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. Umexemplo o warning que o compilador
do Eclipse d quando voc no usa determinada varivel. Voc vai ver que um dos quick xes a sugesto
de usar o @SupressWarnings.
Anotaes podem receber parmetros. Existem muitas delas na API do java , mas realmente ainda mais
utilizada em frameworks, como o Hibernate , o EJB e o JUnit.
., JUN:1{, coNvvNovs v nNo1nXo
Para cada classe, teremos uma classe correspondente (por conveno, com o suxo Test) que contar todos
os testes relativos aos mtodos dessa classe. Essa classe car no pacote de mesmo nome, mas na Source
Folder de testes (src/test/java).
Por exemplo, para a nossa CandlestickFactory, teremos a CandlestickFactoryTest:
package br.com.caelum.argentum.modelo;
public class CandlestickFactoryTest {
public void sequenciaSimplesDeNegociacoes() {
Calendar hoje = Calendar.getInstance();
Negociacao negociacao1 = new Negociacao(40.5, 100, hoje);
Negociacao negociacao2 = new Negociacao(45.0, 100, hoje);
Negociacao negociacao3 = new Negociacao(39.8, 100, hoje);
Negociacao negociacao4 = new Negociacao(42.3, 100, hoje);
List<Negociacao> negociacoes = Arrays.asList(negociacao1, negociacao2,
negociacao3, negociacao4);
CandlestickFactory fabrica = new CandlestickFactory();
Candlestick candle = fabrica.constroiCandleParaData(hoje, negociacoes);
}
}
Emvez de ummain, criamos ummtodo comnome 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 reection, de que aquele mtodo deva ser
executado:
Captulo - Testes Automatizados - JUnit, convenes e anotao - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
public class CandlestickFactoryTest {
@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 vericao. Ela realizada atravs dos mtodos estticos da classe Assert, importada
do org.junit. Por exemplo, podemos vericar se o valor de abertura desse candle .:
Assert.assertEquals(40.5, candle.getAbertura(), 0.00001);
Oprimeiro 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:
expected <valor esperado> but was <o que realmente deu>
Docntv v :Nvxn1o
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.
OJUnit trata esse caso adicionando umterceiro argumento, que s necessrio quando comparamos valores
double ou oat. 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 sowares 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 nal do teste, agora com as devidas asseres, car assim:
public class CandlestickFactoryTest {
@Test
public void sequenciaSimplesDeNegociacoes() {
Calendar hoje = Calendar.getInstance();
Negociacao negociacao1 = new Negociacao(40.5, 100, hoje);
Captulo - Testes Automatizados - JUnit, convenes e anotao - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Negociacao negociacao2 = new Negociacao(45.0, 100, hoje);
Negociacao negociacao3 = new Negociacao(39.8, 100, hoje);
Negociacao negociacao4 = new Negociacao(42.3, 100, hoje);
List<Negociacao> negociacoes = Arrays.asList(negociacao1, negociacao2,
negociacao3, negociacao4);
CandlestickFactory fabrica = new CandlestickFactory();
Candlestick candle = fabrica.constroiCandleParaData(hoje, negociacoes);
Assert.assertEquals(40.5, candle.getAbertura(), 0.00001);
Assert.assertEquals(42.3, candle.getFechamento(), 0.00001);
Assert.assertEquals(39.8, candle.getMinimo(), 0.00001);
Assert.assertEquals(45.0, candle.getMaximo(), 0.00001);
Assert.assertEquals(1676.0, candle.getVolume(), 0.00001);
}
}
Existem ainda outras anotaes principais e mtodos importantes da classe Assert, que conheceremos no
decorrer da construo do projeto.
.8 Exvncc:os: m:cnnNoo os 1vs1vs oo mn:N vnnn JUN:1
) considerada boa prtica separar as classes de testes das classes principais. Para isso, normalmente se
cria um novo source folder apenas para os testes. Vamos fazer isso:
a) Ctrl + N e comece a digitar Source Folder at que o ltro a encontre:
b) Preencha com src/test/java e clique Finish:
Captulo - Testes Automatizados - Exerccios: migrando os testes do main para JUnit - Pgina
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.
) 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
JUnit{.
Captulo - Testes Automatizados - Exerccios: migrando os testes do main para JUnit - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Ao clicar em Finish, o Eclipse te perguntar se pode adicionar os jars do JUnit no projeto.
Aanotao @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.
Vamos colocar primeiro o teste inicial:
public class CandlestickFactoryTest {
@Test
public void sequenciaSimplesDeNegociacoes() {
Calendar hoje = Calendar.getInstance();
Negociacao negociacao1 = new Negociacao(40.5, 100, hoje);
Negociacao negociacao2 = new Negociacao(45.0, 100, hoje);
Negociacao negociacao3 = new Negociacao(39.8, 100, hoje);
Negociacao negociacao4 = new Negociacao(42.3, 100, hoje);
List<Negociacao> negociacoes = Arrays.asList(negociacao1, negociacao2,
negociacao3, negociacao4);
CandlestickFactory fabrica = new CandlestickFactory();
Candlestick candle = fabrica.constroiCandleParaData(hoje, negociacoes);
Assert.assertEquals(40.5, candle.getAbertura(), 0.00001);
Assert.assertEquals(42.3, candle.getFechamento(), 0.00001);
Assert.assertEquals(39.8, candle.getMinimo(), 0.00001);
Assert.assertEquals(45.0, candle.getMaximo(), 0.00001);
Assert.assertEquals(1676.0, candle.getVolume(), 0.00001);
}
}
Para rodar, use qualquer um dos seguintes atalhos:
ctrl + F::: roda o que estiver aberto no editor;
Captulo - Testes Automatizados - Exerccios: migrando os testes do main para JUnit - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
alt + shi + X (solte) T: roda testes do JUnit.
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:
O nmero correto mesmo :o,oo.o. Adicione esse zero na classe de teste e rode-o novamente:
comum digitarmos errado no teste e o teste falhar, por isso, importante sempre vericar a corretude
do teste, tambm!
) 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() {
Captulo - Testes Automatizados - Exerccios: migrando os testes do main para JUnit - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Calendar hoje = Calendar.getInstance();
List<Negociacao> negociacoes = Arrays.asList();
CandlestickFactory fabrica = new CandlestickFactory();
Candlestick candle = fabrica.constroiCandleParaData(hoje, negociacoes);
Assert.assertEquals(0.0, candle.getVolume(), 0.00001);
}
Rode o teste com o mesmo atalho.
) 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();
Negociacao negociacao1 = new Negociacao(40.5, 100, hoje);
List<Negociacao> negociacoes = Arrays.asList(negociacao1);
CandlestickFactory fabrica = new CandlestickFactory();
Candlestick candle = fabrica.constroiCandleParaData(hoje, negociacoes);
Assert.assertEquals(40.5, candle.getAbertura(), 0.00001);
Assert.assertEquals(40.5, candle.getFechamento(), 0.00001);
Assert.assertEquals(40.5, candle.getMinimo(), 0.00001);
Assert.assertEquals(40.5, candle.getMaximo(), 0.00001);
Assert.assertEquals(4050.0, candle.getVolume(), 0.00001);
}
Rode o teste. Repare no erro:
Captulo - Testes Automatizados - Exerccios: migrando os testes do main para JUnit - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Como consertar?
. Vntv n vvNn 1vs1nn ctnssvs ov moovto:
Faz todo sentido testar classes como a CandlestickFactory, j que existe um algoritmo nela, alguma lgica
que deve ser executada e h uma grande chance de termos esquecido algum comportamento para casos
incomuns - como vimos nos testes anteriores.
Mas as classes de modelo, Negociacao e Candlestick, tambm precisam ser testadas?
A resposta para essa pergunta um grande e sonoro sim! Apesar de serem classes mais simples elas tambm
tm comportamentos especcos como:
) as classes Negociacao e Candlestick devem ser imutveis, isto , no devemos ser capazes de alterar
nenhuma de suas informaes depois que o objeto criado;
) valores negativos tambm no deveriam estar presentes nas negociaes e candles;
) se voc fez o opcional CandleBuilder, ele no deveria gerar a candle se os valores no tiverem sido preen-
chidos;
) 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.
Captulo - Testes Automatizados - Vale a pena testar classes de modelo? - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
.:o Exvncc:os: Novos 1vs1vs
) A classe Negociacao realmente imutvel?
Vamos criar um novo Unit Test para a classe Negociacao. O processo o mesmo que zemos para o teste
da CandlestickFactory: abra a classe Negociacao no editor e faa Ctrl + N JUnit Test Case.
Lembre-se de alterar a Source Folder para src/test/java e selecionar o JUnit .
public class NegociacaoTest {
@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);
// ainda que eu tente mudar a data para 20...
n.getData().set(Calendar.DAY_OF_MONTH, 20);
// ele continua no dia 15.
Assert.assertEquals(15, n.getData().get(Calendar.DAY_OF_MONTH));
}
}
Voc pode rodar esse teste apenas, usando o atalho (alt + shi + 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.
Captulo - Testes Automatizados - Exerccios: novos testes - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
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.
Evvvc1:vv Jnvn
Item : Faa cpias defensivas quando necessrio.
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.
Captulo - Testes Automatizados - Exerccios: novos testes - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
L:s1ns v nnnnvs
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.
Os mtodos Collections.unmodifiableList(List) e outros ajudam bastante nesse trabalho.
) Podemos criar uma Negociacao com data nula? Por enquanto, podemos, mas no deveramos. Para que
outras partes do meu sistema no se surpreendammais 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?
A exceo padro no Java para cuidar de parmetros indesejveis a IllegalArgumentException ento,
em vez de criar uma nova com a mesma semntica, vamos us-la para isso.
Evvvc1:vv Jnvn
Item : Favorea o uso das excees padres!
Antes de fazer a modicao 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.
Adicione um novo mtodo naoCriaNegociacaoComDataNula na classe NegociacaoTest. Repare que
agora temos um argumento na anotao expected=IllegalArgumentException.class. Isso indica que,
para esse teste ser considerado um sucesso, uma exceo deve ser lanada daquele tipo. Caso contrrio
ser uma falha:
@Test(expected=IllegalArgumentException.class)
public void naoCriaNegociacaoComDataNula() {
new Negociacao(10, 5, null);
}
Rode os testes. Barrinha vermelha! J que ainda no vericamos o argumento na classe Negociacao e
ainda no lanamos a exceo:
Captulo - Testes Automatizados - Exerccios: novos testes - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
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;
}
Rode novamente os testes.
Captulo - Testes Automatizados - Exerccios: novos testes - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
) (opcional) Nosso teste para quando no h negociaes na CandlestickFactory est vericando apenas
se o volume zero. Ele tambm poderia vericar que os outros valores dessa candle so zero.
Modique o mtodo semNegociacoesGeraCandleComZeros e adicione os asserts faltantes de abertura,
fechamento, mnimo e mximo.
O teste vai parar de passar!
Corrija ele da mesma forma que resolvemos o problema para as variveis abertura e fechamento.
) (opcional) Um Candlestick pode ter preo mximo menor que o preo mnimo? No deveria.
Crie um novo teste, o CandlestickTest, da maneira que zemos com o Negociacao. boa prtica que
todos os testes da classe X se encontrem em XTest.
Dentro dele, crie o precoMaximoNaoPodeSerMenorQueMinimo e faa um new passando argumentos que
quebrem isso. O teste deve esperar pela IllegalArgumentException.
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());
) (opcional) Um Candlestick pode ter data nula? Pode ter algum valor negativo?
Teste, verique o que est errado, altere cdigo para que os testes passem! Pegue o ritmo, essa ser sua
rotina daqui para a frente.
Captulo - Testes Automatizados - Exerccios: novos testes - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
) (opcional) Crie mais dois testes na CandlestickFactoryTest: o negociacoesEmOrdemCrescenteDeValor
e negociacoesEmOrdemDecrescenteDeValor, que devem fazer o que o prprio nome diz.
Agora eles funcionam?
.:: Pnnn snnvn mn:s: Imvon1 Es1K1:co
Algumas vezes, escrevemos classes que contm muitos mtodos e atributos estticos (nais, como constan-
tes). Essas classes so classes utilitrias e precisamos sempre nos referir a elas antes de chamar um mtodo
ou utilizar um atributo:
import pacote.ClasseComMetodosEstaticos;
class UsandoMetodosEstaticos {
void metodo() {
ClasseComMetodosEstaticos.metodo1();
ClasseComMetodosEstaticos.metodo2();
}
}
Comea a car muito chato escrever, toda hora, o nome da classe. Para resolver esse problema, no Java .
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:
import static pacote.ClasseComMetodosEstaticos.*;
class UsandoMetodosEstaticos {
void metodo() {
metodo1();
metodo2();
}
}
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.
Um bom exemplo de uso so os mtodos e atributos estticos da classe Assert do JUnit:
import static org.junit.Assert.*;
class TesteMatematico {
@Test
void doisMaisDois() {
Captulo - Testes Automatizados - Para saber mais: Import Esttico - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
assertEquals(4, 2 + 2);
}
}
Use os imports estticos dos mtodos de Assert nos testes de unidade que voc escreveu.
.:i Mn:s vxvncc:os ovc:oNn:s
) Crie um teste para o CandleBuilder. Ele possui um grande erro: se s chamarmos alguns dos mtodos,
e no todos, ele construir um Candle invlido, com data nula, ou algum nmero zerado.
Faa umteste geracaoDeCandleDeveTerTodosOsDadosNecessarios que tente isso. Omtodo geraCandle
deveria lanar outra exception conhecida da biblioteca Java, a IllegalStateException, quando invocado
antes dos seus outros seis mtodos j terem sido.
O teste deve falhar. Corrija-o criando booleans que indicam se cada mtodo setter foi invocado, ou utili-
zando alguma outra forma de vericao.
) 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
especicado 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.
Crie o teste quandoAberturaIgualFechamentoEhAlta dentro de CandlestickTest, verique se isso est
ocorrendo. Se o teste falhar, faa mudanas no seu cdigo para que a barra volte a car verde!
) 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.
.: D:sccssXo vmnctn: 1vs1vs sXo :mvon1nN1vs:
Captulo - Testes Automatizados - Mais exerccios opcionais - Pgina
C
Trabalhando com XML
Se eu enxerguei longe, foi por ter subido nos ombros de gigantes."
Isaac Newton
{.: Os onoos on notsn ov vntonvs
Como vamos puxar os dados da bolsa de valores para popular nossos candles?
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.
{.i Ovonmn1o XML
XML (eXtensible Markup Language) uma formalizao da WC para gerar linguagens de marcao que
podem se adaptar a quase qualquer tipo de necessidade. Algo bem extensvel, exvel, de fcil leitura e
hierarquizao. Sua denio formal pode ser encontrada em:
http://www.w.org/XML/
Exemplo de dados que so armazenados em XMLs e que no conhecemos to bem, o formato aberto de
grcos vetoriais, o SVG(usado pelo Corel Draw, Firefox, Inkscape, etc), e o Open Document Format (ODF),
formato usado pelo OpenOce, 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 sowares, e
pudesse ser integrada as outras linguagens. Entre seus princpios bsicos, denidos pelo WC:
Separao do contedo da formatao
Simplicidade e Legibilidade
Possibilidade de criao de tags novas
Criao de arquivos para validao (DTDs e schemas)
O XML uma excelente opo para documentos que precisam ter seus dados organizados com uma certa
hierarquia (uma rvore), com relao de pai-lho entre seus elementos. Esse tipo de arquivo dicilmente
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:
Captulo - Trabalhando com XML - O formato XML - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
O cabealho opcional de todo XML o que se segue:
<?xml version="1.0" encoding="ISO-8859-1"?>
Esses caracteres no devem ser usados como elemento, e devem ser escapados":
&, use &amp;
, use &apos;
, use &quot;
<, use &lt;
>, use &gt;
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 linguagemexistente, possui uma ou mais formas de ler umXML. OJava possui diversas, vamos ver
algumas delas, suas vantagens e suas desvantagens.
{. LvNoo XML comJnvn ov mnNv:nn o:vc:t, o SAX
OSAX(Simple API for XML) uma API para ler dados emXML, tambmconhecido como Parser de XML.
Um parser serve para analisar uma estrutura de dados e geralmente o que fazemos transform-la em uma
outra.
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 uxo 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.
Existem vrios tipos de eventos, por exemplo:
Captulo - Trabalhando com XML - Lendo XML com Java de maneira difcil, o SAX - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
incio do documento XML;
incio de um novo elemento;
novo atributo;
incio do contedo dentro de um elemento.
Para tratar estes eventos, o programador deve passar um objeto listener ao parser que ser noticado auto-
maticamente pelo parser quando umdesses eventos ocorrer. Comumente, este objeto chamado de Handler,
Observer, ou Listener e quem faz o trabalho necessrio de processamento do XML.
public class NegociacaoHandler extends DefaultHandler {
@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
}
}
Aclasse DefaultHandler permite que voc reescreva mtodos que vo te noticar sobre quando umelemento
(tag) est sendo aberto, quando est sendo fechado, quando caracteres esto sendo parseados (contedo de
Captulo - Trabalhando com XML - Lendo XML com Java de maneira difcil, o SAX - Pgina
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 dene mais alguns outros mtodos.
Ccn:os:onov sonnv o SAX
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 e faz parte do JAX-P (Java API for XML Processing).
O SAX somente sabe ler dados e nunca modic-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
umpequeno pedao. Devido tambma leitura sequencial, ele muito rpido comparado comos 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.
S1AX - S1nvnm:Nc API von XML
StAX um projeto que foi desenvolvido pela empresa BEA e padronizado pela JSR-. Ele
mais novo do que o SAX e foi criado para facilitar o trabalho com XML. StAX faz parte do Java
SE e JAX-P.
Como o SAX, o StAX tambm l os dados de maneira sequencial. A diferena entre os dois a
forma como noticada a ocorrncia de um evento.
No SAXtemos que registrar umHandler. o SAXque avisa o Handler e chama os mtodos dele.
Ele empurra os dados para o Handler e por isso ele um parser do tipo push, .
OStAX, ao contrrio, no precisa deste Handler. Podemos usar a API do StAXpara 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 eciente de processar documentos xml.
Abiblioteca XPP a implementao emJava mais conhecida deste conceito. usada por outras
bibliotecas de processamento de xml, como o CodeHaus XStream.
Captulo - Trabalhando com XML - Lendo XML com Java de maneira difcil, o SAX - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
{.{ XS1nvnm
O XStream uma alternativa perfeita para os casos de uso de XML em persistncia, transmisso de dados e
congurao. 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. Ogrupo patroci-
nado por empresas como a oughWorks, BEAe Atlassian. Entre os desenvolvedores do projeto, Guilherme
Silveira da Caelum est tambm presente.
http://xstream.codehaus.org
Diversos projetos opensource, como o container de inverso de controle NanoContainer, o framework de
redes neurais Joone, dentre outros, passaram a usar XStream depois de experincias com outras bibliotecas.
O XStream conhecido pela sua extrema facilidade de uso. Repare que raramente precisaremos fazer con-
guraes ou mapeamentos, como extremamente comum nas outras bibliotecas mesmo para os casos mais
bsicos.
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:
Negociacao negociacao = new Negociacao(42.3, 100, Calendar.getInstance());
XStream stream = new XStream(new DomDriver());
System.out.println(stream.toXML(negociacao));
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 denir se quer usar SAX, DOM, DOMJ dentre outros, e com isso o XStream ser mais rpido,
mais lento, usar mais ou menos memria, etc.
Odefault do XStream usar umdriver chamado XPP, 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.
Captulo - Trabalhando com XML - XStream - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
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 XStreamserializa 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 denido, ou simplesmente no queremos
gerar um XML com cara de java. Para isso podemos utilizar um alias. Vamos modicar nosso cdigo que
gera o XML:
XStream stream = new XStream(new DomDriver());
stream.alias("negociacao", Negociacao.class);
Essa congurao tambm pode ser feita atravs da anotao @XStreamAlias("negociacao") em cima da
classe Negociacao.
Podemos agora fazer o processo inverso. Dado umXML que representa umbean da nossa classe Negociacao,
queremos popular esse bean. O cdigo novamente extremamente simples:
XStream stream = new XStream(new DomDriver());
stream.alias("negociacao", Negociacao.class);
Negociacao n = (Negociacao) stream.fromXML("<negociacao>" +
"<preco>42.3</preco>" +
"<quantidade>100</quantidade>" +
"</negociacao>");
System.out.println(negociacao.getPreco());
Obviamente no teremos um XML dentro de um cdigo Java. O exemplo aqui meramente ilustrativo (til
emumteste!). Os atributos no existentes caro 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 oc XS1nvnm:
Avantagemdo JAXB ser uma especicao do Java, e a do XStream ser mais exvel e permitir
trabalhar com classes imutveis.
Captulo - Trabalhando com XML - XStream - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
qXS1nvnmAt:ns
Em vez de chamar stream.alias("negociacao", Negociacao.class);, podemos fazer essa
congurao direto na classe Negociacao com uma anotao:
@XStreamAlias("negociacao")
public class Negociacao {
}
Para habilitar o suporte a anotaes, precisamos chamar no xstream:
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 conguraes centralizadas e, assim, se houver mais de uma parte
na sua aplicao responsvel por gerar XMLs de ummesmo modelo, no corremos o risco de ter
XMLs incompatveis.
{. Exvncc:os: LvNoo o XML
) Para usarmos o XStream, precisamos copiar seus JARs para o nosso projeto e adicion-los ao Build Path.
Para facilitar, vamos criar uma pasta lib para colocar todos os JARs que necessitarmos.
Crie uma nova pasta usando ctrl + N e comeando a digitar Folder:
Captulo - Trabalhando com XML - Exerccios: Lendo o XML - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Coloque o nome de lib e clique OK:
) Vamos pr o XStream no nosso projeto. V na pasta Caelum no seu Desktop e entre em ii. Localize o
arquivo do XStream:
Captulo - Trabalhando com XML - Exerccios: Lendo o XML - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Esse o mesmo arquivo que voc encontra para download no site do XStream, na verso minimal.
) Copie o JAR do XStream . para a pasta lib/ do Argentum e, pelo Eclipse, entre na pasta lib e d refresh
(F) 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.
) Vamos, nalmente, 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...
public class LeitorXML {
public List<Negociacao> carrega(InputStream inputStream) {
XStream stream = new XStream(new DomDriver());
stream.alias("negociacao", Negociacao.class);
return (List<Negociacao>) stream.fromXML(inputStream);
}
}
) 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:
Lembre-se de coloc-lo na source folder src/test/java.
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():
Captulo - Trabalhando com XML - Exerccios: Lendo o XML - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
@Test
public void carregaXmlComUmaNegociacaoEmListaUnitaria() {
String xmlDeTeste = "..."; // o XML vai aqui!
LeitorXML leitor = new LeitorXML();
InputStream xml = new ByteArrayInputStream(xmlDeTeste.getBytes());
List<Negociacao> negociacoes = leitor.carrega(xml);
}
Use o seguinte XML de teste, substituindo a linha em negrito acima:
String xmlDeTeste = "<list>" +
" <negociacao>" +
" <preco>43.5</preco>" +
" <quantidade>1000</quantidade>" +
" <data>" +
" <time>1322233344455</time>" +
" </data>" +
" </negociacao>" +
"</list>";
) Um teste de nada serve se no tiver suas vericaes. Assim, no esquea de vericar valores esperados
como:
a lista devolvida deve ter tamanho ;
a negociao deve ter preo .;
a quantidade deve ser .
) (Opcional) Crie mais alguns testes para casos excepcionais, como:
Zero negociaes;
Preo ou quantidade faltando;
Outras quantidades de negociaes (, por exemplo).
) (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!
Captulo - Trabalhando com XML - Exerccios: Lendo o XML - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Pensar emsempre testar as menores unidades possveis nos fora a pensar emclasses 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).
{.o D:sccssXo vmnctn: ONov csnn XML v o nncso oo mvsmo
Captulo - Trabalhando com XML - Discusso em aula: Onde usar XML e o abuso do mesmo - Pgina
C
Test Driven Design - TDD
Experincia sem teoria cegueira, mas teoria sem experincia mero jogo intelectual."
Immanuel Kant
.: SvvnnnNoo ns cnNotvs
Agora que temos nosso leitor de XML que cria uma lista com as negociaes representadas no arquivo pas-
sado, um novo problema surge: a BOVESPA permite fazer download de um arquivo XML contendo todas
as negociaes de umativo desde a data especicada. Entretanto, nossa CandlestickFactory est preparada
apenas para construir candles de uma data especca.
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.
Para fazer tal lgica, ento, precisamos:
passar por cada negociaes da lista original;
vericar se continua no mesmo dia e...
...se sim, adiciona na lista do dia;
...caso contrrio:
gera a candle;
guarda numa lista de Candlesticks;
zera a lista de negociaes do dia;
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
indica que vai olhar o prximo dia, agora;
ao nal, devolver a lista de candles;
O algoritmo no trivial e, ainda, ele depende de uma vericao que o Java no nos d prontamente: se
continua no mesmo dia. Isto , dado que eu sei qual a dataAtual, quero vericar se a negociao pertence a
esse mesmo dia.
Vericar 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:
se for exatamente o mesmo milissegundo => true;
se for no mesmo dia, mas em horrios diferentes => true;
se for no mesmo dia, mas em meses diferentes => false;
se for no mesmo dia e ms, mas em anos diferentes => false.
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).
.i VnN1ncvNs oo TDD
TDD uma tcnica que consiste em pequenas iteraes, em que novos casos de testes de funcionalidades
desejadas so criados antes mesmo da implementao. Nesse momento, o teste escrito deve falhar, j que
a funcionalidade implementada no existe. Ento, o cdigo necessrio para que os testes passem, deve ser
escrito e o teste deve passar. O ciclo se repete para o prximo teste mais simples que ainda no passa.
Um dos principais benefcio dessa tcnica que, como os testes so escritos antes da implementao do
trecho a ser testado, o programador no inuenciado 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. Emsistemas semtestes, comumencontrarmos centenas de linhas
que jamais sero invocadas, simplesmente porque o desenvolvedor achou que algum um dia precisaria
daquele determinado mtodo.
Captulo - Test Driven Design - TDD - Vantagens do TDD - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
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 modicar 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.
. Exvncc:os: IovN1:v:cnNoo Nvcoc:novs oo mvsmo o:n
Poderamos criar uma classe LeitorXML que pega todo o XML e converte em candles, mas ela teria muita
responsabilidade. Vamos cuidar da lgica que separa as negociaes em vrios candles por datas em outro
lugar.
) 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 identicar 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 vericao.
Seguindo os princpios do TDD, comeamos escrevendo um teste na classe NegociacaoTest:
@Test
public void mesmoMilissegundoEhDoMesmoDia() {
Calendar agora = Calendar.getInstance();
Calendar mesmoMomento = (Calendar) agora.clone();
Negociacao negociacao = new Negociacao(40.0, 100, agora);
Assert.assertTrue(negociacao.isMesmoDia(mesmoMomento));
}
Esse cdigo no vai compilar de imediato, j que no temos esse mtodo na nossa classe. No Eclipse,
aperte Ctrl + : em cima do erro e escolha Create method isMesmoDia.
E qual ser uma implementao interessante? Que tal simplicar usando o mtodo equals de Calendar?
Captulo - Test Driven Design - TDD - Exerccios: Identicando negociaes do mesmo dia - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
public boolean isMesmoDia(Calendar outraData) {
return this.data.equals(outraData);
}
Rode o teste! Passa?
) 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);
Negociacao negociacao = new Negociacao(40.0, 100, manha);
Assert.assertTrue(negociacao.isMesmoDia(tarde));
}
Rode o teste. No passa!
Infelizmente, usar o equals no resolve nosso problema de comparao.
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.DATE) == outraData.get(Calendar.DATE);
}
Altere o mtodo isMesmoDia na classe Negociacao e rode os testes anteriores. Passamos agora?
) 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!
Crie o mesmoDiaMasMesesDiferentesNaoSaoDoMesmoDia na classe de testes do Negociacao, veja o teste
falhar e, ento, implemente o necessrio para que ele passe. Note que, dessa vez, o valor esperado o
false e, portanto, utilizaremos o Assert.assertFalse.
) 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:
Escreva o teste mesmoDiaEMesMasAnosDiferentesNaoSaoDoMesmoDia;
Rode e veja que falhou;
Implemente o necessrio para faz-lo passar.
Feito esse processo, seu mtodo isMesmoDia na classe Negociacao deve ter cado bemparecido comisso:
Captulo - Test Driven Design - TDD - Exerccios: Identicando negociaes do mesmo dia - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
public boolean isMesmoDia(Calendar outraData) {
return this.data.get(Calendar.DATE) == outraData.get(Calendar.DATE) &&
this.data.get(Calendar.MONTH) == outraData.get(Calendar.MONTH) &&
this.data.get(Calendar.YEAR) == outraData.get(Calendar.YEAR);
}
.{ Exvncc:os: SvvnnnNoo os cnNotvs
) Prximo passo: dada uma lista de negociaes de vrias datas diferentes mas ordenada por data, quebrar
em uma lista de candles, uma para cada data.
Seguindo a disciplina do TDD: comeamos pelo teste!
Adicione o mtodo paraNegociacoesDeTresDiasDistintosGeraTresCandles na classe
CandlestickFactoryTest:
@Test
public void paraNegociacoesDeTresDiasDistintosGeraTresCandles() {
Calendar hoje = Calendar.getInstance();
Negociacao negociacao1 = new Negociacao(40.5, 100, hoje);
Negociacao negociacao2 = new Negociacao(45.0, 100, hoje);
Negociacao negociacao3 = new Negociacao(39.8, 100, hoje);
Negociacao negociacao4 = new Negociacao(42.3, 100, hoje);
Calendar amanha = (Calendar) hoje.clone();
amanha.add(Calendar.DAY_OF_MONTH, 1);
Negociacao negociacao5 = new Negociacao(48.8, 100, amanha);
Negociacao negociacao6 = new Negociacao(49.3, 100, amanha);
Calendar depois = (Calendar) amanha.clone();
depois.add(Calendar.DAY_OF_MONTH, 1);
Negociacao negociacao7 = new Negociacao(51.8, 100, depois);
Negociacao negociacao8 = new Negociacao(52.3, 100, depois);
List<Negociacao> negociacoes = Arrays.asList(negociacao1, negociacao2,
negociacao3, negociacao4, negociacao5, negociacao6, negociacao7,
negociacao8);
CandlestickFactory fabrica = new CandlestickFactory();
List<Candlestick> candles = fabrica.constroiCandles(negociacoes);
Captulo - Test Driven Design - TDD - Exerccios: Separando os candles - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
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 + : e Create
method.
Como implementamos? Precisamos:
Criar a List<Candlestick>;
Percorrer a List<Negociacao> adicionando cada negociaco no Candlestick atual;
Quando achar uma negociao de um novo dia, cria um Candlestick novo e adiciona;
Devolve a lista de candles;
O cdigo talvez que um pouco grande. Ainda bem que temos nosso teste!
public List<Candlestick> constroiCandles(List<Negociacao> todasNegociacoes) {
List<Candlestick> candles = new ArrayList<Candlestick>();
List<Negociacao> negociacoesDoDia = new ArrayList<Negociacao>();
Calendar dataAtual = todasNegociacoes.get(0).getData();
for (Negociacao negociacao : todasNegociacoes) {
// se no for mesmo dia, fecha candle e reinicia variveis
if (!negociacao.isMesmoDia(dataAtual)) {
Candlestick candleDoDia = constroiCandleParaData(dataAtual,
negociacoesDoDia);
candles.add(candleDoDia);
negociacoesDoDia = new ArrayList<Negociacao>();
dataAtual = negociacao.getData();
}
negociacoesDoDia.add(negociacao);
}
// adiciona ltimo candle
Candlestick candleDoDia = constroiCandleParaData(dataAtual,
negociacoesDoDia);
candles.add(candleDoDia);
return candles;
}
Captulo - Test Driven Design - TDD - Exerccios: Separando os candles - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Rode o teste!
. Exvncc:os ovc:oNn:s
) E se passarmos para o mtodo constroiCandles da fbrica uma lista de negociaes que no est na
ordem crescente? O resultado vai ser candles em ordem diferentes, e provavelmente com valores erra-
dos. Apesar da especicao dizer que os negociaes vem ordenados pela data, boa prtica programar
defensivamente em relao aos parmetros recebidos.
Aqui temos diversas opes. Uma delas , caso alguma Negociacao venha em ordem diferente da cres-
cente, lanamos uma exception, a IllegalStateException.
Crie o naoPermiteConstruirCandlesComNegociacoesForaDeOrdem e congure o teste para vericar que
uma IllegalStateException foi lanada. Basta usar como base o mesmo teste que tnhamos antes, mas
adicionar as negociaes com datas no crescentes.
Rode o teste e o veja falhar.
Pra isso, modicamos o cdigo adicionando as linhas em negrito ao mtodo constroiCandles:
for (Negociacao negociacao : todasNegociacoes) {
if (negociacao.getData().before(dataAtual)) {
throw new IllegalStateException("negociaes em ordem errada");
}
// se no for mesmo dia, fecha candle e reinicia variveis
...
Captulo - Test Driven Design - TDD - Exerccios opcionais - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
) Vamos criar um gerador automtico de arquivos para testes da bolsa. Ele vai gerar dias de candle e
cada candle pode ser composto de a 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>();
double valor = 40;
int quantidade = 1000;
for (int dias = 0; dias < 30; dias++) {
int quantidadeNegociacoesDoDia = random.nextInt(20);
for (int negociacao = 0; negociacao < quantidadeNegociacoesDoDia;
negociacao++){
// no mximo sobe ou cai R$1,00 e nao baixa alm de R$5,00
valor += (random.nextInt(200) - 100) / 100.0;
if (valor < 5.0) {
valor = 5.0;
}
// quantidade: entre 500 e 1500
quantidade += 1000 - random.nextInt(500);
Negociacao n = new Negociacao(valor, quantidade, data);
negociacoes.add(n);
}
data = (Calendar) data.clone();
data.add(Calendar.DAY_OF_YEAR, 1);
}
XStream stream = new XStream(new DomDriver());
stream.alias("negociacao", Negociacao.class);
stream.setMode(XStream.NO_REFERENCES);
PrintStream out = new PrintStream(new File("negociacao.xml"));
out.println(stream.toXML(negociacoes));
}
}
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 comumna hora de integrar sistemas, passar umXML simples com
Captulo - Test Driven Design - TDD - Exerccios opcionais - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
todos os dados.
Aopo XStream.NO_REFERENCES serve para indicar ao XStreamque 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.
Dvsnv:o - OnovNv n t:s1n oN ovmnNo
) 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 vericar se os negociaes esto vindo em ordem crescente!
Perceba que mudamos uma regra de negcio, ento teremos de reetir isso no nosso teste unitrio que
estava comexpected=IllegalStateException.class no caso de vir emordemerrada. Oresultado agora
com essa modicao tem de dar o mesmo que com as datas crescentes.
Captulo - Test Driven Design - TDD - Exerccios opcionais - Pgina
C
Acessando um Web Service
Nenhum homem uma ilha isolada; cada homem uma partcula do continente, uma parte da terra
John Donne
o.: IN1vcnnXo vN1nv s:s1vmns
No captulo anterior resolvemos o problema de como interpretar os dados oriundos de um arquivo XML,
apesar disso, no mundo real, dados so gerados dinamicamente a todo instante das mais diversas fontes.
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.
o.i CoNscm:Noo onoos ov cmWvn Svnv:cv
Para consumir dados vindos de outra aplicao, a primeira coisa importante saber onde essa aplicao se
encontra. Emtermos tcnicos, qual a URLdesse webservice. Emnosso projeto a URLespecca da aplicao
ser http://argentum-ws.cloudfoundry.com/negociacoes.
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
o. Cn:nNoo o ct:vN1v Jnvn
J sabemos de onde consumir, resta saber como consumir esses dados pela web. No mundo web trabalhamos
com o conceito de requisio e resposta. Se queremos os dados precisamos realizar uma requisio para
aquela URL, mas como?
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.
URL url = new URL("http://argentum-ws.cloudfoundry.com/negociacoes");
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.
URL url = new URL("http://argentum-ws.cloudfoundry.com/negociacoes");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
Dessa conexo pediremos um InputStream que ser usado pelo nosso LeitorXML.
URL url = new URL("http://argentum-ws.cloudfoundry.com/negociacoes");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
InputStream content = connection.getInputStream();
List<Negociacao> negociacoes = new LeitorXML().carrega(content);
Captulo - Acessando um Web Service - Criando o cliente Java - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
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.
public class ClienteWebService {
private static final String URL_WEBSERVICE =
"http://argentum-ws.cloudfoundry.com/negociacoes";
}
Por ltimo, e no menos importante, declararemos um mtodo que retorna uma lista de negociaes, justa-
mente o que usaremos no projeto.
public class ClienteWebService {
private static final String URL_WEBSERVICE =
"http://argentum-ws.cloudfoundry.com/negociacoes";
public List<Negociacao> getNegociacoes() {
URL url = new URL(URL_WEBSERVICE);
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
InputStream content = connection.getInputStream();
return new LeitorXML().carrega(content);
}
}
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() {
HttpURLConnection connection = null;
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);
Captulo - Acessando um Web Service - Criando o cliente Java - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
} 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-: | Curso Java EE avanado e Web Services.
H11vCt:vN1
Existe uma biblioteca capaz de lidar com dados de uma forma simples e mais especca do que
utilizar diretamente a API do Java. Para trabalhar com o protocolo HTTP h a biblioteca Http-
Client que faz parte do Apache Soware 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:
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet(URL_DO_WEBSERVICE);
HttpResponse response = client.execute(request);
InputStream content = response.getEntity().getContent();
Captulo - Acessando um Web Service - Criando o cliente Java - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Wvn Svnv:cv - SOAP, JSONv oc1nos
Por denio 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 especicar mais ainda o XML dos Web Services so os padres SOAP e WSDL.
Junto com o protocolo HTTP, eles denem 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 assimo uso para quemno conhece os padres Web. No treinamento
FJ- 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
umpouco menos verboso e fcil de usar comJavaScript. JSONganhou 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.
o.{ Exvncc:os: Nosso ct:vN1v Wvn Svnv:cv
) Vamos agora implementar o cliente do Web Service, primeiramente criaremos a classe
ClienteWebService, dentro do pacote br.com.caelum.argentum.ws na pasta src/main/java. Va-
mos criar tambm uma constante com a URL para onde ser feita a requisio.
public class ClienteWebService {
private static final String URL_WEBSERVICE =
"http://argentum-ws.cloudfoundry.com/negociacoes";
}
) Agora iremos criar o mtodo getNegociacoes(), que retorna a nossa lista de negociaes:
public class ClienteWebService {
private static final String URL_WEBSERVICE =
"http://argentum-ws.cloudfoundry.com/negociacoes";
public List<Negociacao> getNegociacoes() {
HttpURLConnection connection = null;
URL url = new URL(URL_WEBSERVICE);
Captulo - Acessando um Web Service - Exerccios: Nosso cliente Web Service - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
connection = (HttpURLConnection)url.openConnection();
InputStream content = connection.getInputStream();
return new LeitorXML().carrega(content);
}
}
) No podemos esquecer de colocar o try/catch para tratar possveis erros e logo em seguida fechar a
conexo:
public class ClienteWebService {
private static final String URL_WEBSERVICE =
"http://argentum-ws.cloudfoundry.com/negociacoes";
public List<Negociacao> getNegociacoes() {
HttpURLConnection connection = null;
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();
}
}
}
o. D:sccssXovmnctn: Como1vs1nn oct:vN1v oowvn svnv:cv:
Captulo - Acessando um Web Service - Discusso em aula: Como testar o cliente do web service? - Pgina
C
Introduo ao JSF e Primefaces
Eu no temo computadores, eu temo a falta deles
Isaac Asimov
,.: IN1vnvncvs cnKv:cns vnnn o cscKn:o - GUI
Usurios se habituaram com aplicaes Desktop durante muitos anos. Este tipo de aplicao instalada no
computador local e acessa diretamente umbanco 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 sosticados
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 cam associados a eventos/aes e
guardam automaticamente seu estado, pois mantm os valores digitados pelo usurio.
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Esses componentes no esto, contudo, associados exclusivamente ao desenvolvimento de aplicaes Desk-
top. Podemos criar a mesma sensao confortvel para o cliente em uma aplicao web, tambm usando
componentes ricos e reaproveitveis.
,.i Oct:vN1v conoo v o ovsvNvotv:mvN1o Dvs1ov
Existem algumas desvantagens nessa abordagem, visto que cada usurio possui uma cpia, muitas das ve-
zes integral, dessa aplicao. Qualquer alterao precisaria ser propagada para todas as outras mquinas.
Estamos usando um cliente gordo, com muita responsabilidade no lado do cliente.
Captulo - Introduo ao JSF e Primefaces - O cliente gordo e o desenvolvimento Desktop - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Para piorar, as regras de negcio rodam no computador do usurio, sendo muito difcil depurar a aplicao.
Em geral, enfrentamos problemas de manuteno e gerenciabilidade.
,. OovsvNvotv:mvN1o Wvn v o vno1ocoto HTTP
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 clientes podem acess-la atravs do
protocolo HTTP.
O usurio precisa basicamente instalar um navegador web, como Firefox ou Internet Explorer, que receber
o HTML, o CSS e o JavaScript, que anal so tecnologias que ele entende.
Entre cada requisio (request), trafega o HTML do lado servidor (Server Side) para o computador do cliente
(Client Side). Em nenhum momento a aplicao est salva no cliente. Todas as regras da aplicao esto
sendo processadas no lado do servidor. Por isso, essa abordagem tambm foi chamada de cliente magro.
Captulo - Introduo ao JSF e Primefaces - O desenvolvimento Web e o protocolo HTTP - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Isso facilita bastante a manuteno e a gerenciabilidade, pois temos um lugar - central -, onde a aplicao
executada, mas ainda preciso conhecer bastante de HTML, CSS e JavaScript para denir a interface
com o usurio. Tambm no h mais eventos, mas sim um modelo bem diferente orientado a requisio e
resposta. Alm disso, ainda preciso conhecer o protocolo HTTP. Assim, toda essa responsabilidade ca a
cargo do desenvolvedor.
Comparando as duas abordagens, podemos ver vantagens e desvantagens em ambas. No lado da aplicao
puramente Desktop, temos um estilo de desenvolvimento orientado ao evento, 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 e conhecer o protocolo HTTP, e seguir o modelo
request-response (requisio-resposta).
,.{ Mvsctnn ovsvNvotv:mvN1o Dvs1ov v Wvn
O ideal seria mesclar os dois estilos, aproveitando as vantagens de cada um. Seria um desenvolvimento
Desktop para WEB, central e comcomponentes ricos, seguindo as boas prticas de orientao de objetos mas
sem problemas de manuteno e gerenciabilidade. Isso 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.
,. Esvvc:v:cnXo v :mvtvmvN1nXo oo JSF
JSF uma tecnologia que nos permite criar aplicaes Java para Web utilizando componentes visuais, fazendo
com que o desenvolvedor no se preocupe com Javascript e HTML. Basta adicionarmos os componentes
(calendrios, tabelas, formulrios) que eles sero renderizados e exibidos em formato html.
Gcnnon o vs1noo oos comvoNvN1vs
Alm disso o estado dos componentes sempre guardado automaticamente (como veremos mais a frente),
fazendo o papel de Stateful. Isso nos permite, por exemplo, criar wizards e navegar nos vrios passos dessa
wizard com o estado das telas sendo mantidos, sem ter que resgat-los novamente.
Svvnnn ns cnmnons
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 que, por padro,
se baseia nos Facelets e um conjunto de classes conhecidas como Managed Beans; ambos veremos com mais
detalhes.
Captulo - Introduo ao JSF e Primefaces - Mesclar desenvolvimento Desktop e Web - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
cmn vsvvc:v:cnXo Jnvn EE
Analisando um pouco melhor o JSF, percebemos que ele na verdade um padro ou especicao que faz
parte do Java Enterprise Edition (Java EE). Por ser uma especicao, ou Java Specication Request (JSR),
ele mantido dentro do Java Community Process (JCP).
O JSF foi lanado em Julho de atravs da JSR . No lanamento do Java EE em Dezembro de
, passou a ser ocial na plataforma Java EE. A especicao do JSF pode ser acessada no site da JCP:
http://jcp.org/en/jsr/detail?id=
Nesse site mostrado a verso . do JSF e todos os documentos disponveis para os interessados na imple-
mentao dessa especicao JSF.
VKn:ns :mvtvmvN1novs
Baseado nesta especicao, h vrias implementaes. Amais famosa, e tambmimplementao referencial
(RI), a Oracle Mojarra disponvel emhttp://javaserverfaces.java.net/, aquela que mostra como o JSF deveria
se comportar. Outra implementao famosa da Apache Soware Foundation, e se chama MyFaces (http:
//myfaces.apache.org/).
Neste treinamento usaremos a implementao referencial Mojarra. Acessando o site http://javaserverfaces.
java.net, na parte de downloads, podemos encontrar o JAR do Mojarra.
,.o IN1noocXo no JSF comMo)nnnn v Pn:mvFncvs
Como dito antes, nosso projeto utilizar a implementao Mojarra do JSF. Ela j dene o modelo de desen-
volvimento e oferece alguns componentes bem bsicos. Nada alm de inputs, botes e ComboBox simples.
No h componentes sosticados dentro da especicao. Isto proposital, pois o mundo web evolui rpido
(principalmente na questo das interfaces grcas).
Os componentes da especicao JSF so bem simples:
Captulo - Introduo ao JSF e Primefaces - Introduo ao JSF com Mojarra e PrimeFaces - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Para atender a demanda dos desenvolvedores por componentes mais sosticados, existem vrias extenses
do JSF que seguem o mesmo ciclo e modelo da especicao. Exemplos dessas bibliotecas so: PrimeFaces,
RichFaces ou IceFaces. Todas elas denem componentes JSF, mas muito alm da especicao.
Cada biblioteca oferece ShowCases na web para mostrar seus componentes e suas funcionalidades. O show-
case do PrimeFaces est disponvel em http://www.primefaces.org.
Podemos ver na demo online uma lista de componentes disponveis entre eles inputs, paneis e botes diver-
sos, menus e charts e componentes drag &drop, muito almda especicaes, pormmantendo a facilidade
de uso:
Captulo - Introduo ao JSF e Primefaces - Introduo ao JSF com Mojarra e PrimeFaces - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Captulo - Introduo ao JSF e Primefaces - Introduo ao JSF com Mojarra e PrimeFaces - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Para a denio da interface do projeto Argentum usaremos Oracle Mojarra com PrimeFaces, uma combi-
nao muito comum no mercado.
,., PnvvnnnXo oo nmn:vN1v
Nossa aplicaoArgentumprecisa de uma interface web. Para issovamos preparar uma aplicaowebcomum
que roda dentro de um Servlet Container.
Tomcn1 como Svnvtv1 CoN1n:Nvn
Usaremos Apache Tomcat , no entanto, poderia ser utilizado qualquer outro servlet container como por
exemplo Jetty.
CoNv:ccnnXo oo coN1notnoon oo JSF
JSF segue o padro arquitetural MVC (Model-View-Controller) por isso precisamos congurar o servlet do
JSF no web.xml da aplicao que representa o controller (C) dentro do modelo MVC. Esse Servlet res-
ponsvel em receber as requisies e deleg-las ao core do JSF. Para congur-lo basta adicionar as seguintes
conguraes no web.xml:
<servlet>
<servlet-name>FacesServlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
Captulo - Introduo ao JSF e Primefaces - Preparao do ambiente - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
<servlet-name>FacesServlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
Ao usar o Eclipse com suporte a JSF essa congurao no web.xml j feita automaticamente.
Fncvs-coNv:c: o nnqc:vo ov coNv:ccnnXo oo mcNoo JSF
Alm disso, h um segundo XML que o arquivo de congurao relacionado com o mundo JSF, o
faces-config.xml.
Como o JSF na verso dois encoraja o uso de anotaes invs de conguraes no XML, este arquivo torna-se
pouco usado, sendo muito mais importante na primeira verso do JSF. Para este treinamento no usaremos
o arquivo, cando ento vazio:
<faces-config
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
version="2.0">
</faces-config>
Agora j temos as informaes necessrias para criar nosso primeiro projeto utilizando JSF.
,.8 Exvncc:os: INs1ntnNoo o Tomcn1 v cn:nNoo o vno)v1o
) Primeiramente, precisamos instalar o Tomcat. Usaremos a verso .x:
a) V no Desktop e entre na pasta Caelum e em seguida na pasta .
b) Descompacte o arquivo apache-tomcat-7.x.x.zip no seu Desktop. Para isso d um duplo clique no
arquivo para abrir o Archive Manager e clique em Extract.
Captulo - Introduo ao JSF e Primefaces - Exerccios: Instalando o Tomcat e criando o projeto - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
c) Na janela que abriu, selecione no lado esquerdo o item Desktop e clique em Extract.
d) O Tomcat j est pronto para o uso.
) O prximo passo congurar o Tomcat no Eclipse, para que possamos control-lo mais facilmente.
a) Abra o Eclipse, e ao ser perguntado sobre o caminho da sua workspace apenas conrme.
b) Dentro do Eclipse, abra a aba Servers. Para isso, pressione CTRL + , digite servers e pressione [EN-
TER]. Ela ser aberta na parte inferior do seu Eclipse.
c) Dentro da aba Servers clique com o boto direito do mouse e escolha New -> Server.
Captulo - Introduo ao JSF e Primefaces - Exerccios: Instalando o Tomcat e criando o projeto - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
d) Dentro da Janela New Server escolha Apache Tomcat v. Server e clique em Next.
e) 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.
Captulo - Introduo ao JSF e Primefaces - Exerccios: Instalando o Tomcat e criando o projeto - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
f) Clique em Finish.
) O prximo passo para podermos comear a trabalhar criar o nosso projeto no Eclipse.
a) Dentro do Eclipse, v ao menu File -> New -> Dynamic Web Project
b) Em Project name coloque fj22-argentum-web.
Captulo - Introduo ao JSF e Primefaces - Exerccios: Instalando o Tomcat e criando o projeto - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
c) Na seo Conguration clique em Modify para acrescentarmos suporte ao JSF.
d) Na tela que abre, marque o checkbox com JavaServer Faces e verso i.o, depois clique OK:
e) De volta tela de criao do projeto, clique em Next trs vezes at chegar tela de congurao do
JSF. Nessa tela, escolha a opo Disable Library Conhguration (isso indica para o Eclipse que ns
mesmos copiaremos os JARs do JSF). Ainda nessa tela, na parte URL Mapping Patterns, remova o
mapeamento /faces/*, se existir, e adicione um novo mapeamento como *.xhtml
Captulo - Introduo ao JSF e Primefaces - Exerccios: Instalando o Tomcat e criando o projeto - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
f) Clique em Finish e o projeto est criado.
g) Agora, vamos adicionar o projeto ao servidor Tomcat. Na aba Servers, clique como boto direito sobre
o nome do servidor e escolha a opo Add and Remove...:
h) Na tela seguinte, selecione o projeto -argentum-web no box Available (da esquerda), pressione o
boto Add > (mover para o box Congured da direita) e depois Finish.
Captulo - Introduo ao JSF e Primefaces - Exerccios: Instalando o Tomcat e criando o projeto - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
i) Agora precisamos importar o projeto anterior, classes como Negociacao ou Candlestick. J o te-
mos pronto na pasta Desktop/caelum/22/, com o nome de modelo-argentum.zip, copie-o para o seu
Desktop.Para import-lo, d um clique com o boto direito sobre o nosso projeto atual, e em seguida,
Import > Import.... E selecione Archive File.
j) Em Browse..., selecione o nosso arquivo modelo-argentum.zip e nalize-o.
Captulo - Introduo ao JSF e Primefaces - Exerccios: Instalando o Tomcat e criando o projeto - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
k) Agora precisamos remover o src do Build Path. Ento, d um clique com o direito sobre o diretrio
src e v at Build path > Congure Build Path. Feito isto, clicaremos na aba Source, selecione ii-
argentum-web/src, e aps isto, remova-o, clicando no boto Remove.
l) Precisamos adicionar nossos diretrios src/main/java e src/test/java no projeto. Para isto, d um
clique em Add Folder..., e marque as devidas caixas, assim como na imagem abaixo:
Captulo - Introduo ao JSF e Primefaces - Exerccios: Instalando o Tomcat e criando o projeto - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
D OK, e depois OK novamente.
m) Nossas classes de teste (src/test/java) apresentam problemas, e eles esto relacionados ao JUnit, pois
o mesmo no foi adicionado ao Build Path. Abra a classe ClandlestickFactoryTest, do pacote
br.com.caelum.argentum.modelo e sobre a anotao @Test, d um simples CTRL + : e faa como
na imagem abaixo, salvando as alteraes.
,. A vn:mv:nn vKc:Nn comJSF i
As nossas pginas estaro emarquivos coma extenso .xhtml. Dessa forma, criaremos umarquivo chamado
index.xhtml.
Captulo - Introduo ao JSF e Primefaces - A primeira pgina com JSF - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
As 1nc t:nnnn:vs v
Os componentes do JSF so usados atravs de tags novas na nossa tela. O JSF j dene dois conjuntos prin-
cipais de tags (tag library) que vamos utilizar, a core e a html.
A html possui os componentes necessrios para montarmos a nossa tela gerando o HTML adequado. En-
quanto a core possui diversos componentes no visuais, como por exemplo, tratadores de eventos ou valida-
dores.
Imvon1nNoo ns 1ncs vmNossn vKc:Nn
Para importar todas essas tags, no nosso arquivo .xhtml, basta declararmos como namespace XML do nosso
arquivo. Dessa forma, teremos:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<!-- aqui usaremos as tags do JSF -->
</html>
U1:t:znNoo n :mvtvmvN1nXo Mo)nnnn
O JSF uma especicao e como foi dito utilizaremos a implementao do Projeto Mojarra. Para isto, co-
piaremos o JAR do Mojarra (javax.faces-2.x.x.jar) da pasta Desktop/caelum/22/jsf-jars para a pasta
WebContent/WEB-INF/lib. Assim os taglibs do namespace sero encontrados.
O JAR do Mojarra tambm est disponvel em http://javaserverfaces.java.net/.
Dvv:N:Noo n :N1vnvncv on nvt:cnXo
Vamos comear a denir a interface para a aplicao fj22-argentum-web e criar nossa primeira tela utili-
zando o JSF. Colocaremos uma mensagem de boas vindas para o usurio.
Como todo arquivo HTML, tudo o que ser renderizado no navegador deve car dentro de uma Tag body.
Utilizaremos a Tag h:head para denirmos o cabealho da pgina contendo o ttulo dela e tambm a Tag
h:body na qual colocaremos o contedo da nossa pgina.
Pn:mv:no comvoNvN1v, o n:oc1vc1Tvx1
Utilizaremos nosso primeiro componente, o h:outputText. atravs do seu atributo value que denimos
o texto que ser apresentado na pgina.
Captulo - Introduo ao JSF e Primefaces - A primeira pgina com JSF - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Juntando tudo, nosso primeiro exemplo uma tela simples com um campo de texto:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>Argentum Web</title>
</h:head>
<h:body>
<h:outputText value ="Ol JSF!" />
</h:body>
</html>
,.:o Exvncc:os: Os vn:mv:nos comvoNvN1vs JSF
) Ao importamos nosso projeto ii-argentum-web, j temos na pasta WebContent/WEB-INF/lib os JARs
do JSF (javax.faces-2.x.x.jar) e do Primefaces (primefaces-3.x.jar).
Caso esteja seguindo esses passos em casa, possvel fazer o download dos JARs do JSF e do primefaces
nos sites ociais dos projetos: https://javaserverfaces.dev.java.net/ e http://primefaces.org
) EmWebContent, crie umarquivo chamado index.xhtml atravs do menu File ->New->Other ->HTML.
Aps denir o nome do arquivo clique em Next e voc ver a seguinte tela:
Captulo - Introduo ao JSF e Primefaces - Exerccios: Os primeiros componentes JSF - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Selecione a mesma opo da imagem acima e pressione Finish.
Implemente nosso primeiro cdigo JSF com apenas uma sada de texto:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>Argentum Web</title>
</h:head>
<h:body>
<h:outputText value ="Ol JSF!" />
</h:body>
</html>
) Inicie o Tomcat e acesse a URL: http://localhost:/-argentum-web/index.xhtml
) Verique o cdigo fonte gerado pela pgina. Repare que ele no nada mais que simples HTML. Para
isso, nos navegadores Firefox ou Chrome pressione CTRL + U.
Captulo - Introduo ao JSF e Primefaces - Exerccios: Os primeiros componentes JSF - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Repare no uso das tags <h:head>, <h:body> e <h:outputText>. Elas geraro o cdigo HTML necessrio
para o exemplo funcionar.
,.:: L:s1ncvmov Nvcoc:novs comPn:mvvncvs
Pretendemos usar Primefaces para a denio da interface web devido aos componentes muitos mais so-
sticados e funcionais. Para usar os componentes devemos copiar o JAR do Primefaces primefaces-.X.jar
da pasta Desktop/Caelum/22/jsf-jar para a pasta WebContent/WEB-INF/lib e declarar o namespace do
mesmo no arquivo XHTML. Repare o novo namespace xmlns:p="http://primefaces.org/ui:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<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">
...
</html>
O JAR do Primefaces tambm est disponvel em http://primefaces.org.
Comisso j podemos usufruir os componentes ricos do Primefaces, por exemplo, usando umsimples painel
(p:panel) na pgina:
<html ...>
<h:head>
<title>Argentum Web</title>
</h:head>
<h:body>
<p:panel header="Negociaes" footer="Argentum Web">
<h:outputText value="Ol JSF!" />
</p:panel>
</h:body>
</html>
Captulo - Introduo ao JSF e Primefaces - Listagem de Negociaes com Primefaces - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
,.:i Coo:co n1nKs on 1vtn - MnNncvo BvnNs
Nosso objetivo listar as negociaes do Web Service na tela. O componente que usaremos para a listagem
se chama p:dataTable. O p:dataTable recebe uma lista pelo atributo value. Nesse atributo devemos usar a
Expression Language (EL) que dene a classe e o mtodo que fornece a lista de negociaes. Diferentemente
da EL do JSP, a EL do JSF comea com #{expression} (tralha):
<p:dataTable value="#{nomeDaClasse.nomeDoMetodoQueDevolveALista}" >
</p:dataTable>
Essas classes ligadas tela se chamam Managed Beans. So classes simples (ou POJOs) que devem utilizar
uma anotao com o mesmo nome: @ManagedBean. Na nossa aplicao vamos criar um Managed Bean com
nome ArgentumBean:
@ManagedBean
public class ArgentumBean {
}
Agora falta implementar um getter que devolva uma lista de negociaes. Nesse mtodo vamos usar a classe
ClienteWebService que chama Web Service:
@ManagedBean
public class ArgentumBean {
public List<Negociacao> getNegociacoes() {
ClienteWebService cliente = new ClienteWebService();
return cliente.getNegociacoes();
}
}
Isso j basta para chamar o mtodo na pgina pelo componente p:dataTable. Repare que usaremos a Ex-
pression Language seguindo a nomenclatura Java Beans, ou seja o mtodo no usa o prexo get:
<p:dataTable var="negociacao" value="#{argentumBean.negociacoes}">
</p:dataTable>
Captulo - Introduo ao JSF e Primefaces - Cdigo atrs da tela - Managed Beans - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
OJSF chama o mtodo getNegociacoes vrias vezes durante uma requisio. Como custoso chamar o Web
Service, vamos garantir que ele ser inicializado apenas quando o Managed Bean for criado. OJSF prev para
isso um mtodo especial que deve ser anotado com a anotao @PostConstruct. Esse mtodo chamado
apenas uma vez, na criao da classe ArgentumBean. Como o bean instanciado emcada requisio (Request
Scope), o mtodo chamado uma vez por request:
@ManagedBean
public class ArgentumBean {
private List<Negociacao> negociacoes;
@PostConstruct
public void preparaDados() {
ClienteWebService cliente = new ClienteWebService();
this.negociacoes = cliente.getNegociacoes();
}
public List<Negociacao> getNegociacoes() {
return this.negociacoes;
}
}
Caso queiramos colocar a Managed Bean na sesso Http basta usar a anotao @SessionScoped em cima da
classe:
@ManagedBean
@SessionScoped
public class ArgentumBean {
//cdigo omitido
}
Com a classe ArgentumBean criado vamos completar a tabela na pgina. O prximo passo denir uma
varivel que representa uma negociao:
<p:dataTable var="negociacao" value="#{argentumBean.negociacoes}" >
</p:dataTable>
Comessa negociao emmos podemos declarar o qu queremos apresentar emcada coluna. Atag p:column
dene o cabealho e recebe o contedo da coluna. Repare que imprimimos o preo, volume e a data da
negociao corrente em cada coluna:
Captulo - Introduo ao JSF e Primefaces - Cdigo atrs da tela - Managed Beans - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
<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>
POJO (Ptn:N Oto Jnvn On)vc1)
POJO um termo criado por Martin Fowler, Rebecca Parsons e Josh MacKenzie que serve para
denir 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.
,.: Fonmn1nXo ov Dn1n comJSF
A tabela j funcional, mas com a data mal formatada. O componente no sabe como gostaramos de for-
matar a data e chama por de baixo dos planos o mtodo toString da data para receber uma apresentao
como String.
Podemos facilmente mudar este comportamento usando o componente f:convertDateTime que dene um
pattern para a data. importante saber que o f:convertDateTime s aceita objetos do tipo java.util.Date,
por isso chamaremos o mtodo getTime da data. Mais uma vez podemos omitir a palavra get com expres-
sion language. Segue a tabela completa:
<p:dataTable var="negociacao" value="#{argentumBean.negociacoes}">
<p:column headerText="Preo" >
<h:outputText value="#{negociacao.preco}" />
</p:column>
Captulo - Introduo ao JSF e Primefaces - Formatao de Data com JSF - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
<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.time}" >
<f:convertDateTime pattern="dd/MM/yyyy" />
</h:outputText>
</p:column>
</p:dataTable>
,.:{ Pnc:NnXo v OnovNnXo ons Nvcoc:novs
Ocomponente p:dataTable no s sabe listar os negociaes, ele j vemcomvrias outras funes prontas e
fceis de usar. Primeiramente vamos habilitar a paginao automtica usando o atributo paginator="true"
e denir a quantidade de linhas por pgina pelo atributo rows. Veja a denio da tabela:
<p:dataTable var="negociacao" value="#{argentumBean.negociacoes}"
paginator="true" rows="15">
<!-- colunas omitidas -->
</p:dataTable>
Alm disso, vamos deixar as colunas ordenveis atravs do simples atributo sortBy. Para a ordenao fun-
cionar preciso colocar a tabela dentro de um formulrio (h:form). Veremos mais para frente como os
formulrios funcionam com mais detalhe:
<h:form id="listaNegociacao">
<p:dataTable var="negociacao" value="#{argentumBean.negociacoes}"
paginator="true" rows="15">
<p:column sortBy="#{negociacao.preco}" headerText="Preo" >
<h:outputText value="#{negociacao.preco}" />
</p:column>
<!-- outras colunas omitidas -->
Captulo - Introduo ao JSF e Primefaces - Paginao e Ordenao das negociaes - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
</p:dataTable>
<h:form>
Usando todas as colunas do nosso modelo Negociacao temos um resultado mais atraente:
Isso so apenas algumas das muitas funcionalidades que o p:dataTable oferece. Vale a pena vericar o
showcase e documentao no site do Primefaces.
,.: Exvncc:os: v:on1nTnntv vnnn t:s1nn ns Nvcoc:novs oo
Wvn Svnv:cv
) Como j termos os JARs necessrios adicionados ao projeto, para usar os componentes do Prime-
faces, devemos declarar o namespace do mesmo no arquivo index.xhtml. Acrescente o namespace
xmlns:p="http://primefaces.org/ui:
) Agora, o prximo passo preparar o Managed Bean. Ainda no projeto fj22-argentum-web, pasta
src/main/java, crie uma nova classe ArgentumBean dentro da pacote br.com.caelum.argentum.bean.
Use a anotao @ManagedBean e @SessionScoped em cima da classe:
package br.com.caelum.argentum.bean;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
@ManagedBean
@SessionScoped
Captulo - Introduo ao JSF e Primefaces - Exerccios: p:dataTable para listar as Negociaes do Web Service - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
public class ArgentumBean {
}
) Na classe ArgentumBean crie ummtodo preparaDados. Nele chamaremos o Web Service para inicializar
a lista de negociaes. Para garantir que o JSF chame o mtodo na criao do bean usaremos a anotao
@PostConstruct:
private List<Negociacao> negociacoes;
@PostConstruct
public void preparaDados() {
ClienteWebService cliente = new ClienteWebService();
this.negociacoes = cliente.getNegociacoes();
}
) Falta gerar um getter para o atributo negociacoes. Na classe digite getN e aperte Ctrl+Espao para usar
o auto-complete do Eclipse:
public List<Negociacao> getNegociacoes() {
return negociacoes;
}
) Abra novamente a pgina index.xhtml que se encontra na pasta WebContent. Dentro da tag <h:body>,
coloque o componente <p:panel> e remova o componente <h:outputText> do exerccio anterior:
<h:body>
<p:panel header="Negociaes" footer="Argentum Web">
</p:panel>
</h:body>
) Ainda na pgina index.xhtml, adicione o formulrio com a tabela dentro do componente p:panel:
<h:form id="listaNegociacao">
<p:dataTable var="negociacao" value="#{argentumBean.negociacoes}">
<!-- aqui vamos definir as colunas -->
</p:dataTable>
</h:form>
) Dentro do componente p:dataTable adicione as trs primeiras colunas :
<p:column headerText="Preo" >
<h:outputText value="#{negociacao.preco}" />
</p:column>
<p:column headerText="Quantidade">
Captulo - Introduo ao JSF e Primefaces - Exerccios: p:dataTable para listar as Negociaes do Web Service - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
<h:outputText value="#{negociacao.quantidade}" />
</p:column>
<p:column headerText="Volume">
<h:outputText value="#{negociacao.volume}" />
</p:column>
) Reinicie o Tomcat e acesse em seu navegador o endereo http://localhost:/-argentum-web/index.
xhtml. O resultado deve ser algo parecido com:
) Vamos colocar paginao na tabela. Adicione os atributos paginator="true" e rows="15". A denio
da tabela ca como (a primeira parte j existe, adicione somente os ltimos dois atributos):
<p:dataTable var="negociacao" value="#{argentumBean.negociacoes}"
paginator="true" rows="15">
Salve a pgina e acesse no seu navegador o endereo http://localhost:/-argentum-web/index.xhtml.
) (opcional) Deixe as colunas ordenveis, use o atributo sortBy em cada atributo, Por exemplo, para a
coluna que mostra o preo da negociao:
Captulo - Introduo ao JSF e Primefaces - Exerccios: p:dataTable para listar as Negociaes do Web Service - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
<p:column sortBy="#{negociacao.preco}" headerText="Preo" >
<h:outputText value="#{negociacao.preco}" />
</p:column>
Repare que usamos dentro do sortBy expression language (#{negociacao.preco}) para denir o valor a
ordenar.
Salve a pgina e acesse novamente em seu navegador: http://localhost:/-argentum-web/index.xhtml
) (opcional) Adicione mais uma coluna para a data da negociao. Para formatar a data usaremos umnovo
componente f:convertDateTime que recebe um pattern.
<p:column sortBy="#{negociacao.data}" headerText="Data">
<h:outputText value="#{negociacao.data.time}" >
<f:convertDateTime pattern="dd/MM/yyyy" />
</h:outputText>
</p:column>
,.:o O PnonXo Moovt V:vwCoN1nottvn
Generalizando o modelo acima, podemos dar nomes a cada uma das partes dessa nossa arquitetura. Quem
responsvel por apresentar os resultados na pgina web chamado de Apresentao (View).
O responsvel em ligar a View com o modelo, neste caso o ManagedBean, atua como um Controlador
(Controller).
As classes que representam suas entidades e as que te ajudam a armazenar e buscar os dados so chamadas
de Modelo (Model).
Esses trs formam um padro arquitetural chamado de MVC, ou Model View Controller. Ele pode sofrer
variaes de diversas maneiras. O que o MVC garante a separao de tarefas, facilitando assim a reescrita
de alguma parte, e a manuteno do cdigo.
Captulo - Introduo ao JSF e Primefaces - O Padro Model View Controller - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
A gura abaixo ilustrar o modelo MVC.
Captulo - Introduo ao JSF e Primefaces - O Padro Model View Controller - Pgina
C
Refatorao: os Indicadores da bolsa
Nunca cone em um computador que voc no pode jogar pela janela.
Steve Wozniak
8.: ANKt:sv TvcN:cn on notsn ov vntonvs
AAnlise Tcnica Grahsta uma escola econmica que temcomo objetivo avaliar o melhor momento para
compra e venda de aes atravs da anlise histrica e comportamental do ativo na bolsa.
Essa forma de anlise dos dados gerados sobre dados das negociaes (preo, volume, etc), usa grcos na
busca de padres e faz anlise de tendncias para tentar prever o comportamento futuro de uma ao.
Aanlise tcnica surgiu no incio do sculo , como trabalho de Charles Dowe Edward Jones. Eles criaram
a empresa DowJones &Company e foramos primeiros a inventaremndices para tentar prever o comporta-
mento do mercado de aes. Oprimeiro ndice era simplesmente uma mdia ponderada de 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 guras, ana-
listas podem determinar, com algum grau de acerto, como o mercado se comportar dali para a frente.
Munehisa Homna, no sculo , foi o primeiro a pesquisar os preos antigos do arroz para reconhecer pa-
dres. Ele fez isso e comeou a criar um catlogo grande de guras que se repetiam.
A estrela da manh, Doji, da gura abaixo, um exemplo de gura sempre muito buscada pelos analistas:
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Ela indica umpadro de reverso. Dizemque 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.
8.i INo:cnoonvs TvcN:cos
Uma das vrias formas de se aplicar as premissas da anlise tcnica grasta atravs do uso de indicadores
tcnicos. Indicadores so frmulas que manipulam dados das negociaes e tiram valores deles em busca
de informaes interessantes para recomendar as prximas aes para um ativo. Esse novo nmero, deter-
minstico e de fcil clculo por umcomputador. at de praxe que analistas nanceiros programemdiversas
dessas frmulas em macros VBScript, para v-las dentro do Excel.
comum, na mesma visualizao, termos uma combinao de grcos, indicadores e at dos candles:
Captulo - Refatorao: os Indicadores da bolsa - Indicadores Tcnicos - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Uma lista com os indicadores mais usados e como calcul-los pode ser encontrada em: http://stockcharts.
com/school/doku.php?id=chart_school:technical_indicators
Diversos livros tambm so publicados sobre o assunto. Os principais homebrokers fornecem sowares que
traam esses indicadores e muitos outros.
8. As mvo:ns movv:s
H diversos tipos de mdias mveis usadas em anlises tcnicas e elas so frequentemente usadas para in-
vestidores que fazem compras/vendas em intervalos muito maiores do que o intervalo de recolhimento de
dados para as candles. As mdias mais famosas so a simples, a ponderada, a exponencial e a Welles Wilder.
Vamos ver as duas primeiras, a mdia mvel simples e a mdia mvel ponderada.
Mvo:n movvt s:mvtvs
Amdia mvel simples calcula a mdia aritmtica de algumindicar do papel (emgeral o valor de fechamento)
para umdeterminado intervalo de tempo. Basta pegar todos os valores, somar e dividir pelo nmero de dias.
A gura a seguir mostra duas mdias mveis simples: uma calculando a mdia dos ltimos dias e outra
dos ltimos dias. O grco do valor das aes da antiga Sun Microsystems em .
Captulo - Refatorao: os Indicadores da bolsa - As mdias mveis - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Repare que a mdia mvel mais curta, a de dias, responde mais rpido aos movimentos atuais da ao,
mas pode gerar sinais errados a mdio prazo.
Em geral, estamos interessados na mdia mvel dos ltimos N dias e queremos denir 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 dias anteriores ao dia que estamos
interessados. Por exemplo: se pegamos o dia o, a mdia mvel simples para os ltimos dias a soma do
dia ao dia : ( + + ) / = {. A mdia mvel do dia para os ltimos dias : ( + + ) / . E assim
por diante.
Captulo - Refatorao: os Indicadores da bolsa - As mdias mveis - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
O grco anterior das mdias mveis da Sun pega, para cada dia do grco, a mdia dos dias anteriores.
Mvo:n movvt voNovnnon
Outra mdia mvel muito famosa a ponderada. Ela tambmleva emconta 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.
Por exemplo, para os dias a seguir:
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 dias, onde hoje tem peso , ontem tem peso e anteontem
tem peso . Se calcularmos a mdia mvel ponderada para o dia temos: (* + * + *) / = :{.o.
Captulo - Refatorao: os Indicadores da bolsa - As mdias mveis - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Amdia ponderada nos d uma viso melhor do que est acontecendo no momento coma 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 eciente quando estudamos uma srie a
longo prazo.
8.{ Exvncc:os: cn:nNoo :No:cnoonvs
) O clculo de uma mdia mvel feito a partir de uma lista de resumos do papel na bolsa. No nosso caso,
vamos pegar vrios Candlesticks, um para cada dia, e usar seus valores de fechamento.
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 {
private final List<Candlestick> candles;
public SerieTemporal(List<Candlestick> candles) {
this.candles = candles;
}
public Candlestick getCandle(int i) {
return this.candles.get(i);
}
public int getTotal() {
return this.candles.size();
}
}
Captulo - Refatorao: os Indicadores da bolsa - Exerccios: criando indicadores - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
) Vamos criar a classe MediaMovelSimples, dentro do novo pacote
br.com.caelum.argentum.indicadores. Essa classe ter o mtodo calcula que recebe a posio
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.
Comece fazendo apenas o cabealho desse mtodo:
public class MediaMovelSimples {
public double calcula(int posicao, SerieTemporal serie) {
return 0;
}
}
Aideia 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 da srie, ele deve calcular a
mdia dos valores de fechamento dos dias , e (j que nosso intervalo de dias).
Como essa uma lgica um pouco mais complexa, comearemos essa implementao pelos testes.
) Seguindo a ideia do TDD, faremos o teste antes mesmo de implementar a lgica da mdia. Assim como
voc j vemfazendo, 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 umteste para vericar 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 a. linha do cdigo abaixo:
public class MediaMovelSimplesTest {

@Test
public void sequenciaSimplesDeCandles() throws Exception {
SerieTemporal serie =
GeradorDeSerie.criaSerie(1, 2, 3, 4, 3, 4, 5, 4, 3);
MediaMovelSimples mms = new MediaMovelSimples();

Assert.assertEquals(2.0, mms.calcula(2, serie), 0.00001);


Assert.assertEquals(3.0, mms.calcula(3, serie), 0.00001);
Assert.assertEquals(10.0/3, mms.calcula(4, serie), 0.00001);
Assert.assertEquals(11.0/3, mms.calcula(5, serie), 0.00001);
Assert.assertEquals(4.0, mms.calcula(6, serie), 0.00001);
Assert.assertEquals(13.0/3, mms.calcula(7, serie), 0.00001);
Assert.assertEquals(4.0, mms.calcula(8, serie), 0.00001);
Captulo - Refatorao: os Indicadores da bolsa - Exerccios: criando indicadores - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
}
}
) 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.
Vnnnncs
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 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.
Leia mais sobre esse recurso em: http://docs.oracle.com/javase/../docs/guide/language/
varargs.html
Na classe GeradorDeSerie, faa o seguinte mtodo (ateno: no necessrio copiar o comentrio):
/**
* Serve para ajudar a fazer os testes.
*
* Recebe uma sequncia de valores e cria candles com abertura, fechamento,
* minimo e maximo iguais, mil de volume e data de hoje. Finalmente, devolve
* tais candles encapsuladas em uma Serie Temporal.
**/
public static SerieTemporal criaSerie(double... valores) {
List<Candlestick> candles = new ArrayList<Candlestick>();
for (double d : valores) {
candles.add(new Candlestick(d, d, d, d, 1000,
Calendar.getInstance()));
}
return new SerieTemporal(candles);
}
Agora que ele compila, rode a classe de teste. Ele falha, j que a implementao padro simplesmente
Captulo - Refatorao: os Indicadores da bolsa - Exerccios: criando indicadores - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
devolve zero!
) Volte classe principal MediaMovelSimples e implemente agora a lgica de negcio do mtodo calcula,
que j existe. O mtodo deve car parecido com o que segue:
public class MediaMovelSimples {

public double calcula(int posicao, SerieTemporal serie) {


double soma = 0.0;
for (int i = posicao - 2; i <= posicao; i++) {
Candlestick c = serie.getCandle(i);
soma += c.getFechamento();
}
return soma / 3;
}
}
Repare que iniciamos o for com posicao - 2. Isso signica que estamos calculando a mdia mvel dos
ltimos dias. Mais para frente, existe um exerccio opcional para parametrizar esse valor.
) Crie a classe MediaMovelPonderada anloga a MediaMovelSimples. Essa classe d peso para o dia atual,
peso para o dia anterior e o peso 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.
A implementao do mtodo calcula deve car bem parecida com isso:
public class MediaMovelPonderada {

public double calcula(int posicao, SerieTemporal serie) {


double soma = 0.0;
int peso = 1;

for (int i = posicao - 2; i <= posicao; i++) {


Candlestick c = serie.getCandle(i);
soma += c.getFechamento() * peso;
peso++;
}
return soma / 6;
}
}
Repare que o peso comea valendo 1 e vai sendo incrementado. O ltimo dia deve ter peso 3, que o
tamanho do nosso intervalo.
A diviso por 6 no nal a soma dos pesos para o intervalo de 3 dias ( + + = ).
) Depois a classe MediaMovelPonderada deve passar pelo seguinte teste:
Captulo - Refatorao: os Indicadores da bolsa - Exerccios: criando indicadores - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
public class MediaMovelPonderadaTest {
@Test
public void sequenciaSimplesDeCandles() {
SerieTemporal serie =
GeradorDeSerie.criaSerie(1, 2, 3, 4, 5, 6);
MediaMovelPonderada mmp = new MediaMovelPonderada();
//ex: calcula(2): 1*1 + 2*2 +3*3 = 14. Divide por 6, da 14/6
Assert.assertEquals(14.0/6, mmp.calcula(2, serie), 0.00001);
Assert.assertEquals(20.0/6, mmp.calcula(3, serie), 0.00001);
Assert.assertEquals(26.0/6, mmp.calcula(4, serie), 0.00001);
Assert.assertEquals(32.0/6, mmp.calcula(5, serie), 0.00001);
}
}
Rode o teste e veja se passamos!
) (opcional) Crie um teste de unidade em uma nova classe SerieTemporalTest, que verique 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. Rvvn1onnXo
Refatorao uma tcnica controlada para reestruturar um trecho de cdigo existente, alterando sua
estrutura interna sem modicar seu comportamento externo. Consiste em uma srie de pequenas
transformaes que preservam o comportamento inicial. Cada transformao (chamada de refatorao)
reete em uma pequena mudana, mas uma sequncia de transformaes pode produzir uma signicante
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 danicado durante a reestruturao.
Martin Fowler
Emoutras palavras, refatorao o processo de modicar umtrecho de cdigo j escrito, executando peque-
nos passos (baby-steps) semmodicar 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 ganharamnomes que identicamsua utilidade (veremos algumas
nas prximas sees). Alm disso, Martin Fowler escreveu o livro Refactoring: Improving the Design of
Captulo - Refatorao: os Indicadores da bolsa - Refatorao - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Existing Code, onde descreve em detalhes as principais.
Algumas so to corriqueiras, que o prprio Eclipse inclui um menu com diversas refatoraes que ele
capaz de fazer por voc:
8.o Exvncc:os: Pn:mv:nns nvvn1onnovs
) Temos usado no texto sempre o termo candle em vez de Candlestick. Essa nomenclatura se propagou
no nosso dia-a-dia, tornando-se parte do nosso modelo. Refatore o nome da classe Candlestick para
Candle no pacote br.com.caelum.argentum.modelo.
Dica: Use ctrl + shift + T para localizar e abrir as classes.
H vrias formas de se fazer isso no Eclipse. Pelo Package Explorer, podemos selecionar a classe e apertar
F. Ou, se estivermos dentro da classe, podemos colocar o cursor sobre o nome dela e usar o atalho alt
+ shift + R, que renomeia classes, mtodos, variveis, etc.
Captulo - Refatorao: os Indicadores da bolsa - Exerccios: Primeiras refatoraes - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
) 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 do mtodo abaixo, coloque o cursor na varivel c e use o alt + shift + I. (Alternativamente,
use ctrl + 1 Inline local variable)
public double calcula(int posicao, SerieTemporal serie) {
double soma = 0.0;
for (int i = posicao - 2; i <= posicao; i++) {
Candle c = serie.getCandle(i);
soma += c.getFechamento();
}
return soma / 3;
}
O novo cdigo, ento car assim:
public double calcula(int posicao, SerieTemporal serie) {
double soma = 0.0;
for (int i = posicao - 2; i <= posicao; i++) {
soma += serie.getCandle(i).getFechamento();
}
return soma / 3;
}
No esquea de tirar os imports desnecessrios (ctrl + shift + O)!
) Finalmente, abra a classe CandlestickFactory e observe o mtodo constroiCandles. Escrevemos esse
mtodo no captulo de XML com um algoritmo para separar todos os negcios em vrios candles.
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 dizempara
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 nal.
Captulo - Refatorao: os Indicadores da bolsa - Exerccios: Primeiras refatoraes - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
No Eclipse, podemos aplicar a refatorao Extract Method. Basta ir at a classe CandlestickFactory e
selecionar essas linhas de cdigo dentro do mtodo constroiCandles e usar o atalho alt + shift + M,
nomeando o novo mtodo de criaEGuardaCandle e clique em OK.
Repare como a IDE resolve os parmetros e ainda substitui as chamadas ao cdigo repetido pela chamada
ao novo mtodo.
) No mtodo constroiCandleParaData, observe que no bloco de cdigo dentro do for invocamos
negociacao.getPreco() quatro vezes.
// ...
for (Negociacao negociacao : negociacoes) {
volume += negociacao.getVolume();
if (negociacao.getPreco() > maximo) {
maximo = negociacao.getPreco();
}
if (negociacao.getPreco() < minimo) {
minimo = negociacao.getPreco();
}
}
// ...
Uma forma de deixar o cdigo mais limpo e evitar chamadas desnecessrias seria extrair para uma varivel
local.
Captulo - Refatorao: os Indicadores da bolsa - Exerccios: Primeiras refatoraes - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Para isso, usaremos a refatoraoExtract 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.
O Eclipse vai alterar o cdigo de forma que que parecido com:
// ...
for (Negociacao negociacao : negociacoes) {
volume += negociacao.getVolume();
double preco = negociacao.getPreco();
if (preco > maximo) {
maximo = preco;
}
if (preco < minimo) {
minimo = preco;
}
}
// ...
Observe que o Eclipse automaticamente substituiu as outras chamadas negociacoes.getPreco() por
preco.
) (Opcional) Aproveite e mude os nomes das outras classes que usam a palavra Candlestick: a Factory e
os Testes.
Rvvn1onnovs o:svoNvv:s
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.
8., Rvvn1onnovs mn:onvs
As refatoraes que zemos at agora so bastante simples e, por conta disso, o Eclipse pde fazer todo o
trabalho para ns!
H, contudo, refatoraes bem mais complexas que afetam diversas classes e podem mudar o design da
Captulo - Refatorao: os Indicadores da bolsa - Refatoraes maiores - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
aplicao. Algumas refatoraes ainda mais complexas chegam a modicar at a arquitetura do sistema!
Mas, quanto mais complexos as mudanas para chegar ao resultado nal, mais importante quebrar essa
refatorao em pedaos pequenos e rodar os testes a cada passo.
No nal dos prximos captulos faremos refatoraes que exibilizam nosso sistema e tornam muito mais
fcil trabalhar com os Indicadores Tcnicos que vimos mais cedo.
Exemplos de refatoraes maiores so:
Adicionar uma camada a um sistema;
Tirar uma camada do sistema;
Trocar uma implementao domstica por uma biblioteca;
Extrair uma biblioteca de dentro de um projeto;
etc...
8.8 D:sccssXo vmnctn: qcnNoo nvvn1onnn:
Captulo - Refatorao: os Indicadores da bolsa - Discusso em aula: quando refatorar? - Pgina
C
Grcos interativos com Primefaces
A nica pessoa educada aquela que aprendeu a aprender e a mudar.
Carl Rogers
.: Pon qcv csnn cnKv:cos:
Nossa aplicao apresenta os dados das negociaes tabularmente atravs do componente p:dataTable.
Alm disso, precisaremos apresentar os dados da SerieTemporal gracamente.
Grcos comprovadamente ajudamno entendimento dos dados e so mais fceis de analisar do que nmeros
dentro de uma tabela. mais simples reconhecer padres de imagens, principalmente para a anlise tcnica
de valores da bolsa.
Para o projeto argentum, apresentaremos os valores da SerieTemporal em um grco de linha, aplicando
algum indicador como abertura ou fechamento. Continuaremos com a biblioteca Primefaces que j vem
com suporte para vrios tipos de grcos.
.i Exvmvtos ov GnKv:cos
OPrimefaces j possui uma paleta de componentes para grcos. possvel utiliz-la para desenhar grcos
de linha, de barra, de torta, de rea, grcos para atualizao dinmica e at para Candles, entre outros.
Tambm podemos exportar e animar os grcos.
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
. U1:t:znNoo o Pn:mvvncvs
Vamos usar o Primefaces para gerar um grco que visualiza a evoluo dos valores da srie. Nosso projeto
est congurado e j podemos decidir qual grco utilizar. Para facilitar a deciso e ao mesmo tempo ver as
possibilidades e tipos de grcos disponveis, o showcase do Primefaces nos ajudar muito:
http://www.primefaces.org/showcase/ui/home.jsf
Nele encontramos o resultado nal e tambm o cdigo utilizado para a renderizao. Vamos progra-
mar usando o componente p:lineChart que deve mostrar os valores de abertura ou de fechamento da
SerieTemporal.
Captulo - Grcos interativos com Primefaces - Utilizando o Primefaces - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
O uso de componente simples, segue o cdigo de exemplo do showcase:
<p:lineChart id="category" value="#{chartBean.categoryModel}" legendPosition="e"
title="Category Chart" minY="0" maxY="200" style="height:300px;margin-top:20px"/>
Alm dos atributos para denir o layout (maxY e style) em forma de propriedades CSS, o ttulo (title) e a
posio da legenda (legendPosition), podemos ver que o componente recebe os dados atravs da Expression
Language chamando o Managed Bean #{chartBean.categoryModel}.
.{ Pnovn:vonovs vnnn vvnsoNnt:znn o cnKv:co
J vimos algumas propriedades do componente p:lineChart, mas existem outras bastante utilizadas, so
elas:
legendPosition - a posio da legenda - west (w), east (e), south (s), north (n)
xaxisLabel - nome do eixo X
yaxisLabel - nome do eixo y
minX, maxX - mnimo e mximo do valor no eixo X
minY, maxY - mnimo e mximo do valor no eixo X
title - o ttulo do grco
fill - true ou false, preenche o grco, no renderiza uma linha apenas
showMarkers - true ou false, habilita detalhes em cada ponto do grco
zoom - true ou false, habilita a funcionalidade de zoom no navegador
Todas as propriedades so opcionais. Na documentao do Primefaces h uma seo dedicada aos grcos
no qual podemos ver as classes relacionadas, atributos do componentes com exemplos de utilizao. Segue
uma parte da documentao ocial do Primefaces:
Captulo - Grcos interativos com Primefaces - Propriedades para personalizar o grco - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
A documentao do Primefaces est disponvel em forma de guia de usurio (PDF) e deve fazer parte do
dia-a-dia do desenvolvedor:
http://www.primefaces.org/documentation.html
Tambm h o tradicional Javadoc disponvel em: http://www.primefaces.org/docs/api/./. Devemos usar
ambos para descobrir funcionalidades e propriedades dos componentes.
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.
Captulo - Grcos interativos com Primefaces - Propriedades para personalizar o grco - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
JSF v CSS
O Primefaces ajuda o desenvolvedor atravs de seu suporte a temas, mas nem sempre ele su-
ciente, inclusive quando h uma equipe de designers responsvel em determinar a apresentao
da aplicao.
Apesar de trabalharmos comcomponentes, no nal o que enviado para o cliente puro HTML,
sendo assim, possvel aplicar estilos atravs de CSS para mudar o visual da aplicao.
A Caelum oferece o curso WD-{ | Desenvolvimento Web comHTML, CSS e JavaScript. Vol-
tado ao programador de interfaces preocupado com a semntica perfeita, estilos CSS poderosos
e JavaScripts corretos e funcionais. Um curso dedicado a criar interfaces Web com experincia
rica do usurio, estruturao correta e otimizaes.
. Dvv:N:Xo oo moovto oo cnKv:co
J temos uma noo de como renderizar grcos atravs de umcomponente so Primefaces. Odesenvolvedor
no precisa se preocupar como detalhes de JavaScript, de imagens e de animaes. Tudo isso encapsulado
dentro do componente seguindo boas prticas do mundo OO.
O que o componente no sabe ainda quais os dados que queremos exibir no grco. Para o componente,
esses dados representam o modelo (M), seguindo o padro MVC.
A classe principal do modelo a org.primefaces.model.chart.ChartModel e h lhas especializadas
como CartesianChartModel, PieChartModel ou BubbleChartModel. Em nosso projeto utilizaremos o
CartesianChartModel. No Javadoc podemos ver todas as lhas que devemos usar dependendo do grco
escolhido:
http://www.primefaces.org/docs/api/./org/primefaces/model/chart/ChartModel.html
Um CartesianChartModel recebe um ou mais ChartSeries. Uma ChartSeries representa uma linha no
grco do tipo p:lineChart. Ouseja, so os valores Xe Ypara renderizar a linha no chart. Como poderamos
renderizar mais do que uma linha no chart, um ChartModel pode receber vrias ChartSerie.
Vejo como ca o cdigo fcil de usar:
ChartSeries serieGrafico = new ChartSeries("Abertura");
serieGrafico.set("dia 1", 20.9);
serieGrafico.set("dia 1", 25.1);
serieGrafico.set("dia 1", 22.6);
serieGrafico.set("dia 1", 24.6);
CartesianChartModel modeloGrafico = new CartesianChartModel();
modeloGrafico.addSeries(serieGrafico);
Captulo - Grcos interativos com Primefaces - Denio do modelo do grco - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
ChartSeries recebe no construtor o rtulo (label) e atravs do mtodo set, passamos os valores X, Y. Agora
s falta gerar o modelo do grco dentro do ArgentumBean. por exemplo:
@ManagedBean
@SessionScoped
public class ArgentumBean {
private List<Negociacao> negociacoes;
private CartesianChartModel modelo;
@PostConstruct
void preparaDados() {
ClienteWebService cliente = new ClienteWebService();
this.negociacoes = cliente.getNegociacoes();
ChartSeries serieGrafico = new ChartSeries("Abertura");
serieGrafico.set("1", 300.06);
serieGrafico.set("2", 230.48);
serieGrafico.set("3", 311.12);
serieGrafico.set("4", 298.14);
this.modelo = new CartesianChartModel();
this.modelo.addSeries(serieGrafico);
}
public List<Negociacao> getNegociacoes() {
return negociacoes;
}
public ChartModel getModeloGrafico() {
return modelo;
}
}
No index.xhtml usaremos o componente p:lineChart da forma mais simples chamando o mtodo
getModeloGrafico do ArgentumBean dentro do p:panel:
<p:panel header="Negociaes" footer="Argentum Web">
<p:lineChart value="#{argentumBean.modeloGrafico}" title="PETR4" />"
<!-- cdigo da tabela omitido -->
Captulo - Grcos interativos com Primefaces - Denio do modelo do grco - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
.o IsotnNoo n API oo Pn:mvvncvs: nn:xo ncovtnmvN1o
O que acontecer se precisarmos criar dois grcos de indicadores diferentes? Vamos copiar e colar todo
aquele cdigo e modicar apenas as partes que mudam? E se precisarmos alterar algo na gerao do modelo?
Essas mudanas sero fceis se tivermos o cdigo todo espalhado pelo nosso programa?
Os princpios de orientao a objetos e as boas prticas de programao podem nos ajudar nesses
casos. Vamos encapsular a maneira como o modelo do grco criado dentro de uma classe, a
GeradorModeloGrafico.
Essa classe deve ser capaz de gerar o modelo com os dados que quisermos. Mas... se ela receber os dados
para gerar o grco, como receberemos esses dados?
fcil notar que no uma boa ideia pedir um CartesianChartModel para quem quiser usar o
CartesianChartModel! Se passarmos um CartesianChartModel, no dia que em precisssemos trocar um
ChartModel por outro o impacto dessa mudana seria muito maior: afetaramos no apenas essa classe, mas
todas as que a utilizam.
Vamos encapsular inclusive a passagem dos dados para o grco: a partir de uma SerieTemporal e do in-
tervalo que desejamos plotar, a prpria classe GeradorModeloGrafico se encarregar de traduzir essas infor-
maes em um CartesianChartModel:
public class GeradorModeloGrafico {
private SerieTemporal serie;
private int comeco;
private int fim;
public GeradorModeloGrafico(SerieTemporal serie, int comeco, int fim) {
this.serie = serie;
this.comeco = comeco;
this.fim = fim;
}
}
Captulo - Grcos interativos com Primefaces - Isolando a API do Primefaces: baixo acoplamento - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
E, quem for usar essa classe, far:
SerieTemporal serie = criaSerie(1,2,3,4,5,6,7,8,8,9,9,4,3,2,2,2,2);
GeradorModeloGrafico g = new GeradorModeloGrafico(serie, 2, 10);
Repare como esse cdigo de teste no possui nada que o ligue ao ChartModel especicamente. O dia em que
precisarmos mudar, apenas a classe GeradorModeloGrafico ser alterada. Encapsulamento!
Vamos encapsular tambm a gerao do ChartSeries. Para criar o grco, precisamos colocar algumas in-
formaes como ttulo e eixos. E, para desenhar a linha do grco, chamaremos o plotaMediaMovelSimples.
public class GeradorModeloGrafico {
private final SerieTemporal serie;
private final int comeco;
private final int fim;
private CartesianChartModel modeloGrafico;
public GeradorModeloGrafico(SerieTemporal serie, int comeco, int fim) {
this.serie = serie;
this.comeco = comeco;
this.fim = fim;
this.modeloGrafico = new CartesianChartModel();
}
public void plotaMediaMovelSimples() {
MediaMovelSimples indicador = new MediaMovelSimples();
LineChartSeries chartSerie = new LineChartSeries("MMS - Fechamento");
for (int i = comeco; i <= fim; i++) {
double valor = indicador.calcula(i, serie);
chartSerie.set(i, valor);
}
this.modeloGrafico.addSeries(chartSerie);
}
public ChartModel getModeloGrafico() {
return this.modeloGrafico;
}
}
Vamos analisar esse cdigo detalhadamente. O construtor recebe os dados da srie temporal e, alm de
gravar essas informaes nos atributos, ele cria o objeto que receber os dados, o CartesianChartModel em
si, que guardado no atributo modeloGrafico.
Captulo - Grcos interativos com Primefaces - Isolando a API do Primefaces: baixo acoplamento - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
O mtodo plotaMediaMovelSimples cria um objeto da MediaMovelSimples e varre a SerieTemporal rece-
bida para calcular o conjunto de dados para o modelo do grco.
Por m, o mtodo getModeloGrafico devolve o modelo. Repare que o retorno do tipo ChartModelo, a classe
me do CartesianChartModel. boa prtica deixar nossa classe a mais genrica possvel para funcionar com
qualquer tipo de mtodo.
Veja como ca o programa dentro do ArgentumBean:
@ManagedBean
@SessionScoped
public class ArgentumBean {
private List<Negociacao> negociacoes;
private ChartModel modeloGrafico;
@PostConstruct
void preparaDados() {
ClienteWebService cliente = new ClienteWebService();
this.negociacoes = cliente.getNegociacoes();
List<Candle> candles = new CandlestickFactory().constroiCandles(negociacoes);
SerieTemporal serie = new SerieTemporal(candles);
GeradorModeloGrafico gerador =
new GeradorModeloGrafico(serie, 2, serie.getTotal() - 1);
gerador.plotaMediaMovelSimples();
this.modeloGrafico = gerador.getModeloGrafico();
}
public ChartModel getModeloGrafico() {
return this.modeloGrafico;
}
public List<Negociacao> getNegociacoes() {
return this.negociacoes;
}
}
Note que, para quem usa o GeradorModeloGrafico nem d para saber como ele gera o modelo. um cdigo
encapsulado, exvel, pouco acoplado e elegante: usa boas prticas de OO.
Captulo - Grcos interativos com Primefaces - Isolando a API do Primefaces: baixo acoplamento - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
., Pnnn snnvn mn:s: Dvs:cN Pn11vnNs Fnc1onv Mv1noo v Bc:t-
ovn
Dois famosos design patterns do GoF so o Factory Method e o Builder - e estamos usando ambos.
Eles so chamados de padres de criao (creational patterns), pois nos ajudama criar objetos complicados.
Afactory usada pelo GeradorDeSerie. Aideia que criar umobjeto SerieTemporal diretamente compli-
cado. 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 nal (o grco) e encapsular
a complexidade disso.
Leia mais sobre esses e outros Design Patterns no livro do GoF.
Captulo - Grcos interativos com Primefaces - Para saber mais: Design Patterns Factory Method e Builder - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
JFnvvCnnn1
O JFreeChart uma biblioteca famosa para desenho de grcos, independente da tecnologia
JSF. um projeto de soware livre iniciado em e que tem ampla aceitao pelo mercado,
funcionando at em ambientes Java ..
Alm do fato de ser livre, possui a vantagem de ser bastante robusta e exvel. possvel us-la
para desenhar grcos de pontos, de barra, de torta, de linha, grcos nanceiros, gantt charts,
em D ou D e muitos outros. Consegue dar sada em JPG, PNG, SVG, EPS e at mesmo exibir
em componentes Swing.
O site ocial possui links para download, demos e documentao:
http://www.jfree.org/jfreechart/
Existe um livro ocial do JFreeChart escrito pelos desenvolvedores com exemplos e explicaes
detalhadas de vrios grcos diferentes. Ele pago e pode ser obtido no site ocial. Alm disso,
h muitos tutoriais gratuitos na Internet.
.8 Exvncc:os: GnKv:cos comPn:mvvncvs
) Dentro da pasta src/main/java crie a classe GeradorModeloGrafico no pacote
br.com.caelum.argentum.grafico para encapsular a criao do modelo do grco.
Use os recursos do Eclipse para escrever esse cdigo! Abuse do ctrl + espao, do ctrl + 1 e do ctrl
+ shift + O.
public class GeradorModeloGrafico {
// atributos: serie, comeco, fim e grafico
// (todos gerados com Ctrl + 1, conforme voc criar o construtor)
// importe as classes com Ctrl + Shift + O
Captulo - Grcos interativos com Primefaces - Exerccios: Grcos com Primefaces - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
public GeradorModeloGrafico(SerieTemporal serie, int comeco, int fim) {
this.serie = serie;
this.comeco = comeco;
this.fim = fim;
this.modeloGrafico = new CartesianChartModel();
}
public void plotaMediaMovelSimples() {
MediaMovelSimples indicador = new MediaMovelSimples();
LineChartSeries chartSerie = new LineChartSeries("MMS - Fechamento");
for (int i = comeco; i <= fim; i++) {
double valor = indicador.calcula(i, serie);
chartSerie.set(i, valor);
}
this.modeloGrafico.addSeries(chartSerie);
}
public ChartModel getModeloGrafico() {
return this.modeloGrafico;
}
}
) Vamos usar o GeradorModeloGrafico no ArgentumBean. Abra a classe ArgentumBean e crie um novo
atributo que representa o modelo do grco. preciso importar a classe ChartModel do Primefaces (Ctrl
+ Shift + O):
private ChartModel modeloGrafico;
Gere o getter para este atributo.
Dica: Na classe ArgentumBean escreva getM e aperte Ctrl + Espao. O Eclipse sugerir o getter para o
atributo modeloGrafico.
) Na classe ArgentumBean, procure o mtodo preparaDados. neste mtodo que criaremos
uma SerieTemporal baseada na lista de negociaes do Web Service. Depois usaremos o
GeradorModeloGrafico para criar o modelo grco:
List<Candle> candles = new CandlestickFactory().constroiCandles(this.negociacoes);
SerieTemporal serie = new SerieTemporal(candles);
GeradorModeloGrafico gerador =
new GeradorModeloGrafico(serie, 2, serie.getTotal() - 1);
gerador.plotaMediaMovelSimples();
Captulo - Grcos interativos com Primefaces - Exerccios: Grcos com Primefaces - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
this.modeloGrafico = gerador.getModeloGrafico();
) Falta usar o componente para renderizar o grco na tela. Abra a pgina index.xhtml que se encontra na
pasta WebContent.
Na pgina procure o componente p:panel. Logo depois da abertura da tag do p:panel mas antes do
h:form adicione o componente p:lineChart:
<p:lineChart value="#{argentumBean.modeloGrafico}" legendPosition="e" title="PETR4"/>
Salve a pgina. Reinicie o Tomcat e acesse emseu navegador: http://localhost:/-argentum-web/index.
xhtml
Captulo - Grcos interativos com Primefaces - Exerccios: Grcos com Primefaces - Pgina
C
Aplicando Padres de projeto
Estamos todos na sarjeta, mas alguns de ns esto olhando para as estrelas.
Oscar Wilde
:o.: Nossos :No:cnoonvs v o ovs:cN vn11vnN S1nn1vcv
Nosso gerador de grcos j est interessante, mas no momento ele s consegue plotar a mdia mvel sim-
ples da srie. Nosso cliente certamente precisar de outros indicadores tcnicos como o de Mdia Mvel
Ponderada ou ainda indicadores mais simples como um indicador de Abertura ou de Fechamento.
Esses indicadores, similarmente MediaMovelSimples, devem calcular o valor de uma posio do grco
baseado na SerieTemporal que ele atende.
Ento, com o indicador criado, precisaremos que o GeradorModeloGrafico consiga plotar cada um desses
grcos tambm. Terminaremos com uma crescente classe GeradorModeloGrafico com mtodos extrema-
mente parecidos:
public class GeradorModeloGrafico {
//...
public void plotaMediaMovelSimples() {
MediaMovelSimples indicador = new MediaMovelSimples();
LineChartSeries chartSerie = new LineChartSeries("MMS - Fechamento");
for (int i = comeco; i <= fim; i++) {
double valor = indicador.calcula(i, serie);
chartSerie.set(i, valor);
}
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
this.modeloGrafico.addSeries(chartSerie);
}
public void plotaMediaMovelPonderada() {
MediaMovelPonderada indicador = new MediaMovelPonderada();
LineChartSeries chartSerie = new LineChartSeries("MMP - Fechamento");
for (int i = comeco; i <= fim; i++) {
double valor = indicador.calcula(i, serie);
chartSerie.set(i, valor);
}
this.modeloGrafico.addSeries(chartSerie);
}
//...
}
Oproblema que cada vez que criarmos umindicador tcnico diferente, umnovo 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?
A orientao a objetos nos d a resposta: polimorhsmo! Repare que nossos dois indicadores possuem a
mesma assinatura de mtodo, parece at que eles assinaram o mesmo contrato. Vamos denir ento a inter-
face Indicador:
public interface Indicador {
public abstract double calcula(int posicao, SerieTemporal serie);
}
Podemos fazer as classes MediaMovelSimples e MediaMovelPonderada implementarem a interface
Indicador. Com isso, podemos criar apenas um mtodo na classe do grco que recebe um Indicador
qualquer:
public class GeradorModeloGrafico {
...
public void plotaIndicador(Indicador indicador) {
LineChartSeries chartSerie = new LineChartSeries(indicador.toString());
Captulo - Aplicando Padres de projeto - Nossos indicadores e o design pattern Strategy - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
for (int i = comeco; i <= fim; i++) {
double valor = indicador.calculaPara(i, serie);
chartSerie.set(i, valor);
}
this.modeloGrafico.addSeries(chartSerie);
}
...
}
Na hora de desenhar os grcos, chamaremos sempre o plotaIndicador, passando como parmetro qual-
quer classe que seja um Indicador:
GeradorModeloGrafico gerador = new GeradorModeloGrafico(serie, 2, 40);
gerador.plotaIndicador(new MediaMovelSimples());
gerador.plotaIndicador(new MediaMovelPonderada());
A ideia de usar uma interface comum ganhar polimorsmo e poder trocar os indicadores. Se usamos um
Indicador, podemos trocar a classe especca sem mexer em nosso cdigo e ganhamos exibilidade. Pode-
mos ainda criar novos indicadores que implementem a interface e pass-los para o grco sem que nunca
mais mexamos na classe GeradorModeloGrafico.
Por exemplo, imagine que queremos um grco simples que mostre apenas os preos de fechamento. Pode-
mos considerar a evoluo dos preos de fechamento como um Indicador:
public class IndicadorFechamento implements Indicador {
public double calcula(int posicao, SerieTemporal serie) {
return serie.getCandle(posicao).getFechamento();
}
}
Ou criar ainda classes como IndicadorAbertura, IndicadorMaximo, etc.
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. Esse o design pattern chamado de Strategy.
Captulo - Aplicando Padres de projeto - Nossos indicadores e o design pattern Strategy - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Dvs:cN Pn11vnNs
Design Patterns so aquelas solues catalogadas para problemas clssicos de orientao a ob-
jetos, como este que temos no momento: encapsular e ter exibilidade.
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.
:o.i Exvncc:os: nvvn1onnNoo vnnn cmn :N1vnvncv v csnNoo
nvmos 1vs1vs
) J que nossas classes de mdias mveis so indicadores tcnicos, comearemos extraindo a interface de
um Indicador a partir dessas classes.
Abra a classe MediaMovelSimples e use o ctrl + Extract interface. Selecione o mtodo calcula e d o
nome da interface de Indicador:
Evvvc1:vv Jnvn
Item : Rera a objetos pelas suas interfaces
) Na classe MediaMovelPonderada coloque agora o implements Indicador nela.
Captulo - Aplicando Padres de projeto - Exerccios: refatorando para uma interface e usando bem os testes - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
public class MediaMovelPonderada implements Indicador {
...
}
) Vamos criar tambm uma classe para, por exemplo, ser o indicador do preo de fechamento,
o IndicadorFechamento, no pacote br.com.caelum.argentum.modelo, que implementa a interface
Indicador:
public class IndicadorFechamento implements Indicador {
@Override
public double calcula(int posicao, SerieTemporal serie) {
return serie.getCandle(posicao).getFechamento();
}
}
) De maneira anloga vamos criar o IndicadorAbertura, tambm no pacote
br.com.caelum.argentum.modelo, que implementa a interface Indicador:
public class IndicadorAbertura implements Indicador {
@Override
public double calcula(int posicao, SerieTemporal serie) {
return serie.getCandle(posicao).getAbertura();
}
}
) Volte para a classe GeradorModeloGrafico e altere o mtodo plotaMediaMovelSimples usando o atalho
alt + shi + C. Voc precisar alterar o nome para plotaIndicador e adicionar um parmetro. Veja com
ateno o screenshot abaixo:
Captulo - Aplicando Padres de projeto - Exerccios: refatorando para uma interface e usando bem os testes - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
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 chartSerie = new LineChartSeries(indicador.toString());
for (int i = comeco; i <= fim; i++) {
double valor = indicador.calcula(i, serie);
chartSerie.set(i, valor);
}
this.modeloGrafico.addSeries(chartSerie);
}
) 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:
public class MediaMovelSimples implements Indicador{
....
public String toString() {
return "MMS de Fechamento";
}
}
Sobrescreva na classe MediaMovelPonderada:
public class MediaMovelPonderada implements Indicador{
....
public String toString() {
return "MMP de Fechamento";
}
}
Tambm na classe IndicadorFechamento:
public class IndicadorFechamento implements Indicador {
....
public String toString() {
return "Fechamento";
}
Captulo - Aplicando Padres de projeto - Exerccios: refatorando para uma interface e usando bem os testes - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
}
E por ltimo na classe IndicadorAbertura:
public class IndicadorAbertura implements Indicador {
....
public String toString() {
return "Abertura";
}
}
:o. Exvncc:os ovc:oNn:s
) Nossos clculos de mdias mveis so sempre para o intervalo de dias. Faa com que o intervalo seja
parametrizvel. As classes devem receber o tamanho desse intervalo no construtor e usar esse valor no
algoritmo de clculo.
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 carem desatualizados aparecero com erros de compilao.
) 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.
Se voc julgar necessrio, acrescente mais testes sua aplicao refatorada.
:o.{ INo:cnoonvs mn:s Etnnonnoos v o Dvs:cN Pn11vnN Dvco-
nn1on
Vimos no captulo de refatorao que os analistas nanceiros fazemsuas anlises sobre indicadores mais ela-
borados, como por exemplo Mdias Mveis, que so calculadas a partir de outros indicadores. No momento,
nossos algoritmos de mdias mveis sempre calculam seus valores sobre o preo de fechamento. Mas, e se
quisermos calcul-las a partir de outros indicadores? Por exemplo, o que faramos se precisssemos da mdia
mvel simples do preo mximo, da abertura ou de outro indicador qualquer?
Criaramos classes como MediaMovelSimplesAbertura e MediaMovelSimplesMaximo? Que cdigo colo-
caramos l? Provavelmente, copiaramos o cdigo que j temos e apenas trocaramos a chamada do
getFechamento pelo getAbertura e getVolume.
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 cdigos idnticos em
lugares diferentes.
Captulo - Aplicando Padres de projeto - Exerccios opcionais - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
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:
MediaMovelSimples mms = new MediaMovelSimples(
new IndicadorFechamento());
// ... ou ...
MediaMovelSimples mms = new MediaMovelPonderada(
new IndicadorFechamento());
Repare na exibilidade desse cdigo. Oclculo de mdia ca 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:
public class MediaMovelSimples implements Indicador {
private final Indicador outroIndicador;
public MediaMovelSimples(Indicador outroIndicador) {
this.outroIndicador = outroIndicador;
}
// ... calcula ...
}
E, dentro do mtodo calcula, em vez de chamarmos o getFechamento, delegamos a chamada para o
outroIndicador:
@Override
public double calcula(int posicao, SerieTemporal serie) {
double soma = 0.0;
for (int i = posicao - 2; i <= posicao; i++) {
soma += outroIndicador.calcula(i, serie);
}
return soma / 3;
}
Nossa classe MediaMovelSimples recebe um outro indicador que modihca um pouco os valores de sada -
ele complementa o algoritmo da mdia! Passar um objeto que modica um pouco o comportamento do seu
uma soluo clssica para ganhar em exibilidade e, como muitas solues clssicas, ganhou um nome
nos design patterns de Decorator.
Captulo - Aplicando Padres de projeto - Indicadores mais Elaborados e o Design Pattern Decorator - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Tnmnvmv cmcomvos:1v:
Note que, agora, nossa MediaMovelSimples umIndicador e tambmtemumoutro Indicador.
J vimos antes outro tipo que se comporta da mesma forma, voc se lembra?
Assimcomo os componentes do Swing, nossa MediaMovelSimples se tornou tambmumexem-
plo de Composite.
:o. Exvncc:os: INo:cnoonvs mn:s vsvvn1os v oDvs:cNPn11vnN
Dvconn1on
) Faremos uma grande mudana agora: nossas mdias devemreceber como argumento umoutro indicador,
formando o design pattern Decorator, como visto na explicao.
Para isso, crie o construtor padro (sem parmetros) da MediaMovelSimples usando o atalho de sua pre-
ferncia:
a) Comece a escrever o nome da classe e mande autocompletar: Med<ctrl + espao>;
b) Use o criador automtico de construtores: ctrl + Constructor.
) Modique o construtor usando o atalho alt + shi + 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 + : e guarde esse valor em um novo
atributo, selecionando assign parameter to new eld.
Captulo - Aplicando Padres de projeto - Exerccios: Indicadores mais espertos e o Design Pattern Decorator - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
) Troque a implementao do mtodo calcula para chamar o calcula do outroIndicador:
public double calcula(int posicao, SerieTemporal serie) {
double soma = 0.0;
for (int i = posicao - 2; i <= posicao; i++) {
soma += outroIndicador.calcula(i, serie);
}
return soma / 3;
}
) 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.
) Modique tambm a classe MediaMovelPonderada para tambm ter um Decorator.
Isto , faa ela tambm receber um outroIndicador no construtor e delegar a chamada a esse indicador
no seu mtodo calcula, assim como zemos com a MediaMovelSimples.
) (opcional)Faa um teste unitrio na classe MediaMovelSimplesTest que use receba um
IndicadorAbertura vez do de fechamento. Faa tambm para mximo, mnimo ou outros que
desejar. Mas lembre-se de implementar os indicadores especcos.
Captulo - Aplicando Padres de projeto - Exerccios: Indicadores mais espertos e o Design Pattern Decorator - Pgina
C
Formulrios com JSF
::.: MvtnonnNoo n IN1vnvncv
At agora, ao acessar a aplicao pelo navegador, o grco e a tabela de negociaes sero gerados automa-
ticamente. No h nenhuma forma de personalizar o grco, como por exemplo denir o ttulo ou escolher
qual indicador queremos mostrar.
Vamos melhorar a interface e adicionar um formulrio que oferece para o usurio as seguintes opes:
Ttulo do grco
Tipo de indicador (abertura ou fechamento)
Tipo de mdia mvel (simples ou ponderada)
Alm disso, o formulrio deve validar a entrada de dados.
::.i ComvoNvN1vs ov vN1nnon
Para denir o ttulo do grco usaremos um simples input. A especicao JSF possui para isso um
componente h:inputText que foi reimplementado pelo Primefaces, sendo necessrio utilizar seu prexo
p:inputText.
muito comum bibliotecas estenderem a funcionalidade da especicao JSF usando o mesmo nome
do componente adicionando recursos no previstos pela especicao. J vimos isso com o componente
p:dataTable. O Primefaces estendeu o h:dataTable para, por exemplo, paginar a tabela e ordenar os ele-
mentos de maneira muito simples, entre vrias outras funcionalidades extras.
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Isso tambm acontece com p:inputText, por exemplo, ele recebe o tema congurado no Primefaces, em
nosso caso, o tema padro. Otema composto por umconjunto de CSSs que do a aplicao umvisual mais
atraente.
Igual aos demais componentes, usaremos expression language para ligar o componente ao nosso
ArgentumBean. Usando o componente p:inputText podemos recuperar o valor que o usurio digitou.
O nosso formulrio inicial ca como:
<h:form id="dadosGrafico">
<p:outputLabel for="titulo" value="Ttulo:"/>
<p:inputText id="titulo" value="#{argentumBean.titulo}"/>
</h:form>
uma boa prtica identicar os componentes atravs do atributo id. Aproveitamos essa id no componente
p:outputLabel dentro do atributo for. Assim o label ca associado com o p:inputText.
A classe ArgentumBean ganhou um atributo do tipo String que representa o titulo, alm do getter e setter
para ele:
@ManagedBean
@SessionScoped
public class ArgentumBean {
private String titulo;
//gettter e setter para o atributo titulo
//outros atributos e mtodos omitidos
}
::. Scnmv1vNoo o vonmctKn:o
Como j vimos, umformulrio no mundo JSF apresentado pela tag h:form. Os componentes de entrada de-
vemestar dentro dessa tag. Para recuperar os valores, associamos os componentes coma classe ArgentumBean
pela Expression Language.
Agora falta ainda chamar algum mtodo na classe ArgentumBean que realmente far algo com os dados sub-
metidos. Para isso o JSF prev comandos na especicao. So eles que causam a execuo de um mtodo
dentro de um Managed Bean.
Captulo - Formulrios com JSF - Submetendo o formulrio - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Veja o exemplo a seguir:
<h:form id="dadosGrafico">
<!-- outros componentes omitidos -->
<h:commandButton action="#{argentumBean.preparaDados}" value="Gerar grfico" />
</h:form>
Nesse exemplo, associamos o componente h:commandButton com o mtodo preparaDados da classe
ArgentumBean. Repare que usamos no atributo action a Expression Language. Ou seja, o comando que
dene qual mtodo chamar e no o formulrio como o padro no desenvolvimento que utiliza HTML
diretamente.
Oqcv ncoN1vcv qcnNoo o cscKn:o ct:cn No no1Xo:
Quando o usurio clica no boto Gerar grco, o JSF primeiro atribui ao atributo titulo de ArgentumBean
o ttulo digitado no formulrio e logo em seguida chama o mtodo preparaDados. Repare que esta ordem
importante, uma vez que o mtodo pode depender dos dados inseridos pelo usurio.
Tambm podemos usar mais do que um comando dentro do mesmo formulrio. Os comandos podem at
chamar mtodos diferentes:
<h:form id="dadosGrafico">
<h:commandButton action="#{argentumBean.listaNegociacoes}"
value="Listar negociaes" />
<h:commandButton action="#{argentumBean.preparaDados}"
value="Gerar grfico" />
</h:form>
Podemos trocar o visual do comando. No lugar de renderizarmos o comando como boto, utilizaremos um
link:
<h:form id="dadosGrafico">
<h:commandLink action="#{argentumBean.listaNegociacoes}"
value="Listar negociaes" />
<h:commandLink action="#{argentumBean.geraGrafico}"
value="Gerar grfico" />
</h:form>
Captulo - Formulrios com JSF - Submetendo o formulrio - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
O formulrio sempre ser submetido com uma requisio do tipo POST. A apresentao do comando (link
ou boto) apenas um detalhe visual.
n:vonmsvmvnv csnnK HTTP POST
importante saber que diferente da tag form no HTML, o h:form sempre envia uma requisio
HTTP do tipo POST sem a possibilidade de escolher o uma do tipo GET.
Isso ocorre porque o JSF tenta abstrair o mundo HTTP e assim ca mais perto do desenvolvi-
mento Desktop tradicional. Ou seja, no chamado alguma URL, e sim utilizado um compo-
nente do tipo comando que executa um mtodo ou evento dentro de um Managed Bean.
::.{ Vnt:onXo comJSF
Podemos agora denir um ttulo para cada gerao de grco, mas temos um problema: nada impede que o
usurio deixe o ttulo em branco, o que no faz sentido para nossa aplicao.
PnvvNcn:mvN1o onn:cn1on:o n1nnvvs oo n1n:nc1o nvqc:nvo
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
especicao.
<p:inputText id="titulo" value="#{argentumBean.titulo}" required="true"/>
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 denimos qual
componente ser utilizado para mostrar essa mensagem.
Ex:n:Noo mvNsncvNs comn:mvssncvs
O JSF possui o componente h:messages que exibe para o usurio as mensagens geradas pelo framework,
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>
<h:messages />
....
Pronto, quando o formulrio for submetido com o campo ttulo em branco o JSF exibir automaticamente a
mensagem de validao.
Captulo - Formulrios com JSF - Validao com JSF - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Vnt:onNoo o 1nmnNno oo cnmvo
Conseguimos impedir que o usurio deixe em branco o ttulo do grco, mas nada impede que ele digite
apenas uma letra, algo que com certeza no ser de grande ajuda para quem estiver analisando o grco.
Alm do simples atributo required, o JSF vem com uma srie de validadores que podem ser utilizados com
seus componentes. Utilizaremos o f:validadeLength. Ele deve ser adicionado dentro da tag que ele validar:
<p:inputText id="titulo" value="#{argentumBean.titulo}" required="true">
<f:validateLength minimum="3" />
</p:inputText>
O atributo minimum determina o tamanho mnimo do campo, em nosso caso, trs.
Vnt:onXo No tnoo oo svnv:oon
Para o usurio o JSF parece realizar uma validao no lado do cliente, mas na verdade toda vali-
dao feita no lado do servidor. Isso to verdade, que no houve a necessidade de JavaScript
no lado do cliente.
Umn nt1vnNn1:vn :N1vnvssnN1v: v:cnowt
Utilizamos o componente h:messages mensagens. O Primefaces tem uma alternativa interessante, o com-
ponente p:growl. Este componente tem a mesma funcionalidade de h:messages, mas sua mensagem utua
no canto superior direito e desaparece depois de alguns segundos:
....
<h:form>
<!-- Substituindo h:messages por p:growl -->
<p:growl />
....
::. OncnN:znXo oos comvoNvN1vs
Criamos o formulrio para o usurio denir os dados do grco. Vejamos mais uma vez o cdigo, desta vez,
completo:
Captulo - Formulrios com JSF - Organizao dos componentes - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
<h:form id="dadosGrafico">
<p:growl />
<p:outputLabel value="Ttulo:" />
<p:inputText id="titulo" value="#{argentumBean.titulo}" required="true">
<f:validateLength minimum="3" />
</p:inputText>
<h:commandLink action="#{argentumBean.preparaDados}" value="Gerar grfico" />
</h:form>
No h nada errado com este cdigo, mas todos os componentes dentro do h:form sero apresentados na
horizontal:
OncnN:znNoo os comvoNvN1vs Nn 1vtn comn:vnNvtGn:o
Para melhorar o JSF j possui umcomponente que ajuda na organizao. Oh:panelGrid sabe alinhar outros
componentes, ideal para nosso caso. Basta denir a quantidade de colunas que queremos usar dentro do grid
e o componente faz o resto. Segue o mesmo exemplo mas com h:panelGrid:
<h:form id="dadosGrafico">
<p:growl />
<h:panelGrid colunms="2">
<p:outputLabel value="Ttulo:" />
<p:inputText id="titulo" value="#{argentumBean.titulo}"
required="true">
<f:validateLength minimum="3" />
</p:inputText>
<h:commandLink action="#{argentumBean.preparaDados}" value="Gerar grfico" />
</h:panelGrid>
</h:form>
Com o grid denido o comando ca abaixo do input:
Por m vamos colocar o formulrio dentro de um painel, aplicando novamente o componente p:panel:
Captulo - Formulrios com JSF - Organizao dos componentes - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
<p:panel header="Dados do grfico">
<p:growl />
<h:form id="dadosGrafico">
<!-- outros componentes omitidos-->
</h:form>
</p:panel>
::.o Exvncc:os: Exvcc1nNoo toc:cn v vnt:onNoo vN1nnon
Vamos permitir que o usurio digite o ttulo do grco e que no seja aceito valor em branco, inclusive o
tamanho deve ter no mnimo trs caracteres.
) No classe ArgentumBean, crie o atributo que guardar o ttulo digitado pelo usurio:
@ManagedBean
@SessionScoped
public class ArgentumBean {
private String titulo; //crie os getters e setters
//outros atributos e mtodos omitidos
}
) Abra a pgina index.xhtml e adicione um label e um componente de entrada para o ttulo do grco.
Utilize expression language para ligar o componente de entrada ao atributo titulo de ArgentumBean.
Crie um novo formulrio dentro de um novo painel.
Logo depois da tag h:body adicione:
<p:panel header="Dados do grfico">
<h:form id="dadosGrafico">
<h:panelGrid columns="2">
<p:outputLabel for="titulo" value="Ttulo:"/>
<p:inputText id="titulo" value="#{argentumBean.titulo}"/>
</h:panelGrid>
</h:form>
</p:panel>
) No podemos deixar que ttulo seja informado embranco, para isso, adicione emp:inputText o atributo
required="true".
Captulo - Formulrios com JSF - Exerccios: Executando lgica e validando entrada - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
...
<p:inputText id="titulo" value="#{argentumBean.titulo}" required="true"/>
...
) Validade tambm se o ttulo tem no mnimo trs caracteres atravs da tag f:validadeLength:
...
<p:inputText id="titulo" value="#{argentumBean.titulo}" required="true">
<f:validateLength minimum="3" />
</p:inputText>
...
) Utilize o componente p:growl do Primefaces para exibir as mensagens de validao. Adicione-o como
primeiro componente dentro de h:form e antes do h:panelGrid. Adicione apenas o p:growl
...
<h:form id="dadosGrafico">
<p:growl/>
<h:panelGrid columns="2">
...
) Por m, no componente p:lineChart, altere o atributo title para que ele aponte para o atributo titulo
de ArgentumBean atravs de expression language:
<p:lineChart value="#{argentumBean.modeloGrafico}" legendPosition="e"
title="#{argentumBean.titulo}" />
) Precisamos submeter o formulrio. Faremos isso atravs do componente h:commandLink que executar o
mtodo preparaDados de ArgentumBean. Adicione-o logo aps o p:inputText do ttulo.
...
<h:commandLink action="#{argentumBean.preparaDados}" value="Gerar grfico" />
...
) No queremos mais executar o mtodo preparaDados quando a pgina for aberta pela primeira vez, dei-
xaremos a execuo deste mtodo sob responsabilidade exclusiva do componente h:commandLink.
Comente a anotao @PostConstruct do mtodo preparaDados de ArgentumBean com //:
@ManagedBean
@SessionScoped
public class ArgentumBean {
...
// @PostConstruct
public void preparaDados() {
...
Captulo - Formulrios com JSF - Exerccios: Executando lgica e validando entrada - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
) Como no podemos exibir o grco enquanto o ChartModel modeloGrafico estiver null, precisamos
fazer uma pequena modicao na pgina index.xhtml. Adicione o parmetro rendered no p:panel do
grco conforme abaixo:
<p:panel header="Negociaes" footer="Argentum Web"
rendered="#{argentumBean.modeloGrafico != null}">
Desta forma, o painel do grco s ser exibido depois que o mtodo preparaDados for chamado atravs
do h:commandLink.
) Salve a pgina e reinicie o Tomcat. Teste as alteraes: http://localhost:/-argentum-web/index.xhtml
::., ComnoBox vnnn svtvc:oNnn os :No:cnoonvs
Permitimos ao usurio denir o ttulo do grco, mas isso ainda no suciente. Precisamos de alguma
maneira permitir a escolha entre os diferentes tipos de indicadores e mdias que j criamos.
Svtvc:oNnNoo :No:cnoonvs v mvo:ns comv:svtvc1ONvMvNc
Para selecionar o indicador base (abertura ou fechamento) e as mdias (simples ou ponderada), usaremos
um combo box. Igual ao inputText h um componente da especicao, mas usaremos a reimplementao
do Primefaces que possui um design mais atraente.
O componente se chama p:selectOneMenu e cada opo dentro do combo box apresentada atravs de um
f:selectItem. Um f:selectItem recebe um valor e um label. Dessa maneira podemos escrever:
<p:outputLabel for="indicador" value="Indicador:" />
<p:selectOneMenu id="indicador">
<f:selectItem itemValue="IndicadorAbertura" itemLabel="Abertura" />
<f:selectItem itemValue="IndicadorFechamento" itemLabel="Fechamento" />
</p:selectOneMenu>
Novamente seguimos a boa prtica de identicar o componente. Falta apenas recuperar o valor selecionado
no ArgentumBean. Sem surpresa, usaremos expression language no componente selectOneMenu dentro do
atributo value.
Captulo - Formulrios com JSF - ComboBox para selecionar os indicadores - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
<p:selectOneMenu id="indicador" value="#{argentumBean.nomeIndicador}">
<f:selectItem itemValue="IndicadorAbertura" itemLabel="Abertura" />
<f:selectItem itemValue="IndicadorFechamento" itemLabel="Fechamento" />
</p:selectOneMenu>
No ArgentumBean recebemos esse valor como String:
@ManagedBean
@SessionScoped
public class ArgentumBean {
private String nomeIndicador; //getter e setter
//outros atributos e mtodos omitidos
}
Alm do design mais elegante, o p:selectOneMenu pode ser criado dinamicamente pelo componente
f:selectItens e possui funcionalidades de ltro e edio. H vrios exemplos no showcase.
O segundo combo box para as mdias. A nica diferena que sua escolha opcional. Por isso haver um
componente do tipo f:selectItem com um itemValue vazio. Veja como ca cdigo:
<p:outputLabel value="Mdia:" />
<p:selectOneMenu id="media" value="#{argentumBean.nomeMedia}">
<f:selectItem itemValue="" itemLabel="Escolhe um" />
<f:selectItem itemValue="MediaMovelSimples" itemLabel="Simples" />
<f:selectItem itemValue="MediaMovelPonderada" itemLabel="Ponderada" />
</p:selectOneMenu>
Assim como o componente anterior, teremos mais um atributo no ArgentumBean com seus getter e setter:
@ManagedBean
@SessionScoped
public class ArgentumBean {
Captulo - Formulrios com JSF - ComboBox para selecionar os indicadores - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
private String nomeMedia; //getter e setter
//outros atributos e mtodos omitidos
}
::.8 Exvncc:os: Comvtv1nNoo o FonmctKn:o
) Na classe ArgentumBean criaremos mais dois atributos, umpara o nome do indicador e outro para a nome
da mdia. No mtodo vamos apenas imprimir os valores
@ManagedBean
@SessionScoped
public class ArgentumBean {
//atributos e outros mtodos omitidos
private String nomeIndicador; //getter e setter
private String nomeMedia; //getter e setter
//@PostConstruct
public void preparaDados() {
System.out.println("Indicador: " + nomeIndicador + ", " + nomeMedia);
//implementao omitida
}
}
) Abra a pgina index.xhtml que se encontra na pasta WebContent.
Procure a tag p:inputText. Diretamente abaixo dessa tag e antes do h:commandLink vamos criar dois
combo boxes para o nome do indicador e a para o nome da mdia.
Adicione logo abaixo p:inputText o primeiro h:selectOneMenu:
<p:outputLabel value="Indicador:" for="indicador" />
<p:selectOneMenu id="indicador" value="#{argentumBean.nomeIndicador}">
<f:selectItem itemValue="IndicadorAbertura" itemLabel="Abertura" />
<f:selectItem itemValue="IndicadorFechamento" itemLabel="Fechamento" />
</p:selectOneMenu>
) Falta o segundo combo box para escolher a mdia. Adicione depois do primeiro p:selectOneMenu:
<p:outputLabel value="Mdia:" for="media" />
<p:selectOneMenu id="media" value="#{argentumBean.nomeMedia}">
<f:selectItem itemValue="" itemLabel="Escolhe um" />
Captulo - Formulrios com JSF - Exerccios: Completando o Formulrio - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
<f:selectItem itemValue="MediaMovelSimples" itemLabel="Simples" />
<f:selectItem itemValue="MediaMovelPonderada" itemLabel="Ponderada" />
</p:selectOneMenu>
) Salve a pgina e reinicie o Tomcat. Teste o formulrio em seu navegador: http://localhost:/
-argentum-web/index.xhtml
Ao submeter o formulrio deve aparecer no console do Eclipse o indicador selecionado.
) Faa mais um teste, e escolha Abertura como indicador e Simples como mdia. Perceba que a legenda do
grco no est condizente com os indicadores e mdias que selecionamos. Para melhorar nossa apre-
sentao, vamos mudar a implementao do mtodo toString() tanto na MediaMovelSimples quanto
na MediaMovelPonderada.
public class MediaMovelSimples implements Indicador {
...
public String toString() {
return "MMS-" + this.outroIndicador.toString();
}
}
public class MediaMovelPonderada implements Indicador {
...
public String toString() {
return "MMP-" + this.outroIndicador.toString();
}
}
Reinicie o Tomcat e faa o mesmo teste anterior. Escolha Abertura como indicador e Simples como mdia.
O resultado deve ser uma legenda com o texto de: MMS-Abertura.
Captulo - Formulrios com JSF - Exerccios: Completando o Formulrio - Pgina
C
API de Reection
:i.: MoN1nNoo os :No:cnoonvs o:Nnm:cnmvN1v
No nosso formulrio criamos dois combo boxes, um para o indicador base e outro para a mdia. Enquanto
o usurio obrigado a escolher o indicador, a mdia opcional.
Baseado nesse input preciso montar o(s) indicador(es). Ou seja, pode ser que o usurio queira gerar o
grco usando apenas a abertura ou fechamento, como ele tambmpode combinar comuma mdia (simples
ou ponderada).
Repare que recebemos no ArgentumBean os dados dos combo boxes como String, e temos dois atributos na
classe:
private String nomeIndicador;
private String nomeMedia;
Para criar os indicadores vamos analisar os dois atributos. A primeira ideia usar um simples if para des-
cobrir qual o indicador base:
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Indicador indicador = null;
if(nomeIndicador.equals("IndicadorAbertura")) {
indicador = new IndicadorAbertura();
} else {
indicador = new IndicadorFechamento();
}
Alm disso, temos que vericar se for selecionado uma mdia. preciso testar se o atributo existe (no
nulo) e qual foi a mdia:
if (nomeMedia != null) {
if (nomeMedia.equals("MediaMovelSimples")) {
indicador = new MediaMovelSimples(indicador);
} else {
indicador = new MediaMovelPonderada(indicador);
}
}
Portanto nosso cdigo caria assim:
Indicador indicador = null;
if (nomeIndicador.equals("IndicadorAbertura")) {
indicador = new IndicadorAbertura();
} else {
indicador = new IndicadorFechamento();
}
if (nomeMedia != null) {
if (nomeMedia.equals("MediaMovelSimples")) {
indicador = new MediaMovelSimples(indicador);
} else {
indicador = new MediaMovelPonderada(indicador);
}
}
Nesse pequeno trecho escrevemos ifs que j umsinal de ummal design e umaumento na Complexidade
Ciclomtica do nosso cdigo.
Captulo - API de Reection - Montando os indicadores dinamicamente - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Comvtvx:onov C:ctomK1:cn
A ideia basicamente contar o nmero de caminhos diferentes que um mtodo pode ter. E
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/
Por vantagem competitiva, nosso cliente pede mais indicadores (mnimo e mximo) e outras mdias (expo-
nencial e adaptativa). sensvel que o cdigo nunca pra de crescer e sempre sujeito a alterao.
Nesse caso a API de reection 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.
:i.i IN1noocXo n Rvvtvc1:oN
Por ser uma linguagem compilada, Java permite que, enquanto escrevemos nosso cdigo, tenhamos total
controle sobre o que ser executado, de tudo que faz parte do nosso sistema. Em tempo de desenvolvimento,
olhando nosso cdigo, sabemos quantos atributos uma classe tem, quais construtores e mtodos ela possui,
qual chamada de mtodo est sendo feita e assim por diante.
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!
Nesse captulo voc vai conhecer um pouco desse recurso avanado e muito poderoso, que embora possua
qualidades aumenta bastante a complexidade do nosso cdigo e por essa razo deve ser usado de forma
sensata.
:i. Pon qcv Rvvtvc1:oN:
Um aluno que j cursou o FJ- pode notar uma incrvel semelhana com a discusso em aula sobre MVC,
onde, dado um parmetro da requisio, criamos um objeto das classes de lgica. Outro exemplo, j visto,
o do XStream: dado um XML, ele consegue criar objetos para ns e colocar os dados nos atributos dele.
Como ele faz isso? Ser que no cdigo-fonte do XStream acharamos algo assim:
Negociacao n = new Negociacao(...);
OXStreamfoi construdo para funcionar comqualquer tipo de XMLe objeto. Comumpouco de ponderao
ca bvio que no h um new para cada objeto possvel e imaginvel dentro do cdigo do XStream. Mas
Captulo - API de Reection - Introduo a Reection - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
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.reect um pacote do Java que permite criar chamadas em tempo de execuo, sem preci-
sar conhecer as classes e objetos envolvidos quando escrevemos nosso cdigo (tempo de compilao). Esse
dinamismo necessrio para resolvermos determinadas tarefas que nosso programa s descobre serem ne-
cessrias ao receber dados, 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.
Apenas para citar algumas possibilidades com reection:
Listar todos os atributos de uma classe e pegar seus valores em um objeto;
Instanciar classes cujo nome s vamos conhecer em tempo de execuo;
Invocar um construtor especico baseado no tipo de atributo
Invocar mtodos dinamicamente baseado no nome do mtodo como String;
Descobrir se determinados pedaos do cdigo tm annotations.
:i.{ CoNs1ncc1on, F:vto v Mv1noo
O ponto de partida da reection a classe Class. Esta, uma classe da prpria API do Java que representa
cada modelo presente no sistema: nossas classes, as que esto em JARs e tambm as do prprio Java. Atravs
da Class conseguimos obter informaes sobre qualquer classe do sistema, como seus atributos, mtodos,
construtores, etc.
Todo objeto tem um jeito fcil pegar o Class dele:
Negociacao n = new Negociacao();
// chamamos o getClass de Object
Class<Negociacao> classe = n.getClass();
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:
Class<Negociacao> classe = Negociacao.class;
Captulo - API de Reection - Constructor, Field e Method - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Jnvn v GvNvn:cs
A partir do Java , a classe Class tipada e recebe o tipo da classe que estamos trabalhando. Isso
melhora alguns mtodos, que antes recebiamObject e agora trabalhamcomumtipo T qualquer,
parametrizado pela classe.
A partir de um Class podemos listar, por exemplo, os nomes e valores dos seus atributos:
Class<Negociacao> classe = Negociacao.class;
for (Field atributo : classe.getDeclaredFields()) {
System.out.println(atributo.getName());
}
A sada ser:
preco
quantidade
data
Fazendo similarmente para os mtodos possvel conseguir a lista:
Class<Negociacao> classe = Negociacao.class;
for (Method metodo : classe.getDeclaredMethods()) {
System.out.println(metodo.getName());
}
Cuja sada ser:
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:
Class<MediaMovelSimples> classe = MediaMovelSimples.class;
Constructor<?>[] construtores = classe.getConstructors();
for (Constructor<?> constructor : construtores) {
System.out.println(Arrays.toString(constructor.getParameterTypes()));
}
Captulo - API de Reection - Constructor, Field e Method - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Imprime o tipo do parmetro do nico construtor:
interface br.com.caelum.argentum.modelo.Indicador
possvel fazer muito mais. Investigue a API de reection usando ctrl + espao a partir das classes Method,
Constructor e Fields no Eclipse e pelo JavaDoc.
UsnNoo nNo1novs
Anotaes (annotations) so uma novidade do Java cujo objetivo possibilitar a declarao de
metadados nos nossos objetos, isto , conguraes de uma classe podem car dentro dela, em
vez de em um XML parte.
At agora, usamos anotaes para indicar que um mtodo j foi sobrescrito (@Override) e para
congurar um mtodo como teste do JUnit (@Test) e talvez, tenhamos visto outras anotaes
como a (@Deprecated) que indica que um mtodo no deve ser utilizado.
Em todas essas ocasies, percebemos que a presena da anotao no inui no comportamento
daquela classe, daqueles objetos. No so cdigos executveis, que mudam o que executado ou
no. So metadados, informaes (dados), que falam sobre nossa classe mas no fazem parte da
classe em si.
Metadados so muito usados para conguraes de funcionalidades anexas quela classe. Por
exemplo, usamos a anotao do Test para congurar que o JUnit entenda aquele mtodo como
um teste e execute-o quando a classe for executada. Mas, se retirarmos a anotao, a nossa classe
continua compilando normalmente - apenas, quando rodarmos o JUnit, esse mtodo ser igno-
rado.
Em geral usamos anotaes para criar conguraes nos nossos artefatos com objetivo de que
depois essas anotaes sejam lidas e processadas por algum interessado naquelas informaes.
:i. MvtnonnNoo Nosso AncvN1cmBvnN
J temos os conhecimentos necessrios para melhorar nosso mtodo preparaDados(). A primeira necessi-
dade naquele mtodo instanciar um Indicador a partir da String recebida. Mas antes preciso descobrir a
classe pela String e atravs do mtodo newInstance() instanciar um objeto da classe.
public void preparaDados() {
....
Captulo - API de Reection - Melhorando nosso ArgentumBean - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
GeradorModeloGrafico gerador = new GeradorModeloGrafico(serie, 2,
serie.getTotal() -1 );
Indicador indicador = (Indicador) Class.forName(
"br.com.caelum.argentum.modelo." + this.nomeIndicador)
.newInstance();
gerador.plotaIndicador(montador.getIndicador());
...
}
Se a mdia for passada precisamos cri-la a partir da String. Diferente das classes indicadoras as mdias, que
tambm so indicadores mas com foco em clculos matemticos, recebem um indicador via construtor. E
por isso no basta fazer a chamada ao mtodo newInstance(), j que este s consegue instanciar quando
existe o construtor sem argumentos ou o padro.
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:
public void preparaDados() {
....
Indicador indicador = (Indicador) Class.forName(
"br.com.caelum.argentum.modelo." + this.nomeIndicador)
.newInstance();
if(!this.nomeMedia.isEmpty()) {
Constructor<?> constructor = Class.forName(
"br.com.caelum.argentum.modelo". + this.nomeMedia)
.getConstructor(Indicador.class);
indicador = (Indicador) constructor.newInstance(indicador);
}
...
}
Repare que esse cdigo funciona com qualquer indicador ou mdia. Desde que seguimos da conveno de
usar o nome da classe no combo box como parmetro, no ter nenhum problema com esse trecho.
No outro lado perceba que o cdigo expe muitos detalhes. Para entender o que ele realmente faz, preciso
conhecer a API de Reection. Vamos criar uma classe que se preocupa comomontar umindicador e esconder
esses detalhes. Seguiremos boas prticas do paradigma Orientado a Objetos, igual ao que j zemos com as
classes ClienteWebService e GeradorModeloGrafico.
Captulo - API de Reection - Melhorando nosso ArgentumBean - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
A nova classe se chamar MontadorIndicador. Ela recebe o nome do indicador e da mdia no construtor e
devolve um indicador pronto para usar. Um esboo dessa classe:
public class MontadorIndicador {
private String nomeIndicador;
private String nomeMedia;
public MontadorIndicador(String nomeIndicador, String nomeMedia) {
this.nomeIndicador = nomeIndicador;
this.nomeMedia = nomeMedia;
}
public Indicador getIndicador() {
//Aqui vem todo o cdigo de reflection
}
}
Alm dos dois atributos vamos criar uma constante para o nome do package. Estamos usando o mesmo
pacote para o indicador e a mdia, uma boa causa para denir o constante:
public class MontadorIndicador {
private static final String PACKAGE = "br.com.caelum.argentum.modelo.";
//atributos e construtor omitidos
public Indicador getIndicador() {
Indicador indicador = (Indicador) Class.forName(PACKAGE + this.nomeIndicador)
.newInstance();
if(this.nomeMedia != null && !this.nomeMedia.isEmpty()) {
Constructor<?> constructor = Class.forName(PACKAGE + this.nomeMedia)
.getConstructor(Indicador.class);
indicador = (Indicador) constructor.newInstance(indicador);
}
return indicador;
}
}
Por m falta o tratamento de excees. A API de reection infelizmente cheio de excees do tipo checked
que o compilador nos obriga a tratar. Nesse pequeno trecho de cdigo sero lanadas nada mais do que
excees checked. Podemos dar um throws na assinatura do mtodo, mas isso violaria o encapsulamento
pois iria expor detalhes da implementao.
Captulo - API de Reection - Melhorando nosso ArgentumBean - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
O mais aconselhado ento seria capturar cada exceo e relan-la atravs de uma exceo unchecked:
public Indicador getIndicador() {
try {
Indicador indicador = (Indicador) Class.forName(PACKAGE + this.nomeIndicador)
.newInstance();
if(this.nomeMedia != null && !this.nomeMedia.isEmpty()) {
Constructor<?> constructor = Class.forName(PACKAGE + this.nomeMedia)
.getConstructor(Indicador.class);
indicador = (Indicador) constructor.newInstance(indicador);
}
return indicador;
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
}
Voltando classe ArgentumBean vamos ento delegar a criao do indicador para o montador:
public void preparaDados() {
....
MontadorIndicador montador =
new MontadorIndicador(this.nomeIndicador, this.nomeMedia)
Indicador indicador = montador.getIndicador();
...
}
Dessa forma as responsabilidades esto bem denidas e a evoluo do sistema no depende de mais ifs no
nosso preparaDados().
Captulo - API de Reection - Melhorando nosso ArgentumBean - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Repare que hoje o MontadorIndicador uma fbrica de indicadores, sendo assim vamos usar a mesma es-
tratgia do CandlestickFactory e renome-lo para IndicadorFactory. Com o recurso de refactoring essa
mudana simples e eciente j que altera todos os outros pontos do sistema.
:i.o Exvncc:os: Pto1nNoo :No:cnoonvs
) Crie a classe usando ctrl + N Class, chamada IndicadorFactory no source folder src/main/java e dentro
do pacote br.com.caelum.argentum.modelo
) Declare na classe gerada os atributos: nomeIndicador e nomeMedia.
public class IndicadorFactory {
private String nomeIndicador;
private String nomeMedia;
}
) O prximo passo declarar o construtor que receba os nossos atributos. Para isso vamos usar mais uma
das facilidades do Eclipse. Dentro da classe Indicador Factory use alt + shi + S e selecione Generate
Constructor Using Fields.
Selecione todos os atributos e aperte em ok.
Captulo - API de Reection - Exerccios: Plotando indicadores - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Sua classe deve estar como o cdigo a seguir:
public class IndicadorFactory {
private String nomeIndicador;
private String nomeMedia;
public IndicadorFactory(String nomeIndicador, String nomeMedia) {
this.nomeIndicador = nomeIndicador;
this.nomeMedia = nomeMedia;
}
}
) Como nosso objetivo devolver um Indicador nessa Factory, crie o mtodo getIndicador() que deve
devolver um Indicador. E ele deve ter a seguinte implementao:
public Indicador getIndicador() {
try {
Indicador indicador = (Indicador) Class.forName(
Captulo - API de Reection - Exerccios: Plotando indicadores - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
"br.com.caelum.argentum.modelo." + this.nomeIndicador)
.newInstance();
if (this.nomeMedia != null && !this.nomeMedia.isEmpty()) {
Constructor<?> constructor = Class.forName(
"br.com.caelum.argentum.modelo." + this.nomeMedia)
.getConstructor(Indicador.class);
indicador = (Indicador) constructor.newInstance(indicador);
}
return indicador;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
) Repare que repetimos a String como nome do pacote, br.com.caelum.argentum.modelo., emdois luga-
res do mtodo. Caso esse pacote seja renomeado, esses dois pontos devem ser modicados. Logo, vamos
declarar uma constante para esse pacote e evitar duplicaes. Mais uma vez vamos utilizar o recurso de
refactoring da IDE.
Selecione a String, "br.com.caelum.argentum.modelo.", boto direito e Refactor. Dentro desse opo,
selecione Extract Constant ....
Declare no campo Constant name o valor de PACKAGE.
Captulo - API de Reection - Exerccios: Plotando indicadores - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
) Com o IndicadorFactory criado, vamos us-lo no mtodo preparaDados() da classe ArgentumBean.
Abra a classe e faa o gerador GeradorModeloGrafivo usar o IndicadorFactory como segue:
public void preparaDados() {
...
GeradorModeloGrafico gerador =
new GeradorModeloGrafico(serie, 2, serie.getTotal() -1 );
IndicadorFactory indicadorFactory =
new IndicadorFactory(getNomeIndicador(), getNomeMedia());
gerador.plotaIndicador(indicadorFactory.getIndicador());
this.modeloGrafico = gerador.getModeloGrafico();
}
) (opcional) Vamos criar um teste para nosso IndicadorFactory. Crie uma classe de
teste, chamada IndicadorFactoryTest no source folder src/test/java e dentro do pacote
br.com.caelum.argentum.modelo. Pelo menos dois testes so necessrio: um quando um indi-
cador simples e outro quando est associado as mdias.
public class IndicadorFactoryTest {
@Test
Captulo - API de Reection - Exerccios: Plotando indicadores - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
public void testMontaAbertura() {
String nomeIndicador = "IndicadorAbertura";
IndicadorFactory indicadorFactory =
new IndicadorFactory(nomeIndicador, null);
Indicador indicador = indicadorFactory.getIndicador();
Assert.assertTrue(indicador instanceof IndicadorAbertura);
}
@Test
public void testMontaAberturaComMediaMovelSimples() {
String nomeIndicador = "IndicadorAbertura";
String nomeMedia = "MediaMovelSimples";
IndicadorFactory indicadorFactory =
new IndicadorFactory(nomeIndicador, nomeMedia);
Indicador indicador = indicadorFactory.getIndicador();
Assert.assertTrue(indicador instanceof MediaMovelSimples);
}
}
Captulo - API de Reection - Exerccios: Plotando indicadores - Pgina
C
Apndice Testes de interface com Selenium
Alm da magia negra, h apenas automao e mecanizao
Federico Garcia Lorca
:.: IN1noocXo no 1vs1v ov ncv:1nXo
Nos captulos anteriores zemos uso dos testes de unidade, ser que eles so sucientes para garantir que
a aplicao funcione da maneira esperada? Em um projeto web, uma das partes mais importantes para o
funcionamento desejado a parte de apresentao, j que a partir dela que toda a comunicao do cliente
com o nosso sistema ser feita.
Vericar se as funcionalidades de um sistema esto se comportando corretamente sem que tenhamos de
testar manualmente a aplicao, abrindo um navegador, navegando por ele e visualizando os resultados so
tarefas que so realizadas pelos Acceptance Testing (ou Testes de Aceitao).
Temos que testar o nosso cdigo, mas em uma aplicao web ca difcil testar a camada de apresentao,
o resultado nal. 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 coma aplicao. Esse o caso do Seleniumque, coma assistncia do JUnit, pode facilitar o trabalho
de escrever tais testes.
:.i Como vcNc:oNn:
Para demonstrar como o Selenium funciona, testaremos se a validao do campo titulo funciona correta-
mente, isto , o formulrio no poder ser submetido caso ele esteja em branco.
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
A primeira coisa que uma pessoa faz para testar a aplicao abrir um browser. Com Selenium, precisamos
apenas da linha abaixo:
WebDriver driver = new FirefoxDriver();
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:
WebDriver driver = new InternetExplorerDriver();
H1mtUN:1Dn:vvn
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 dedignamente:
WebDriver driver = new HtmlUnitDriver();
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
get que recebe a URL:
WebDriver driver = new FirefoxDriver();
driver.get("http://localhost:8080/fj22-argentum-web/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 umcritrio de busca. Aclasse By possui uma srie de mtodos estticos.
Pesquisaremos pelo id:
WebDriver driver = new FirefoxDriver();
driver.get("http://localhost:8080/fj22-argentum-web/index.xhtml");
WebElement titulo = driver.findElement(By.id("titulo"));
Captulo - Apndice Testes de interface com Selenium - Como funciona? - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Agora que temos o elemento, podemos preench-lo como texto que quisermos atravs do mtodo sendKeys.
Em nosso caso, deixaremos o campo em branco passando uma string vazia:
WebDriver driver = new FirefoxDriver();
driver.get("http://localhost:8080/fj22-argentum-web/index.xhtml");
WebElement titulo = driver.findElement(By.id("titulo"));
titulo.sendKeys("");
Quando o formulrio for submetido e o campo titulo estiver em branco, esperamos que o sistema mostre
a mensagem Erro de Validao.
Antes de testarmos se tudo esta correto, precisamos submeter o formulrio. O objeto WebElement possui o
mtodo submit que faz exatamente isso:
WebDriver driver = new FirefoxDriver();
driver.get("http://localhost:8080/fj22-argentum-web/index.xhtml");
WebElement titulo = driver.findElement(By.id("titulo"));
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:
WebDriver driver = new FirefoxDriver();
driver.get("http://localhost:8080/fj22-argentum-web/index.xhtml");
WebElement titulo = driver.findElement(By.id("titulo"));
titulo.sendKeys("");
titulo.submit();
boolean existeMensagem = driver.getPageSource().contains("Erro de validao");
Por m, 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:
Captulo - Apndice Testes de interface com Selenium - Como funciona? - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
WebDriver driver = new FirefoxDriver();
driver.get("http://localhost:8080/fj22-argentum-web/index.xhtml");
WebElement titulo = driver.findElement(By.id("titulo"));
titulo.sendKeys("");
titulo.submit();
boolean existeMensagem = driver.getPageSource().contains("Erro de validao");
Assert.assertTrue(existeMensagem);
Pronto, podemos vericar no prprio Eclipse se o teste passou se ele estiver verde. Se algo der errado, como
de costume, a cor vermelha ser utilizada.
Podemos usar agora o mtodo driver.close() para fechar a janela do navegador.
WebDriver driver = new FirefoxDriver();
driver.get("http://localhost:8080/fj22-argentum-web/index.xhtml");
WebElement titulo = driver.findElement(By.id("titulo"));
titulo.sendKeys("");
titulo.submit();
boolean existeMensagem = driver.getPageSource().contains("Erro de validao);
Assert.assertTrue(existeMensagem);
driver.close();
:. TnnnntnnNoo como:vvnsos 1vs1vs ov ncv:1nXo
comum termos dois ou mais testes de aceitao em nossa bateria de testes. Teramos ento que abrir uma
janela do navegador em cada mtodo, e, aps os testes, fech-la. Com isso, estaramos repetindo muito
cdigo! O Selenium nos permite fazer isso de uma forma mais fcil. Primeiro, criaremos o mtodo setUp, e
o anotaremos com @Before.
@Before
public void setUp() {
driver = new FirefoxDriver();
}
Captulo - Apndice Testes de interface com Selenium - Trabalhando com diversos testes de aceitao - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
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();
}
:.{ Pnnn snnvn mn:s: CoNv:ccnnNoo o SvtvN:cmvmcnsn
Caso voc esteja fazendo esse passo de casa, preciso baixar algumas JARs para o funcionamento dessa
aplicao, usaremos as seguintes verses:
commons-exec-..jar
commons-logging-...jar
guava-..jar
httpclient-...jar
httpcore-...jar
json-.jar
selenium-java-...jar
Para mais informaes, voc pode consultar o site http://docs.seleniumhq.org/
:. Exvncc:os: Tvs1v comSvtvN:cm
Vamos criar nosso primeiro teste com Selenium:
) Antes de tudo vamos colocar as jars do Selenium no nosso projeto, elas se encontram na pasta
Desktop/caelum/22/selenium-jars/:
Captulo - Apndice Testes de interface com Selenium - Para saber mais: Congurando o Selenium em casa - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
Para adicion-las ao projeto, crie uma nova pasta chamada lib-teste na raiz do projeto e copie as jars
para dentro dela.
Logo em seguida adicione-as ao Build Path:
Captulo - Apndice Testes de interface com Selenium - Exerccios: Teste com Selenium - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
) Crie a classe usando ctrl + N Class, chamada GeraGraficoTest no source folder src/test/java e dentro do
pacote br.com.caelum.argentum.aceitacao:
) 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 {
private static final String URL =
"http://localhost:8080/fj22-argentum-web/index.xhtml";
private WebDriver driver;
}
) Vamos criar o mtodo testeAoGerarGraficoSemTituloUmaMensagemEhApresentada e anot-lo com
@Test para indicar que ele deve ser chamado quando o teste for executado:
public class GeraGraficoTest {
private static final String URL =
"http://localhost:8080/fj22-argentum-web/index.xhtml";
private WebDriver driver;
@Test
public void testeAoGerarGraficoSemTituloUmaMensagemEhApresentada() {
}
}
) 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 - Apndice Testes de interface com Selenium - Exerccios: Teste com Selenium - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
private static final String URL =
"http://localhost:8080/fj22-argentum-web/index.xhtml";
private WebDriver driver;
@Test
public void testeAoGerarGraficoSemTituloUmaMensagemEhApresentada() {
driver = new FirefoxDriver();
driver.get(URL);
driver.close();
}
}
) 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 {
private static final String URL =
"http://localhost:8080/fj22-argentum-web/index.xhtml";
private WebDriver driver;
@Test
public void testeAoGerarGraficoSemTituloUmaMensagemEhApresentada() {
driver = new FirefoxDriver();
driver.get(URL);
WebElement titulo = driver.findElement(By.id("dadosGrafico:titulo"));
titulo.sendKeys("");
titulo.submit();
boolean existeMensagem = driver.getPageSource().contains("Erro de validao");
Assert.assertTrue(existeMensagem);
driver.close();
}
}
) 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
o navegador novamente. Para podermos reaproveitar esse cdigo, podemos coloc-los em blocos sepa-
Captulo - Apndice Testes de interface com Selenium - Exerccios: Teste com Selenium - Pgina
Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns
rados e usar as anotaes @Before, para execut-lo antes de cada mtodo, e @After, para execut-lo aps
cada mtodo.
public class GeraGraficoTest {
private static final String URL =
"http://localhost:8080/fj22-argentum-web/index.xhtml";
private WebDriver driver;
@Before
public void setUp() {
driver = new FirefoxDriver();
}
@After
public void tearDown() {
driver.close();
}
@Test
public void testeAoGerarGraficoSemTituloUmaMensagemEhApresentada() {
driver.get(URL);
WebElement titulo = driver.findElement(By.id("dadosGrafico:titulo"));
titulo.sendKeys("");
titulo.submit();
boolean existeMensagem = driver.getPageSource().contains("Erro de validao");
Assert.assertTrue(existeMensagem);
}
}
Captulo - Apndice Testes de interface com Selenium - Exerccios: Teste com Selenium - Pgina
ndice Remissivo
Anotaes,
anotaes,
Calendar,
Candlestick, ,
datas,
Design patterns,
Factory pattern,
nal,
JUnit,
Negociao,
Reection,
static import,
Tail,
TDD,
Test driven design,
testes de unidade,
testes unitrios,