Sie sind auf Seite 1von 178

Conhea mais da Caelum.

Cursos Online
www.caelum.com.br/online

Casa do Cdigo
Livros para o programador
www.casadocodigo.com.br

Blog Caelum
blog.caelum.com.br

Newsletter
www.caelum.com.br/newsletter

Facebook
www.facebook.com/caelumbr

Twitter
twitter.com/caelum

Sobre esta apostila


Esta apostila da Caelum visa ensinar de uma maneira elegante, mostrando apenas o que necessrio e quando
necessrio, no momento certo, poupando o leitor de assuntos que no costumam ser de seu interesse em
determinadas fases do aprendizado.
A Caelum espera que voc aproveite esse material. Todos os comentrios, crticas e sugestes sero muito
bem-vindos.
Essa apostila constantemente atualizada e disponibilizada no site da Caelum. Sempre consulte o site para
novas verses e, ao invs de anexar o PDF para enviar a um amigo, indique o site para que ele possa sempre
baixar as ltimas verses. Voc pode conferir o cdigo de verso da apostila logo no final do ndice.
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
1

.
.
.
.

1
1
2
3
3

.
.
.
.
.
.
.
.
.
.
.
.

4
4
5
6
8
9
9
10
12
16
24
25
28

.
.
.
.
.
.
.
.
.
.
.
.
.

31
31
31
34
34
35
37
37
39
45
46
51
52
52

4 Trabalhando com XML


4.1 Os dados da bolsa de valores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.2 O formato XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.3 Lendo XML com Java de maneira difcil, o SAX . . . . . . . . . . . . . . . . . . . . . . . . . . .

53
53
54
55

Tornando-se um desenvolvedor pragmtico


1.1 O que realmente importante? . . . . .
1.2 A importncia dos exerccios . . . . . .
1.3 Tirando dvidas e referncias . . . . . .
1.4 Para onde ir depois? . . . . . . . . . . . .

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

O modelo da bolsa de valores, datas e objetos imutveis


2.1 A bolsa de valores . . . . . . . . . . . . . . . . . . . . .
2.2 Candlesticks: O Japo e o arroz . . . . . . . . . . . . .
2.3 O projeto Tail . . . . . . . . . . . . . . . . . . . . . . .
2.4 O projeto Argentum: modelando o sistema . . . . . .
2.5 Trabalhando com dinheiro . . . . . . . . . . . . . . . .
2.6 Palavra chave final . . . . . . . . . . . . . . . . . . . . .
2.7 Imutabilidade de objetos . . . . . . . . . . . . . . . . .
2.8 Trabalhando com datas: Date e Calendar . . . . . . .
2.9 Exerccios: o modelo do Argentum . . . . . . . . . . .
2.10 Resumo dirio das Negociaes . . . . . . . . . . . . .
2.11 Exerccios: fbrica de Candlestick . . . . . . . . . . . .
2.12 Exerccios opcionais . . . . . . . . . . . . . . . . . . . .
Testes Automatizados
3.1 Nosso cdigo est funcionando corretamente? . . . .
3.2 Exerccios: testando nosso modelo sem frameworks .
3.3 Definindo melhor o sistema e descobrindo mais bugs
3.4 Testes de Unidade . . . . . . . . . . . . . . . . . . . . .
3.5 JUnit . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.6 Anotaes . . . . . . . . . . . . . . . . . . . . . . . . .
3.7 JUnit4, convenes e anotao . . . . . . . . . . . . .
3.8 Exerccios: migrando os testes do main para JUnit . .
3.9 Vale a pena testar classes de modelo? . . . . . . . . . .
3.10 Exerccios: novos testes . . . . . . . . . . . . . . . . . .
3.11 Para saber mais: Import Esttico . . . . . . . . . . . .
3.12 Mais exerccios opcionais . . . . . . . . . . . . . . . .
3.13 Discusso em aula: testes so importantes? . . . . . .

.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

4.4
4.5
4.6
5

XStream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
Exerccios: Lendo o XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
Discusso em aula: Onde usar XML e o abuso do mesmo . . . . . . . . . . . . . . . . . . . . . . 63

Test Driven Design - TDD


5.1 Separando as candles . . . . . . . . . . . . . . . . . . .
5.2 Vantagens do TDD . . . . . . . . . . . . . . . . . . . .
5.3 Exerccios: Identificando negociaes do mesmo dia
5.4 Exerccios: Separando os candles . . . . . . . . . . . .
5.5 Exerccios opcionais . . . . . . . . . . . . . . . . . . . .

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

6 Acessando um Web Service


6.1 Integrao entre sistemas . . . . . . . . . . . . . . . . . . . .
6.2 Consumindo dados de um Web Service . . . . . . . . . . .
6.3 Criando o cliente Java . . . . . . . . . . . . . . . . . . . . . .
6.4 Exerccios: Nosso cliente Web Service . . . . . . . . . . . .
6.5 Discusso em aula: Como testar o cliente do web service?
7

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

Introduo ao JSF e Primefaces


7.1 Desenvolvimento desktop ou web? . . . . . . . . . . . . . . . . . . .
7.2 Caractersticas do JSF . . . . . . . . . . . . . . . . . . . . . . . . . . .
7.3 Exerccios: Instalando o Tomcat e criando o projeto . . . . . . . . .
7.4 A primeira pgina com JSF . . . . . . . . . . . . . . . . . . . . . . .
7.5 Interagindo com o modelo: Managed Beans . . . . . . . . . . . . .
7.6 Recebendo informaes do usurio . . . . . . . . . . . . . . . . . .
7.7 Exerccios: Os primeiros componentes JSF . . . . . . . . . . . . . .
7.8 A lista de negociaes . . . . . . . . . . . . . . . . . . . . . . . . . . .
7.9 Formatao de Data com JSF . . . . . . . . . . . . . . . . . . . . . .
7.10 Exerccios: p:dataTable para listar as Negociaes do Web Service .
7.11 Para saber mais: paginao e ordenao . . . . . . . . . . . . . . . .
7.12 Exerccio opcional: adicione paginao e ordenao tabela . . . .
Refatorao: os Indicadores da bolsa
8.1 Anlise Tcnica da bolsa de valores . .
8.2 Indicadores Tcnicos . . . . . . . . . .
8.3 As mdias mveis . . . . . . . . . . . .
8.4 Exerccios: criando indicadores . . . .
8.5 Refatorao . . . . . . . . . . . . . . . .
8.6 Exerccios: Primeiras refatoraes . .
8.7 Refatoraes maiores . . . . . . . . . .
8.8 Discusso em aula: quando refatorar?

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

9 Grficos interativos com Primefaces

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.

64
64
65
66
68
70

.
.
.
.
.

73
73
73
74
77
78

.
.
.
.
.
.
.
.
.
.
.
.

79
80
82
86
92
94
95
97
100
102
103
106
108

.
.
.
.
.
.
.
.

111
111
112
113
115
119
120
123
124
125

ii

9.1
9.2
9.3
9.4
9.5
9.6
9.7

Por que usar grficos? . . . . . . . . . . . . . . . . . . . . . . .


Grficos com o Primefaces . . . . . . . . . . . . . . . . . . . .
Propriedades para personalizar o grfico . . . . . . . . . . .
Definio do modelo do grfico . . . . . . . . . . . . . . . . .
Isolando a API do Primefaces: baixo acoplamento . . . . . .
Para saber mais: Design Patterns Factory Method e Builder
Exerccios: Grficos com Primefaces . . . . . . . . . . . . . .

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

10 Aplicando Padres de projeto


10.1 Nossos indicadores e o design pattern Strategy . . . . . . . . . . . . .
10.2 Exerccios: refatorando para uma interface e usando bem os testes .
10.3 Exerccios opcionais . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
10.4 Indicadores mais elaborados e o Design Pattern Decorator . . . . . .
10.5 Exerccios: Indicadores mais espertos e o Design Pattern Decorator
11 A API de Reflection
11.1 Escolhendo qual grfico plotar . . . . . . . . . . . . . .
11.2 Exerccios: permitindo que o usurio escolha o grfico
11.3 Montando os indicadores dinamicamente . . . . . . . .
11.4 Introduo a Reflection . . . . . . . . . . . . . . . . . . .
11.5 Por que reflection? . . . . . . . . . . . . . . . . . . . . .
11.6 Constructor, Field e Method . . . . . . . . . . . . . . . .
11.7 Melhorando nosso ArgentumBean . . . . . . . . . . . .
11.8 Exerccios: indicadores em tempo de execuo . . . . .
11.9 Melhorando a orientao a objetos . . . . . . . . . . . .
12 Apndice Testes de interface com Selenium
12.1 Introduo ao teste de aceitao . . . . . . . . . . . .
12.2 Como funciona? . . . . . . . . . . . . . . . . . . . . .
12.3 Trabalhando com diversos testes de aceitao . . . .
12.4 Para saber mais: Configurando o Selenium em casa
12.5 Exerccios: Teste com Selenium . . . . . . . . . . . .
ndice Remissivo

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.

125
126
127
129
131
134
135

.
.
.
.
.

138
138
141
144
145
146

.
.
.
.
.
.
.
.
.

149
149
153
155
156
157
158
159
160
162

.
.
.
.
.

163
163
163
166
167
167
171

Verso: 17.8.6

iii

Captulo 1

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?

1.1

O que realmente importante?

Voc j passou pelo FJ-11 e, quem sabe, at pelo FJ-21. Agora chegou a hora de codificar 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 tem como objetivo trazer uma viso mais prtica do desenvolvimento Java atravs de uma experincia rica em cdigo, onde exercitaremos diversas APIS e recursos do Java. Vale salientar que as bibliotecas
em si no so os pontos mais importantes do aprendizado neste momento, mas sim as boas prticas, a cultura
e um olhar mais amplo sobre o design da sua aplicao.
Os design patterns, as boas prticas, a refatorao, a preocupao com o baixo acoplamento, os testes de unidade (tambm conhecidos como testes unitrios) e as tcnicas de programao (idiomismos) so passados
com afinco.
Para atingir tal objetivo, esse curso baseia-se fortemente em artigos, blogs e, em especial, na literatura que se
consagrou como fundamental para os desenvolvedores Java. Aqui citamos alguns desses livros:
http://blog.caelum.com.br/2006/09/22/livros-escolhendo-a-trindade-do-desenvolvedor-java/

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

Somamos a esses mais dois livros, que sero citados no decorrer do curso, e influenciaram muito na elaborao do contedo que queremos transmitir a vocs. Todos os cinco so:
Effective 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 enfrentar os principais problemas e
limitaes da linguagem. Uma excelente leitura, dividido em mais de 70 tpicos de 2 a 4 pginas cada,
em mdia. Entre os casos interessantes est o uso de factory methods, os problemas da herana e do
protected, uso de colees, objetos imutveis e serializao, muitos desses abordados e citados aqui
no curso.
Design Patterns, Erich Gamma et al
Livro de Erich Gamma, por muito tempo lder do projeto Eclipse na IBM, e mais outros trs autores,
o que justifica terem o apelido de Gang of Four (GoF). Uma excelente leitura, mas cuidado: no saia
lendo o catlogo dos patterns decorando-os, mas concentre-se especialmente em ler toda a primeira
parte, onde eles revelam um dos princpios fundamentais da programao orientada a objetos:
Evite herana, prefira composio e Programe voltado s interfaces e no implementao.
Refactoring, Martin Fowler
Livro do cientista chefe da ThoughtWorks. Um excelente catlogo de como consertar pequenas falhas
do seu cdigo de maneira sensata. Exemplos clssicos so o uso de herana apenas por preguia,
uso do switch em vez de polimorfismo, entre dezenas de outros. Durante o curso, faremos diversos
refactoring clssicos utilizando do Eclipse, muito mais que o bsico rename.
Pragmatic Programmer, Andrew Hunt
As melhores prticas para ser um bom desenvolvedor: desde o uso de versionamento, ao bom uso do
logging, debug, nomenclaturas, como consertar bugs, etc.
The mythical man-month, Frederick Brooks
Um livro que fala dos problemas que encontramos no dia a dia do desenvolvimento de software, numa
abordagem mais gerencial. Aqui h, inclusive, o clssico artigo No Silver Bullet, que afirma que nunca
haver uma soluo nica (uma linguagem, um mtodo de desenvolvimento, um sistema operacional)
que se adeque sempre a todos os tipos de problema.

1.2

A importncia dos exerccios

um tanto desnecessrio debater sobre a importncia de fazer exerccios, porm neste curso especfico eles
so vitais: como ele focado em boas prticas, alguma parte da teoria no est no texto - e passado no
decorrer de exerccios.

Captulo 1 - Tornando-se um desenvolvedor pragmtico - A importncia dos exerccios - Pgina 2

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

No se assuste, h muito cdigo aqui nesse curso, onde vamos construir uma pequena aplicao que l um
XML com dados da bolsa de valores e plota o grfico de candlesticks, utilizando diversas APIs do Java SE e
at mesmo bibliotecas externas.

1.3

Tirando dvidas e referncias

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/

1.4

Para onde ir depois?

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-21 indicado para ser feito antes ou depois deste curso, dependendo das suas necessidades e do seu
conhecimento. Ele o curso que apresenta o desenvolvimento Web com Java e seus principais ferramentas
e frameworks.
Depois destes cursos, que constituem a Formao Java da Caelum, indicamos dois outros cursos, da Formao Avanada:
http://www.caelum.com.br/formacao-java-avancada/
O FJ-25 aborda Hibernate e JPA 2 e o FJ-26 envolve JSF 2, Facelets e CDI. Ambos vo passar por tecnologias
hoje bastante utilizadas no desenvolvimento server side para web, e j na verso do Java EE 6.

Captulo 1 - Tornando-se um desenvolvedor pragmtico - Tirando dvidas e referncias - Pgina 3

Captulo 2

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-22 aprender boas prticas da orientao a objetos, do design de classes, uso correto dos
design patterns, princpios de prticas geis de programao e a importncia dos testes de unidade.
Dois livros que so seminais na rea sero referenciados por diversas vezes pelo instrutor e pelo material:
Effective Java, do Joshua Bloch, e Design Patterns: Elements of Reusable Object-Oriented Software, de Erich
Gamma e outros (conhecido Gang of Four).

2.1

A bolsa de valores

Poucas atividades humanas exercem tanto fascnio quanto o mercado de aes, assunto abordado exaustivamente em filmes, livros e em toda a cultura contempornea. Somente em novembro de 2007, o total
movimentado pela BOVESPA foi de R$ 128,7 bilhes. Destes, o volume movimentado por aplicaes home
broker foi de R$ 22,2 bilhes.
Neste curso, abordaremos esse assunto que, hoje em dia, chega a ser cotidiano desenvolvendo uma aplicao
que interpreta os dados de um XML, trata e modela eles em Java e mostra grficos pertinentes.

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

2.2

Candlesticks: O Japo e o arroz

Yodoya Keian era um mercador japons do sculo 17. Ele se tornou rapidamente muito rico, dadas as suas
habilidades de transporte e precificao 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 confiscou todo seu dinheiro e suas posses. Depois dele, outros vieram e tentaram esconder
suas origens como mercadores: muitos tiveram seus filhos executados e seu dinheiro confiscado.
Apesar da triste histria, foi em Dojima, no jardim do prprio Yodoya Keian, que nasceu a bolsa de arroz
do Japo. L eram negociados, precificados e categorizados vrios tipos de arroz. Para anotar os preos do
arroz, desenhava-se figuras no papel. Essas figuras parecem muito com velas -- da a analogia candlestick.
Esses desenhos eram feitos em um papel feito de... arroz! Apesar de usado a sculos, o mercado ocidental s
se interessou pela tcnica dos candlesticks recentemente, no ltimo quarto de sculo.
Um candlestick indica 4 valores: o maior preo do dia, o menor preo do dia (as pontas), o primeiro preo
do dia e o ltimo preo do dia (conhecidos como abertura e fechamento, respectivamente).
Os preos de abertura e fechamento so as linhas horizontais e dependem do tipo de candle: se for de alta, o
preo de abertura embaixo; se for de baixa, em cima. Um candle de alta costuma ter cor azul ou branca
e os de baixa costumam ser vermelhos ou pretos. Caso o preo no tenha se movimentado, o candle tem a
mesma cor que a do dia anterior.
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/1_
279_/candlestick.asp
Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - Candlesticks: O Japo e o arroz - Pgina 5

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

Apesar de falarmos que o Candlestick representa os principais valores de um dia, ele pode ser usado para
os mais variados intervalos de tempo: um candlestick pode representar 15 minutos, ou uma semana, dependendo se voc est analisando o ativo para curto, mdio ou longo prazo.

2.3

O projeto Tail

A ideia do projeto Tail (Technical Analysis Indicator Library) nasceu quando um grupo de alunos da Universidade de So Paulo procurou o professor doutor Alfredo Goldman para orient-los no desenvolvimento
de um software 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 definiu o tema: o desenvolvimento de um software open source de anlise tcnica
grafista (veremos o que a anlise tcnica em captulos posteriores).
O software est disponvel no SourceForge:
http://sourceforge.net/projects/tail/

Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - O projeto Tail - Pgina 6

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

Essa ideia, ainda vaga, foi gradativamente tomando a forma do projeto desenvolvido. O grupo se reunia
semanalmente adaptando o projeto, atribuindo novas tarefas e objetivos. Os graduandos tiveram a oportunidade de trabalhar em conjunto com os mestrandos, que compartilharam suas experincias anteriores.
Objetivos do projeto Tail:
Implementar os componentes bsicos da anlise tcnica grafista: srie temporal, operaes de compra
e venda e indicadores tcnicos;
Implementar as estratgias de compra e venda mais utilizadas no mercado, assim como permitir o
rpido desenvolvimento de novas estratgias;
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 grfica, permitindo o uso das ferramentas implementadas de forma fcil, rpida e
de simples entendimento, mas que no limite os recursos da biblioteca;
Arquitetura orientada a objetos, com o objetivo de ser facilmente escalvel e de simples entendimento;
Utilizar prticas de XP, adaptando-as conforme as necessidades do grupo.
Manter a cobertura de testes superior a 90%;
Analisar o funcionamento do sistema de coorientao, com o objetivo estend-lo para projetos futuros.
Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - O projeto Tail - Pgina 7

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

O Tail foi desenvolvido por Alexandre Oki Takinami, Carlos Eduardo Mansur, Mrcio Vinicius dos Santos, Thiago Garutti Thies, Paulo Silveira (mestre em Geometria Computacional pela USP e diretor da Caelum), Julian Monteiro (mestre em sistemas distribudos pela USP e doutor pelo INRIA, em Sophia Antipolis,
Frana) e Danilo Sato (mestre em Metodologias geis pela USP e Lead Consultant na ThoughtWorks).
Esse projeto foi a primeira parceria entre a Caelum e a USP, onde a Caelum patrocinou o trabalho de concluso de curso dos 4 graduandos, hoje todos formados.
Caso tenha curiosidade voc pode acessar o CVS do projeto, utilizando o seguinte repositrio:
http://tail.cvs.sourceforge.net/viewvc/tail/

2.4

O projeto Argentum: modelando o sistema

O projeto Tail bastante ambicioso. Tem centenas de recursos, em especial 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 software, design patterns e Programao eXtrema se
encaixaram muito bem - por isso, nos inspiramos fortemente nele como base para o FJ-22.
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, dinheiro 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 tcnicos
Para isso, implementar um pequeno framework de indicadores e criar alguns deles de forma a facilitar
o desenvolvimento de novos.
Gerar grficos
Embutveis e interativos na interface grfica em Java, dos indicadores que criamos.

Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - O projeto Argentum: modelando o sistema - Pgina 8

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

Para comear a modelar nosso sistema, precisamos entender alguns recursos de design de classes que ainda
no foram discutidos no FJ-11. Entre eles podemos citar o uso da imutabilidade de objetos, uso de anotaes
e aprender a trabalhar e manipular datas usando a API do Java.

2.5

Trabalhando com dinheiro

At agora, no paramos muito para pensar nos tipos das nossas variveis e j ganhamos o costume de automaticamente atribuir valores a variveis double. Essa , contudo, uma prtica bastante perigosa!
O problema do double que no possvel especificar a preciso mnima que ele vai guardar e, dessa forma,
estamos sujeitos a problemas de arredondamento ao fracionar valores e voltar a som-los. Por exemplo:
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.

2.6

Palavra chave final

A palavra chave final tem vrias utilidades. Em uma classe, define que a classe nunca poder ter uma filha,
isso , no pode ser estendida. A classe String, por exemplo, final.
Como modificador de mtodo, final indica que aquele mtodo no pode ser reescrito. Mtodos muito
importantes costumam ser definidos assim. Claro que isso no necessrio declarar caso sua classe j seja
final.
Ao usarmos como modificador na declarao de varivel, indica que o valor daquela varivel nunca poder
ser alterado, uma vez atribudo. Se a varivel for um atributo, voc tem que inicializar seu valor durante a
construo do objeto - caso contrrio, ocorre um erro de compilao, pois atributos final no so inicializados com valores default.
Imagine que, quando criamos um objeto Negociacao, no queremos que seu valor seja modificado:

Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - Trabalhando com dinheiro - Pgina 9

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

class Negociacao {
private final double valor;
// getters e setters?
}

Esse cdigo no compila, nem mesmo com um setter, pois o valor final deveria j ter sido inicializado. Para
resolver isso, ou declaramos o valor da Negociacao direto na declarao do atributo (o que no faz muito
sentido nesse caso), ou ento populamos pelo construtor:
class Negociacao {
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 parece uma constante global! Por exemplo, na classe Collections do java.util existe uma constante public
static final chamada EMPTY_LIST. conveno que constantes sejam declaradas letras maisculas e separadas por travesso (underscore) em vez de usar o padro camel case. Outros bons exemplos so o PI e o E,
dentro da java.lang.Math.
Isso muito utilizado, mas hoje no java 5 para criarmos constantes costuma ser muito mais interessante
utilizarmos o recurso de enumeraes que, alm de tipadas, j possuem diversos mtodos auxiliares.
No caso da classe Negociacao, no entanto, bastar usarmos atributos finais e tambm marcarmos a prpria
classe como final para que ela crie apenas objetos imutveis.

2.7

Imutabilidade de objetos
Effective Java
Item 15: Minimize mutabilidade

Para que uma classe seja imutvel, ela precisa ter algumas caractersticas:
Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - Imutabilidade de objetos - Pgina 10

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

Nenhum mtodo pode modificar 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 modificam o estado do objeto;
Caso sua classe tenha composies com objetos mutveis, eles devem ter acesso exclusivo pela sua
classe.
Diversas classes no Java so imutveis, como a String e todas as classes wrapper. Outro excelente exemplo
de imutabilidade so as classes BigInteger e BigDecimal:
Qual seria a motivao de criar uma classe de tal maneira?

Objetos podem compartilhar suas composies


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
String
String
String
String

palavra = "supercalifragilisticexpialidocious";
inicio = palavra.substring(0, 5);
proximas = palavra.substring(5, 10);
outras = palavra.substring(10, 15);
resto = palavra.substring(15);

Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - Imutabilidade de objetos - Pgina 11

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

Esses objetos tambm so ideais para usar como chave de tabelas de hash.

Thread safety
Uma 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 modificaes acontecerem concorrentemente!

Objetos mais simples


Uma classe imutvel mais simples de dar manuteno. Como no h chances de seu objeto ser modificado,
voc tem uma srie de garantias sobre o uso daquela classe.
Se os construtores j abrangem todas as regras necessrias para validar o estado do objeto, no h preocupao em relao a manter o estado consistente, j que no h chances de modificao.
Uma boa prtica de programao evitar tocar em variveis parmetros de um mtodo. Com objetos imutveis 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 problemas no caso de acesso concorrente ao objeto.

2.8

Trabalhando com datas: Date e Calendar

Se voc fez o FJ-21 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 01/01/1970.
O armazenamento dessa forma no de todo ruim, mas o problema que a API no traz mtodos que
ajudem muito a lidar com situaes do dia como, por exemplo, adicionar dias ou meses a uma data.
A classe Date no mais recomendada porque a maior parte de seus mtodos esto marcados como
deprecated, porm ela tem amplo uso legado nas bibliotecas do java. Ela foi substituda no Java 1.1 pelo
Calendar, para haver suporte correto internacionalizao e localizao do sistema de datas.

Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - Trabalhando com datas: Date e Calendar - Pgina 12

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

Calendar: evoluo do Date


A classe abstrata Calendar tambm encapsula um instante em milissegundos, como a Date, mas ela prov
mtodos para manipulao desse momento em termos mais cotidianos como dias, meses e anos. Por ser
abstrata, no entanto, no podemos criar objetos que so simplesmente Calendars.
A subclasse concreta de Calendar mais usada a GregorianCalendar, que representa o calendrio usado pela
maior parte dos pases -- outras implementaes existem, como a do calendrio budista BuddhistCalendar,
mas estas so bem menos usadas e devolvidas de acordo com seu Locale.
H ainda a API nova do Java 8, chamada java.time, desenvolvida com base no Joda Time. Trabalharemos
aqui com Calendar por ser ainda muito mais difundida, dado que o Java 8 muito recente. Caso voc tenha
a possibilidade de trabalhar com Java 8, favorea o uso da API nova.
Para obter um Calendar que encapsula o instante atual (data e hora), usamos o mtodo esttico
getInstance() de Calendar.
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 maneira adequada, retornando o que for necessrio de acordo com o Locale configurado na mquina.

Effective Java
Item 1: 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):
Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - Trabalhando com datas: Date e Calendar - Pgina 13

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

Calendar c = Calendar.getInstance();
System.out.println("Dia do Ms: " + c.get(Calendar.DAY_OF_MONTH));
System.out.println("Dia da Semana: " + c.get(Calendar.DAY_OF_WEEK));

Um possvel resultado :
Dia do Ms: 4
Dia da Semana: 5

No exemplo acima, o dia da semana 5 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 em Calendar. O mais geral o que recebe dois argumentos: o primeiro indica qual
o campo (usando aquelas constantes de Calendar) e, o segundo, o novo valor. Alm desse mtodo, outros
mtodos set recebem valores de determinados campos; o set de trs argumentos, por exemplo, recebe ano,
ms e dia. Vejamos um exemplo de como alterar a data de hoje:
Calendar c = Calendar.getInstance();
c.set(2011, Calendar.DECEMBER, 25, 10, 30);
// mudamos a data para as 10:30am do Natal

Outro mtodo bastante usado add, que adiciona uma certa quantidade a qualquer campo do Calendar. Por
exemplo, para uma aplicao de agenda, queremos adicionar um ano data de hoje:
Calendar c = Calendar.getInstance();
c.add(Calendar.YEAR, 1); // adiciona 1 ao ano

Note que, embora o mtodo se chame add, voc pode us-lo para subtrair valores tambm; basta colocar
uma quantidade negativa no segundo argumento.
Os mtodos after e before so usados para comparar o objeto Calendar em questo a outro Calendar. O
mtodo after devolver true quando o objeto atual do Calendar representar um momento posterior ao do
Calendar passado como argumento. Por exemplo, after devolver false se compararmos o dia das crianas
com o Natal, pois o dia das crianas no vem depois do Natal:
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 verifica se o momento em questo vem antes do momento do Calendar
que foi passado como argumento. No exemplo acima, c1.before(c2) devolver true, pois o dia das crianas
vem antes do Natal.
Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - Trabalhando com datas: Date e Calendar - Pgina 14

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

Note que Calendar implementa Comparable. Isso quer dizer que voc pode usar o mtodo compareTo para
comparar dois calendrios. No fundo, after e before usam o compareTo para dar suas respostas - apenas,
fazem tal comparao de uma forma mais elegante e encapsulada.
Por ltimo, um dos problemas mais comuns quando lidamos com datas verificar o intervalo de dias entre
duas datas que podem ser at de anos diferentes. O mtodo abaixo devolve o nmero de dias entre dois
objetos Calendar. O clculo feito pegando a diferena entre as datas em milissegundos e dividindo esse
valor pelo nmero de milissegundos em um dia:
public int diferencaEmDias(Calendar c1, Calendar c2) {
long m1 = c1.getTimeInMillis();
long m2 = c2.getTimeInMillis();
return (int) ((m2 - m1) / (24*60*60*1000));
}

Relacionando Date e Calendar


Voc pode pegar um Date de um Calendar 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).

Para saber mais: Classes Deprecated e o JodaTime


O que fazer quando descobrimos que algum mtodo ou alguma classe no saiu bem do jeito que deveria?
Simplesmente apag-la e criar uma nova?
Essa uma alternativa possvel quando apenas o seu programa usa tal classe, mas definitivamente no uma
boa alternativa se sua classe j foi usada por milhes de pessoas no mundo todo.
o caso das classes do Java. Algumas delas (Date, por exemplo) so repensadas anos depois de serem lanadas e solues melhores aparecem (Calendar). Mas, para no quebrar compatibilidade com cdigos existentes, o Java mantm as funcionalidades problemticas ainda na plataforma, mesmo que uma soluo melhor
exista.
Mas como desencorajar cdigos novos a usarem funcionalidades antigas e no mais recomendadas? A prtica
no Java para isso marc-las como deprecated. Isso indica aos programadores que no devemos mais us-las
e que futuramente, em uma verso mais nova do Java, podem sair da API (embora isso nunca tenha ocorrido
na prtica).
Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - Trabalhando com datas: Date e Calendar - Pgina 15

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

Antes do Java 5, para falar que algo era deprecated, usava-se um comentrio especial no Javadoc. A partir
do Java 5, a anotao @Deprecated foi adicionada plataforma e garante verificaes do prprio compilador
(que gera um warning). Olhe o Javadoc da classe Date para ver tudo que foi deprecated.
A API de datas do Java, mesmo considerando algumas melhorias da Calendar em relao a Date, ainda
muito pobre. Numa prxima verso novas classes para facilitar ainda mais o trabalho com datas e horrios
devem entrar na especificao do Java, baseadas na excelente biblioteca JodaTime.
Para mais informaes: http://blog.caelum.com.br/2007/03/15/jsr-310-date-and-time-api/ http://jcp.org/en/
jsr/detail?id=310

2.9

Exerccios: o modelo do Argentum

1) 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:

2) Na janela que abrir em sequncia, preencha o nome do projeto como fj22-argentum e clique em Next:

Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - Exerccios: o modelo do Argentum - Pgina 16

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

3) Na prxima tela, podemos definir uma srie de configuraes do projeto (que tambm podem ser feitas
depois, atravs do menu Build path -> Configure build path, clicando com o boto da direita no projeto.
Queremos mudar o diretrio que conter nosso cdigo fonte. Faremos isso para organizar melhor nosso
projeto e utilizar convenes amplamente utilizadas no mercado.
Nessa tela, remova o diretrio src da lista de diretrios fonte:

Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - Exerccios: o modelo do Argentum - Pgina 17

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

Agora, na mesma tela, adicione um novo diretrio fonte, chamado src/main/java. Para isso, clique em
Create new source folder e preencha com src/main/java:

4) Agora basta clicar em Finish. A estrutura final de seu projeto deve estar parecida com isso:

Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - Exerccios: o modelo do Argentum - Pgina 18

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

5) Crie

classe

usando

ctrl + N
br.com.caelum.argentum.modelo:

Class,

chamada

Negociacao

dentro

do

pacote

6) Transforme a classe em final e j declare os trs atributos que fazem parte de uma negociao da bolsa de
valores (tambm como final):
public final class Negociacao {
private final double preco;
private final int quantidade;
private final Calendar data;
}

Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - Exerccios: o modelo do Argentum - Pgina 19

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

No esquea de importar o Calendar!


7) Vamos criar um construtor que recebe esses dados, j que so obrigatrios para nosso domnio. Em vez
de fazer isso na mo, na edio da classe, use o atalho ctrl + 3 e comece a digitar constructor. Ele vai
mostrar uma lista das opes que contm essa palavra: escolha a Generate constructor using fields.
Alternativamente, tecle ctrl + 3 e digite GCUF, que so as iniciais do menu que queremos acessar.

Agora, selecione todos os campos e marque para omitir a invocao ao super, como na tela abaixo.
Ateno para deixar os campos na ordem preco, quantidade, data. Voc pode usar os botes Up e
Down para mudar a ordem.

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 2 - O modelo da bolsa de valores, datas e objetos imutveis - Exerccios: o modelo do Argentum - Pgina 20

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

8) Agora, vamos gerar os getters dessa classe. Faa ctrl + 3 e comece a digitar getter, as opes aparecero e
basta voc escolher generate getters and setters. sempre bom praticar os atalhos do ctrl + 3.

Selecione os getters e depois Finish:

9) Verifique 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 2 - O modelo da bolsa de valores, datas e objetos imutveis - Exerccios: o modelo do Argentum - Pgina 21

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

return data;
}
}

10) Um dado importante para termos noo da estabilidade de uma ao na bolsa de valores o volume de
dinheiro negociado em um perodo.
Vamos fazer nossa classe Negociacao devolver o volume de dinheiro transferido naquela negociao.
Na prtica, s multiplicar o preco pago pela quantidade de aes negociadas, resultando no total de
dinheiro que aquela negociao realizou.
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 refletem um atributo da classe.
11) Siga o mesmo procedimento para criar a classe Candlestick. Use o ctrl + N Class para isso, marque-a
como final e adicione os seguintes atributos finais, nessa ordem:
public final class Candlestick {
private final double abertura;
private final double fechamento;
private final double minimo;
private final double maximo;
private final double volume;
private final Calendar data;
}

12) Use o ctrl + 3 para gerar o construtor com os seis atributos. Ateno ordem dos parmetros no construtor:

Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - Exerccios: o modelo do Argentum - Pgina 22

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

13) Gere tambm os seis respectivos getters, usando o ctrl + 3.


A classe final deve ficar 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 2 - O modelo da bolsa de valores, datas e objetos imutveis - Exerccios: o modelo do Argentum - Pgina 23

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

return minimo;
}
public double getMaximo() {
return maximo;
}
public double getVolume() {
return volume;
}
public Calendar getData() {
return data;
}
}

14) (opcional) Vamos adicionar dois mtodos de negcio, para que o Candlestick possa nos dizer se ele do
tipo de alta, ou se de baixa:
public boolean isAlta() {
return this.abertura < this.fechamento;
}
public boolean isBaixa() {
return this.abertura > this.fechamento;
}

2.10

Resumo dirio das Negociaes

Agora que temos as classes que representam negociaes 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 vamos criar a candle, a lista de negociaes j vem ordenada por tempo. Dessa forma, a abertura e o fechamento
Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - Resumo dirio das Negociaes - Pgina 24

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

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 verificados. Dessa forma, precisamos
passar por cada negociao da lista verificando se aquele valor menor do que todos os outros que j vimos, maior que nosso mximo atual. Aproveitando esse processo de passar por cada negociao, j vamos
somando o volume de cada negociao.
O algoritmo, agora, est completamente especificado! Basta passarmos essas ideias para cdigo. Para isso,
lembremos, voc pode usar alguns atalhos que j vimos antes:
Ctrl + N: cria novo(a)...
Ctrl + espao: autocompleta
Ctrl + 1: resolve pequenos problemas de compilao e atribui objetos a variveis.

Em que classe colocar?


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 responsabilidades que no cabem a eles!
Criaremos, ento, uma classe que: dado a matria-prima, nos constri uma candle. E uma classe com esse
comportamento, que recebem o necessrio para criar um objeto e encapsulam o algoritmo para tal criao,
costuma ser chamadas de Factory.
No nosso caso particular, essa uma fbrica que cria Candlesticks, ento, seu nome fica
CandlestickFactory.
Perceba que esse nome, apesar de ser um tal Design Pattern nada mais faz do que encapsular uma lgica um
pouco mais complexa, isto , apenas aplica boas prticas de orientao a objetos que voc j vem estudando
desde o FJ-11.

2.11

Exerccios: fbrica de Candlestick

1) 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
ficar numa classe a parte, o que tambm muito comum. Vamos criar a classe CandlestickFactory
dentro do pacote br.com.caelum.argentum.modelo:

Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - Exerccios: fbrica de Candlestick - Pgina 25

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

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) {
}
}

2) Procuraremos os preos mximo e mnimo percorrendo todas as negociaes. Para isso usaremos variveis auxiliares maximo e minimo e, dentro do for, verificaremos se o preo da negociao
atual maior que o valor da varivel maximo. Se no for, veremos se ele menor que o minimo.
Calcularemos o volume somando o volume de cada negociao em uma varivel auxiliar chamada
volume. Poderemos pegar o preo de abertura atravs de negociacoes.get(0) e o de fechamento por
negociacoes.get(negociacoes.size() - 1).
public class CandlestickFactory {
public Candlestick constroiCandleParaData(Calendar data,
List<Negociacao> negociacoes) {
double maximo = negociacoes.get(0).getPreco();
double minimo = negociacoes.get(0).getPreco();

Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - Exerccios: fbrica de Candlestick - Pgina 26

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

double volume = 0;
// 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);
}
}

3) Vamos testar nosso cdigo, criando 4 negociaes e calculando o Candlestick, finalmente. 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
Negociacao
Negociacao
Negociacao

negociacao1
negociacao2
negociacao3
negociacao4

=
=
=
=

new
new
new
new

Negociacao(40.5,
Negociacao(45.0,
Negociacao(39.8,
Negociacao(42.3,

100,
100,
100,
100,

hoje);
hoje);
hoje);
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());
Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - Exerccios: fbrica de Candlestick - Pgina 27

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

System.out.println(candle.getVolume());
}
}

O mtodo asList da classe java.util.Arrays cria uma lista dada uma array. Mas no passamos 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.

Effective Java
Item 47: Conhea e use as bibliotecas!
A sada deve ser parecida com:
40.5
42.3
39.8
45.0
16760.0

2.12

Exerccios opcionais
Effective Java

1)
Item 10: Sempre reescreva o toString
Reescreva o toString da classe Candlestick. Como o toString da classe Calendar retorna uma
String bastante complexa, faa com que a data seja corretamente visualizada, usando para isso o
SimpleDateFormat. Procure sobre essa classe na API do Java.
Ao imprimir um candlestick, por exemplo, a sada deve ser algo como segue:
[Abertura 40.5, Fechamento 42.3, Mnima 39.8, Mxima 45.0,
Volume 145234.20, Data 12/07/2008]

Para reescrever um mtodo e tirar proveito do Eclipse, a maneira mais direta de dentro da classe
Candlestick, fora de qualquer mtodo, pressionar ctrl + espao.
Uma lista com todas as opes de mtodos que voc pode reescrever vai aparecer. Escolha o toString, e
ao pressionar enter o esqueleto da reescrita ser montado.
2) Um double segue uma regra bem definida em relao a contas e arredondamento, e para ser rpido e caber
em 64 bits, no tem preciso infinita. A classe BigDecimal pode oferecer recursos mais interessantes em
um ambiente onde as casas decimais so valiosas, como um sistema financeiro. Pesquise a respeito.
Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - Exerccios opcionais - Pgina 28

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

3) O construtor da classe Candlestick simplesmente muito grande. Poderamos usar uma factory, porm
continuaramos passando muitos argumentos para um determinado mtodo.
Quando construir um objeto complicado, ou confuso, costumamos usar o padro Builder para resolver
isso. Builder uma classe que ajuda voc a construir um determinado objeto em uma srie de passos,
independente da ordem.

Effective Java
Item 2: 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
fluent interface, podemos tornar o cdigo acima mais conciso, sem perder a legibilidade:
Candlestick candle = new CandleBuilder().comAbertura(40.5)
.comFechamento(42.3).comMinimo(39.8).comMaximo(45.0)
.comVolume(145234.20).comData(
new GregorianCalendar(2008, 8, 12, 0, 0, 0)).geraCandle();

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 2 - O modelo da bolsa de valores, datas e objetos imutveis - Exerccios opcionais - Pgina 29

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

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 fluent interface e
mtodos auxiliares.

Usos famosos de Fluent Interface e DSLs


Fluent interfaces so muito usadas no Hibernate, por exemplo. O jQuery, uma famosa biblioteca
de efeitos javascript, popularizou-se por causa de sua fluent interface. O JodaTime e o JMock so
dois excelentes exemplos.
So muito usadas (e recomendadas) na construo de DSLs, Domain Specific Languages. Martin
Fowler fala bastante sobre fluent interfaces nesse timo artigo:
http://martinfowler.com/bliki/FluentInterface.html

Captulo 2 - O modelo da bolsa de valores, datas e objetos imutveis - Exerccios opcionais - Pgina 30

Captulo 3

Testes Automatizados
Apenas duas coisas so infinitas: o universo e a estupidez humana. E eu no tenho certeza do primeiro.
Albert Einstein

3.1

Nosso cdigo est funcionando corretamente?

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 verificar isso e fazer as perguntas
corretas.
Pode parecer que o cdigo funciona, mas ele tem muitas falhas. Olhemos com mais cuidado.

3.2

Exerccios: testando nosso modelo sem frameworks

1) 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?
2) Mais um teste: as aes menos negociadas podem ficar dias sem nenhuma operao acontecer. O que
nosso sistema gera nesse caso?
Vamos ao teste:
public class TestaCandlestickFactorySemNegociacoes {
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?

3) ArrayIndexOutOfBoundsException certamente uma pssima exceo para indicar que no teremos


Candle.

Captulo 3 - Testes Automatizados - Exerccios: testando nosso modelo sem frameworks - Pgina 32

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

Qual deciso vamos tomar? Podemos lanar nossa prpria exception, podemos retornar null ou ainda
podemos devolver um Candlestick que possui um significado especial. Devolver null deve ser sempre
a ltima opo.
Vamos retornar um Candlestick que possui um volume zero. Para corrigir o erro, vamos alterar o cdigo
do nosso CandlestickFactory.
Poderamos usar um if logo de cara para verificar se negociacoes.isEmpty(), porm podemos tentar
algo mais sutil, sem ter que criar vrios pontos de return.
Vamos ento iniciar os valores de minimo e maximo sem usar a lista, que pode estar vazia. Mas, para nosso
algoritmo funcionar, precisaramos iniciar o maximo com um valor bem pequeno, isto , menor do que o
da ao mais barata. Assim, quando percorrermos o for, qualquer valor que encontremos vai substituir
o maximo.
No caso do mximo, fcil pensar nesse valor! Qual o limite inferior para o preo de uma ao? Ser
que ele chega a ser negativo? A resposta no. Ningum vai vender uma ao por um preo negativo!
Portanto, se inicializarmos o mximo com zero, certeza que ele ser substituido na primeira iterao do
for.
Similarmente, queremos inicializar o minimo com um valor bem grande, maior do que o maior valor
possvel para o valor de uma ao. Esse um problema mais complexo, j que no existe um limitante
superior to claro para o preo de uma ao!
Qual valor colocaremos, ento? Quanto um nmero grande o suficiente? Podemos apelar para a limitao do tipo que estamos usando! Se o preo um double, certamente no poderemos colocar nenhum
valor que estoure o tamanho do double. Felizmente, a classe Double conta com a constante que representa
o maior double vlido! o Double.MAX_VALUE.
Altere o mtodo constroiCandleParaData da classe CandlestickFactory:
double maximo = 0;
double minimo = Double.MAX_VALUE;

Alm disso, devemos verificar se negociacoes est vazia na hora de calcular o preo de abertura e
fechamento. Altere novamente o mtodo:
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!
4) Ser que tudo est bem? Rode novamente os outros dois testes, o que acontece?
Incrvel! Consertamos um bug, mas adicionamos outro. A situao lhe parece familiar? Ns desenvolvedores vivemos com isso o tempo todo: tentando fugir dos velhos bugs que continuam a reaparecer!

Captulo 3 - Testes Automatizados - Exerccios: testando nosso modelo sem frameworks - Pgina 33

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

O teste com apenas uma negociao retorna 1.7976931348623157E308 como valor mnimo agora! Mas
deveria ser 40.5. Ainda bem que lembramos de rodar essa classe, e que percebemos que esse nmero est
diferente do que deveria ser.
Vamos sempre confiar em nossa memria?
5) (opcional) Ser que esse erro est ligado a ter apenas uma negociao? Vamos tentar com mais negociaes? Crie e rode um teste com as seguintes negociaes:
Negociacao
Negociacao
Negociacao
Negociacao

negociacao1
negociacao2
negociacao3
negociacao4

=
=
=
=

new
new
new
new

Negociacao(40.5,
Negociacao(45.0,
Negociacao(49.8,
Negociacao(53.3,

100,
100,
100,
100,

hoje);
hoje);
hoje);
hoje);

E com uma sequncia decrescente, funciona? Por qu?

3.3

Definindo melhor o sistema e descobrindo mais bugs

Segue uma lista de dvidas pertinentes ao Argentum. Algumas dessas perguntas voc no saber responder, porque no definimos 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.
1) Uma negociao da Petrobras a 30 reais, com uma quantidade negativa de negociaes vlida? E com
nmero zero de negociaes?
Em outras palavras, posso dar new em uma Negociacao com esses dados?
2) Uma negociao com data nula vlida? Posso dar new Negociacao(10, 5, null)? Deveria poder?
3) Um candle realmente imutvel? No podemos mudar a data de um candle de maneira alguma?
4) Um candle em que o preo de abertura igual ao preo de fechamento, um candle de alta ou de baixa?
O que o sistema diz? O que o sistema deveria dizer?
5) Como geramos um candle de um dia que no houve negociao? O que acontece?
6) E se a ordem das negociaes passadas ao CandlestickFactory no estiver na ordem crescente das datas?
Devemos aceitar? No devemos?
7) E se essas Negociaes forem de dias diferentes que a data passada como argumento para a factory?

3.4

Testes de Unidade

Testes de unidade so testes que testam apenas uma classe ou mtodo, verificando se seu comportamento
est de acordo com o desejado. Em testes de unidade, verificamos a funcionalidade da classe e/ou mtodo
Captulo 3 - Testes Automatizados - Definindo melhor o sistema e descobrindo mais bugs - Pgina 34

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

em questo passando o mnimo possvel por outras classes ou dependncias do nosso sistema.

Unidade
Unidade a menor parte testvel de uma aplicao. Em uma linguagem de programao orientada a objetos como o Java, a menor unidade um mtodo.
O termo correto para esses testes testes de unidade, porm o termo teste unitrio propagou-se
e o mais encontrado nas tradues.
Em testes de unidade, no estamos interessados no comportamento real das dependncias da classe, mas em
como a classe em questo se comporta diante das possveis respostas das dependncias, ou ento se a classe
modificou as dependncias da maneira esperada.
Para isso, quando criamos um teste de unidade, simulamos a execuo de mtodos da classe a ser testada.
Fazemos isso passando parmetros (no caso de ser necessrio) ao mtodo testado e definimos o resultado
que esperamos. Se o resultado for igual ao que definimos como esperado, o teste passa. Caso contrrio, falha.

Ateno
Muitas vezes, principalmente quando estamos iniciando no mundo dos testes, comum criarmos
alguns testes que testam muito mais do que o necessrio, mais do que apenas a unidade. Tais
testes se transformam em verdadeiros testes de integrao (esses sim so responsveis por testar
o sistemas como um todo).
Portanto, lembre-se sempre: testes de unidade testam apenas unidades!

3.5

JUnit

O JUnit (junit.org) um framework muito simples para facilitar a criao destes testes de unidade e em
especial sua execuo. Ele possui alguns mtodos que tornam seu cdigo de teste bem legvel e fcil de fazer
as asseres.
Uma assero uma afirmao: alguma invariante que em determinado ponto de execuo voc quer garantir que verdadeira. Se aquilo no for verdade, o teste deve indicar uma falha, a ser reportada para o
programador, indicando um possvel bug.
medida que voc mexe no seu cdigo, voc roda novamente toda aquela bateria de testes com um comando
apenas. Com isso voc ganha a confiana de que novos bugs no esto sendo introduzidos (ou reintroduzidos) 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
Captulo 3 - Testes Automatizados - JUnit - Pgina 35

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

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.

Usando o JUnit - configurando Classpath e seu JAR no Eclipse


O JUnit uma biblioteca escrita por terceiros que vamos usar no nosso projeto. Precisamos das classes do
JUnit para escrever nossos testes. E, como sabemos, o formato de distribuio de bibliotecas Java o JAR,
muito similar a um ZIP com as classes daquela biblioteca.
Precisamos ento do JAR do JUnit no nosso projeto. Mas quando rodarmos nossa aplicao, como o Java vai
saber que deve incluir as classes daquele determinado JAR junto com nosso programa? (dependncia)
aqui que o Classpath entra histria: nele que definimos qual o caminho para buscar as classes que vamos
usar. Temos que indicar onde a JVM deve buscar as classes para compilar e rodar nossa aplicao.
H algumas formas de configurarmos o classpath:
Configurando 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 configurar por voc.
No Eclipse, muito simples:
1) Clique com o boto direito em cima do nome do seu projeto.
2) Escolha a opo Properties.
3) Na parte esquerda da tela, selecione a opo Java Build Path.
E, nessa tela:
1) Java Build Path onde voc configura o classpath do seu projeto: lista de locais definidos que, por
padro, s vm com a mquina virtual configurada;
2) Opes para adicionar mais caminhos, Add JARs... adiciona Jars que estejam no seu projeto; Add
External JARs adiciona Jars que estejam em qualquer outro lugar da mquina, porm guardar uma
referncia para aquele caminho (ento seu projeto poder no funcionar corretamente quando colocado
em outro micro, mas existe como utilizar variveis para isso);
No caso do JUnit, por existir integrao direta com Eclipse, o processo ainda mais fcil, como veremos no
exerccio. Mas para todas as outras bibliotecas que formos usar, basta copiar o JAR e adicion-lo ao Build
Path. Vamos ver esse procedimento com detalhes quando usarmos as bibliotecas que trabalham com XML
e grficos em captulos posteriores.

Captulo 3 - Testes Automatizados - JUnit - Pgina 36

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

3.6

Anotaes

Anotao a maneira de escrever metadados na prpria classe, isto , configuraes ou outras informaes
pertinentes a essa classe. Esse recurso foi introduzido no Java 5.0. Algumas anotaes podem ser mantidas
(retained) no .class, permitindo que possamos reaver essas informaes, se necessrio.
utilizada, por exemplo, para indicar que determinada classe deve ser processada por um framework de
uma certa maneira, evitando assim as clssicas configuraes atravs de centenas de linhas de XML.
Apesar dessa propriedade interessante, algumas anotaes servem apenas para indicar algo ao compilador.
@Override o exemplo disso. Caso voc use essa anotao em um mtodo que no foi reescrito, vai haver
um erro de compilao! A vantagem de us-la apenas para facilitar a legibilidade.
@Deprecated indica que um mtodo no deve ser mais utilizado por algum motivo e decidiram no retir-lo

da API para no quebrar programas que j funcionavam anteriormente.


@SurpressWarnings indica para o compilador que ele no deve dar warnings a respeito de determinado

problema, indicando que o programador sabe o que est fazendo. Um exemplo o warning que o compilador
do Eclipse d quando voc no usa determinada varivel. Voc vai ver que um dos quick fixes a sugesto
de usar o @SupressWarnings.
Anotaes podem receber parmetros. Existem muitas delas na API do java 5, mas realmente ainda mais
utilizada em frameworks, como o Hibernate 3, o EJB 3 e o JUnit4.

3.7

JUnit4, convenes e anotao

Para cada classe, teremos uma classe correspondente (por conveno, com o sufixo Test) que contar todos
os testes relativos aos mtodos dessa classe. Essa classe ficar 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
Negociacao
Negociacao
Negociacao

negociacao1
negociacao2
negociacao3
negociacao4

=
=
=
=

new
new
new
new

Negociacao(40.5,
Negociacao(45.0,
Negociacao(39.8,
Negociacao(42.3,

100,
100,
100,
100,

hoje);
hoje);
hoje);
hoje);

List<Negociacao> negociacoes = Arrays.asList(negociacao1, negociacao2,


Captulo 3 - Testes Automatizados - Anotaes - Pgina 37

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

negociacao3, negociacao4);
CandlestickFactory fabrica = new CandlestickFactory();
Candlestick candle = fabrica.constroiCandleParaData(hoje, negociacoes);
}
}

Em vez de um main, criamos um mtodo com nome expressivo para descrever a situao que ele est testando.
Mas... como o JUnit saber que deve executar aquele mtodo? Para isso anotamos este mtodo com @Test,
que far com que o JUnit saiba no momento de execuo, por reflection, de que aquele mtodo deva ser
executado:
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 verificao. Ela realizada atravs dos mtodos estticos da classe Assert, importada
do org.junit. Por exemplo, podemos verificar se o valor de abertura desse candle 40.5:
Assert.assertEquals(40.5, candle.getAbertura(), 0.00001);

O primeiro argumento o que chamamos de expected, e ele representa o valor que esperamos para argumento
seguinte (chamado de actual). Se o valor real for diferente do esperado, o teste no passar e uma barrinha
vermelha ser mostrada, juntamente com uma mensagem que diz:
expected <valor esperado> but was <o que realmente deu>

Double inexato
Logo na primeira discusso desse curso, conversamos sobre a inexatido do double ao trabalhar com arredondamentos. Porm, diversas vezes, gostaramos de comparar o double esperado e o valor real, sem nos
preocupar com diferenas de arredondamento quando elas so muito pequenas.
O JUnit trata esse caso adicionando um terceiro argumento, que s necessrio quando comparamos valores
double ou float. Ele um delta que se aceita para o erro de comparao entre o valor esperado e o real.

Captulo 3 - Testes Automatizados - JUnit4, convenes e anotao - Pgina 38

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

Por exemplo, quando lidamos com dinheiro, o que nos importa so as duas primeiras casas decimais e,
portanto, no h problemas se o erro for na quinta casa decimal. Em softwares de engenharia, no entanto,
um erro na quarta casa decimal pode ser um grande problema e, portanto, o delta deve ser ainda menor.
Nosso cdigo final do teste, agora com as devidas asseres, ficar assim:
public class CandlestickFactoryTest {
@Test
public void sequenciaSimplesDeNegociacoes() {
Calendar hoje = Calendar.getInstance();
Negociacao
Negociacao
Negociacao
Negociacao

negociacao1
negociacao2
negociacao3
negociacao4

=
=
=
=

new
new
new
new

Negociacao(40.5,
Negociacao(45.0,
Negociacao(39.8,
Negociacao(42.3,

100,
100,
100,
100,

hoje);
hoje);
hoje);
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.

3.8

Exerccios: migrando os testes do main para JUnit

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 filtro a encontre:

Captulo 3 - Testes Automatizados - Exerccios: migrando os testes do main para JUnit - Pgina 39

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

b) Preencha com src/test/java e clique Finish:

nesse novo diretrio em que voc colocar todos seus testes de unidade.
2) Vamos criar um novo unit test em cima da classe CandlestickFactory. O Eclipse j ajuda bastante: com
o editor na CandlestickFactory, crie um novo (ctrl + N) JUnit Test Case.
Na janela seguinte, selecione o source folder como src/test/java. No esquea, tambm, de selecionar
JUnit4.

Captulo 3 - Testes Automatizados - Exerccios: migrando os testes do main para JUnit - Pgina 40

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

Ao clicar em Finish, o Eclipse te perguntar se pode adicionar os jars do JUnit no projeto.

A anotao @Test indica que aquele mtodo deve ser executado na bateria de testes, e a classe Assert possui 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() {
Captulo 3 - Testes Automatizados - Exerccios: migrando os testes do main para JUnit - Pgina 41

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

Calendar hoje = Calendar.getInstance();


Negociacao
Negociacao
Negociacao
Negociacao

negociacao1
negociacao2
negociacao3
negociacao4

=
=
=
=

new
new
new
new

Negociacao(40.5,
Negociacao(45.0,
Negociacao(39.8,
Negociacao(42.3,

100,
100,
100,
100,

hoje);
hoje);
hoje);
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 + F11: roda o que estiver aberto no editor;
alt + shift + 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:

Captulo 3 - Testes Automatizados - Exerccios: migrando os testes do main para JUnit - Pgina 42

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

O nmero correto mesmo 16760.0. Adicione esse zero na classe de teste e rode-o novamente:

comum digitarmos errado no teste e o teste falhar, por isso, importante sempre verificar a corretude
do teste, tambm!
3) Vamos adicionar outro mtodo de teste mesma classe CandlestickFactoryTest, dessa vez para testar
o mtodo no caso de no haver nenhuma negociao:
@Test
public void semNegociacoesGeraCandleComZeros() {
Calendar hoje = Calendar.getInstance();
List<Negociacao> negociacoes = Arrays.asList();
CandlestickFactory fabrica = new CandlestickFactory();
Captulo 3 - Testes Automatizados - Exerccios: migrando os testes do main para JUnit - Pgina 43

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

Candlestick candle = fabrica.constroiCandleParaData(hoje, negociacoes);


Assert.assertEquals(0.0, candle.getVolume(), 0.00001);
}

Rode o teste com o mesmo atalho.


4) E, agora, vamos para o que tem apenas uma negociao e estava falhando. Ainda na classe
CandlestickFactoryTest adicione o mtodo: (repare que cada classe de teste possui vrios mtodos
com vrios casos diferentes)
@Test
public void apenasUmaNegociacaoGeraCandleComValoresIguais() {
Calendar hoje = Calendar.getInstance();
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 3 - Testes Automatizados - Exerccios: migrando os testes do main para JUnit - Pgina 44

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

Como consertar?

3.9

Vale a pena testar classes de modelo?

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 especficos como:
1) as classes Negociacao e Candlestick devem ser imutveis, isto , no devemos ser capazes de alterar
nenhuma de suas informaes depois que o objeto criado;
2) valores negativos tambm no deveriam estar presentes nas negociaes e candles;
3) se voc fez o opcional CandleBuilder, ele no deveria gerar a candle se os valores no tiverem sido preenchidos;
4) etc...
Por essa razo, ainda que sejam classes mais simples, elas merecem ter sua integridade testada - mesmo
porque so os objetos que representam nosso modelo de negcios, o corao do sistema que estamos desenvolvendo.
Captulo 3 - Testes Automatizados - Vale a pena testar classes de modelo? - Pgina 45

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

3.10

Exerccios: novos testes

1) A classe Negociacao realmente imutvel?


Vamos criar um novo Unit Test para a classe Negociacao. O processo o mesmo que fizemos para o teste
da CandlestickFactory: abra a classe Negociacao no editor e faa Ctrl + N JUnit Test Case.
Lembre-se de alterar a Source Folder para src/test/java e selecionar o JUnit 4.
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 + shift + X T) ou pode fazer melhor e o que mais
comum, rodar todos os testes de unidade de um projeto.
Basta selecionar o projeto na View Package Explorer e mandar rodar os testes: para essa ao, o nico
atalho possvel o alt + shift + X T.

Captulo 3 - Testes Automatizados - Exerccios: novos testes - Pgina 46

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.

Effective Java
Item 39: 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 3 - Testes Automatizados - Exerccios: novos testes - Pgina 47

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

Listas e arrays
Esse tambm um problema que ocorre muito com colees e arrays: se voc retorna uma List
que um atributo seu, qualquer um pode adicionar ou remover um elemento de l, causando
estrago nos seus atributos internos.
Os mtodos Collections.unmodifiableList(List) e outros ajudam bastante nesse trabalho.
2) Podemos criar uma Negociacao com data nula? Por enquanto, podemos, mas no deveramos. Para que
outras partes do meu sistema no se surpreendam mais tarde, vamos impedir que a Negociacao seja criada
se sua data estiver nula, isto , vamos lanar uma exceo.
Mas qual exceo? Vale a pena criar uma nova exceo para isso?
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.

Effective Java
Item 60: Favorea o uso das excees padres!
Antes de fazer a modificao na classe, vamos preparar o teste. Mas o que queremos testar? Queremos
saber se nossa classe Negociacao no permite a criao do objeto e lana uma IllegalArgumentException
quando passamos null no construtor.
Ou seja, esperamos que uma exceo acontea! Para o teste passar, ele precisa dar a exceo (parece meio
contraditrio). fcil fazer isso com JUnit.
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 verificamos o argumento na classe Negociacao e
ainda no lanamos a exceo:

Captulo 3 - Testes Automatizados - Exerccios: novos testes - Pgina 48

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 3 - Testes Automatizados - Exerccios: novos testes - Pgina 49

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

3) (opcional) Nosso teste para quando no h negociaes na CandlestickFactory est verificando apenas
se o volume zero. Ele tambm poderia verificar que os outros valores dessa candle so zero.
Modifique 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.
4) (opcional) Um Candlestick pode ter preo mximo menor que o preo mnimo? No deveria.
Crie um novo teste, o CandlestickTest, da maneira que fizemos com o Negociacao. boa prtica que
todos os testes da classe X se encontrem em XTest.
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 construtor recebe como argumento Candlestick(abertura, fechamento, minimo, maximo, volume, data),
portanto queremos testar se algo assim gera uma exceo (e deveria gerar):
new Candlestick(10, 20, 20, 10, 10000, Calendar.getInstance());

5) (opcional) Um Candlestick pode ter data nula? Pode ter algum valor negativo?
Teste, verifique o que est errado, altere cdigo para que os testes passem! Pegue o ritmo, essa ser sua
rotina daqui para a frente.

Captulo 3 - Testes Automatizados - Exerccios: novos testes - Pgina 50

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

6) (opcional) Crie mais dois testes na CandlestickFactoryTest: o negociacoesEmOrdemCrescenteDeValor


e negociacoesEmOrdemDecrescenteDeValor, que devem fazer o que o prprio nome diz.
Agora eles funcionam?

3.11

Para saber mais: Import Esttico

Algumas vezes, escrevemos classes que contm muitos mtodos e atributos estticos (finais, como constantes). 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 ficar muito chato escrever, toda hora, o nome da classe. Para resolver esse problema, no Java 5.0
foi introduzido o static import, que importa mtodos e atributos estticos de qualquer classe. Usando essa
nova tcnica, voc pode importar os mtodos do exemplo anterior e us-los diretamente:
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 3 - Testes Automatizados - Para saber mais: Import Esttico - Pgina 51

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.

3.12

Mais exerccios opcionais

1) 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 um teste geracaoDeCandleDeveTerTodosOsDadosNecessarios que tente isso. O mtodo 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 utilizando alguma outra forma de verificao.
2) Se voc fez os opcionais do primeiro exerccio do captulo anterior (criao do projeto e dos modelos)
voc tem os mtodos isAlta e isBaixa na classe Candlestick. Contudo, temos um comportamento no
especificado nesses mtodos: e quando o preo de abertura for igual ao de fechamento?
Perguntando para nosso cliente, ele nos informou que, nesse caso, o candle deve ser considerado de alta.
Crie o teste quandoAberturaIgualFechamentoEhAlta dentro de CandlestickTest, verifique se isso est
ocorrendo. Se o teste falhar, faa mudanas no seu cdigo para que a barra volte a ficar verde!
3) O que mais pode ser testado? Testar viciante, e aumentar o nmero de testes do nosso sistema comea
a virar um hbito divertido e contagioso. Isso no ocorre de imediato, necessrio um tempo para se
apaixonar por testes.

3.13

Discusso em aula: testes so importantes?

Captulo 3 - Testes Automatizados - Mais exerccios opcionais - Pgina 52

Captulo 4

Trabalhando com XML


Se eu enxerguei longe, foi por ter subido nos ombros de gigantes."
Isaac Newton

4.1

Os dados da bolsa de valores

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 comumente 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.

4.2

O formato XML

XML (eXtensible Markup Language) uma formalizao da W3C para gerar linguagens de marcao que
podem se adaptar a quase qualquer tipo de necessidade. Algo bem extensvel, flexvel, de fcil leitura e
hierarquizao. Sua definio formal pode ser encontrada em:
http://www.w3.org/XML/
Exemplo de dados que so armazenados em XMLs e que no conhecemos to bem, o formato aberto de
grficos vetoriais, o SVG (usado pelo Corel Draw, Firefox, Inkscape, etc), e o Open Document Format (ODF),
formato usado pelo OpenOffice, e hoje em dia um padro ISO de extrema importncia. (na verdade o ODF
um ZIP que contm XMLs internamente).
A ideia era criar uma linguagem de marcao que fosse muito fcil de ser lida e gerada por softwares, e
pudesse ser integrada as outras linguagens. Entre seus princpios bsicos, definidos pelo W3C:
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-filho entre seus elementos. Esse tipo de arquivo dificilmente
organizado com CSVs ou properties. Como a prpria imagem do wikipedia nos trs e mostra o uso estruturado e encadeado de maneira hierrquica do XML:

Captulo 4 - Trabalhando com XML - O formato XML - Pgina 54

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 linguagem existente, possui uma ou mais formas de ler um XML. O Java possui diversas, vamos ver
algumas delas, suas vantagens e suas desvantagens.

4.3

Lendo XML com Java de maneira difcil, o SAX

O SAX (Simple API for XML) uma API para ler dados em XML, tambm conhecido 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 fluxo ou uma sequncia de dados. Baseado no contedo lido, o parser
vai disparando eventos. o mesmo que dizer que o parser SAX funciona orientado a eventos.
Existem vrios tipos de eventos, por exemplo:
Captulo 4 - Trabalhando com XML - Lendo XML com Java de maneira difcil, o SAX - Pgina 55

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

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 notificado automaticamente pelo parser quando um desses eventos ocorrer. Comumente, este objeto chamado de Handler,
Observer, ou Listener e quem faz o trabalho necessrio de processamento do XML.
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
}
}

A classe DefaultHandler permite que voc reescreva mtodos que vo te notificar sobre quando um elemento
(tag) est sendo aberto, quando est sendo fechado, quando caracteres esto sendo parseados (contedo de
Captulo 4 - Trabalhando com XML - Lendo XML com Java de maneira difcil, o SAX - Pgina 56

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

uma tag), etc.. Voc o responsvel por saber em que posio do object model (rvore) est, e que atitude
deve ser tomada. A interface ContentHandler define mais alguns outros mtodos.

Curiosidade sobre 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 2 e faz parte do JAX-P (Java API for XML Processing).
O SAX somente sabe ler dados e nunca modific-los e s consegue ler para frente, nunca para trs. Quando
passou um determinado pedao do XML que j foi lido, no h mais como voltar. O parser SAX no guarda
a estrutura do documento XML na memria.
Tambm no h como fazer acesso aleatrio aos itens do documento XML, somente sequencial.
Por outro lado, como os dados vo sendo analisados e transformados (pelo Handler) na hora da leitura, o
SAX ocupa pouca memria, principalmente porque nunca vai conhecer o documento inteiro e sim somente
um pequeno pedao. Devido tambm a leitura sequencial, ele muito rpido comparado com os parsers que
analisam a rvore do documento XML completo.
Quando for necessrio ler um documento em partes ou s determinado pedao e apenas uma vez, o SAX
parser uma excelente opo.

StAX - Streaming API for XML


StAX um projeto que foi desenvolvido pela empresa BEA e padronizado pela JSR-173. Ele
mais novo do que o SAX e foi criado para facilitar o trabalho com XML. StAX faz parte do Java
SE 6 e JAX-P.
Como o SAX, o StAX tambm l os dados de maneira sequencial. A diferena entre os dois a
forma como notificada a ocorrncia de um evento.
No SAX temos que registrar um Handler. o SAX que avisa o Handler e chama os mtodos dele.
Ele empurra os dados para o Handler e por isso ele um parser do tipo push, .
O StAX, ao contrrio, no precisa deste Handler. Podemos usar a API do StAX para chamar seus
mtodos, quando e onde preciso. O cliente decide, e no o parser. ele quem pega/tira os
dados do StAX e por isso um parser do tipo pull.
O site http://www.xmlpull.org fornece mais informaes sobre a tcnica de Pull Parsing, que
tem sido considerada por muitos como a forma mais eficiente de processar documentos xml.
A biblioteca XPP3 a implementao em Java mais conhecida deste conceito. usada por outras
bibliotecas de processamento de xml, como o CodeHaus XStream.

Captulo 4 - Trabalhando com XML - Lendo XML com Java de maneira difcil, o SAX - Pgina 57

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

4.4

XStream

O XStream uma alternativa perfeita para os casos de uso de XML em persistncia, transmisso de dados e
configurao. Sua facilidade de uso e performance elevada so os seus principais atrativos.
um projeto hospedado na Codehaus, um repositrio de cdigo open source focado em Java, que foi formado por desenvolvedores de famosos projetos como o XDoclet, PicoContainer e Maven. O grupo patrocinado por empresas como a ThoughWorks, BEA e 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 configuraes 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 definir se quer usar SAX, DOM, DOM4J dentre outros, e com isso o XStream ser mais rpido,
mais lento, usar mais ou menos memria, etc.
O default do XStream usar um driver chamado XPP3, desenvolvido na universidade de Indiana e conhecido
por ser extremamente rpido (leia mais no box de pull parsers). Para us-lo voc precisa de um outro JAR
no classpath do seu projeto.
Captulo 4 - Trabalhando com XML - XStream - Pgina 58

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 XStream serializa por default os objetos atravs de seus atributos
(sejam privados ou no), e no atravs de getters e setters.
Repare que o XStream gerou a tag raiz com o nome de br.com.caelum.argentum.Negociacao. Isso porque
no existe um conversor para ela, ento ele usa o prprio nome da classe e gera o XML recursivamente para
cada atributo no transiente daquela classe.
Porm, muitas vezes temos um esquema de XML j muito bem definido, ou simplesmente no queremos
gerar um XML com cara de java. Para isso podemos utilizar um alias. Vamos modificar nosso cdigo que
gera o XML:
XStream stream = new XStream(new DomDriver());
stream.alias("negociacao", Negociacao.class);

Essa configurao tambm pode ser feita atravs da anotao @XStreamAlias("negociacao") em cima da
classe Negociacao.
Podemos agora fazer o processo inverso. Dado um XML que representa um bean da nossa classe Negociacao,
queremos popular esse bean. O cdigo novamente extremamente simples:
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
em um teste!). Os atributos no existentes ficaro como null no objeto, como o caso aqui do atributo data,
ausente no XML.
O XStream possui uma sobrecarga do mtodo fromXML que recebe um InputStream como argumento, outro
que recebe um Reader.

JAXB ou XStream?
A vantagem do JAXB ser uma especificao do Java, e a do XStream ser mais flexvel e permitir
trabalhar com classes imutveis.

Captulo 4 - Trabalhando com XML - XStream - Pgina 59

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

@XStreamAlias
Em vez de chamar stream.alias("negociacao", Negociacao.class);, podemos fazer essa
configurao 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 principal vantagem manter as configuraes centralizadas e, assim, se houver mais de uma parte
na sua aplicao responsvel por gerar XMLs de um mesmo modelo, no corremos o risco de ter
XMLs incompatveis.

4.5

Exerccios: Lendo o XML

1) 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 4 - Trabalhando com XML - Exerccios: Lendo o XML - Pgina 60

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

Coloque o nome de lib e clique OK:

2) Vamos pr o XStream no nosso projeto. V na pasta Caelum no seu Desktop e entre em 22. Localize o
arquivo do XStream:

Esse o mesmo arquivo que voc encontra para download no site do XStream, na verso minimal.
3) Copie o JAR do XStream 1.4 para a pasta lib/ do Argentum e, pelo Eclipse, entre na pasta lib e d refresh
(F5) nela.
Ento, selecione o JAR, clique com o boto direito e v em Build Path, Add to build path. A partir de
agora o Eclipse considerar as classes do XStream para esse nosso projeto.

Captulo 4 - Trabalhando com XML - Exerccios: Lendo o XML - Pgina 61

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

4) Vamos, finalmente, implementar a leitura do XML, delegando o trabalho para o XStream. Criamos a
classe LeitorXML dentro do pacote br.com.caelum.argentum.reader:
package br.com.caelum.argentum.reader;
// imports...
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);
}
}

5) Crie um teste de unidade LeitorXMLTest pelo Eclipse para testarmos a leitura do XML. Com o cursor na
classe LeitorXML, faa Ctrl + N e digite JUnit Test Case:
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():
@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>";

Captulo 4 - Trabalhando com XML - Exerccios: Lendo o XML - Pgina 62

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

6) Um teste de nada serve se no tiver suas verificaes. Assim, no esquea de verificar valores esperados
como:
a lista devolvida deve ter tamanho 1;
a negociao deve ter preo 43.5;
a quantidade deve ser 1000.
7) (Opcional) Crie mais alguns testes para casos excepcionais, como:
Zero negociaes;
Preo ou quantidade faltando;
Outras quantidades de negociaes (3, por exemplo).
8) (importante, conceitual) E o que falta agora? Testar nosso cdigo com um XML real?
muito comum sentirmos a vontade de fazer um teste maior": um teste que realmente abre um
InputStreamReader, passa o XML para o LeitorXML e depois chama a CandlestickFactory para quebrar as negociaes em candles.
Esse teste seria um chamado teste de integrao - no de unidade. Se crissemos esse teste e ele falhasse,
seria muito mais difcil detectar o ponto de falha!
Pensar em sempre testar as menores unidades possveis nos fora a pensar em classes menos dependentes
entre si, isto , com baixo acoplamento. Por exemplo: poderamos ter criado um LeitorXML que internamente 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).

4.6

Discusso em aula: Onde usar XML e o abuso do mesmo

Captulo 4 - Trabalhando com XML - Discusso em aula: Onde usar XML e o abuso do mesmo - Pgina 63

Captulo 5

Test Driven Design - TDD


Experincia sem teoria cegueira, mas teoria sem experincia mero jogo intelectual."
Immanuel Kant

5.1

Separando as candles

Agora que temos nosso leitor de XML que cria uma lista com as negociaes representadas no arquivo passado, um novo problema surge: a BOVESPA permite fazer download de um arquivo XML contendo todas
as negociaes de um ativo desde a data especificada. Entretanto, nossa CandlestickFactory est preparada
apenas para construir candles de uma data especfica.
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 armazenadas em uma nova lista para serem devolvidas.
Para fazer tal lgica, ento, precisamos:
passar por cada negociaes da lista original;
verificar 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 final, devolver a lista de candles;
O algoritmo no trivial e, ainda, ele depende de uma verificao que o Java no nos d prontamente: se
continua no mesmo dia. Isto , dado que eu sei qual a dataAtual, quero verificar se a negociao pertence a
esse mesmo dia.
Verificar uma negociao do mesmo dia que um Calendar qualquer exige algumas linhas de cdigo, mas
veja que, mesmo antes de implement-lo, j sabemos como o mtodo isMesmoDia dever se comportar em
diversas situaes:
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).

5.2

Vantagens do 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 influenciado pelo cdigo j feito - assim, ele tende a escrever testes
melhores, pensando no comportamento em vez da implementao.
Lembremos: os testes devem mostrar (e documentar) o comportamento do sistema, e no o que uma implementao faz.
Alm disso, nota-se que TDD traz baixo acoplamento, o que timo j que classes muito acopladas so
difceis de testar. Como criaremos os testes antes, desenvolveremos classes menos acopladas, isto , menos
dependentes de outras muitas, separando melhor as responsabilidades.
O TDD tambm uma espcie de guia: como o teste escrito antes, nenhum cdigo do sistema escrito
por acharmos que vamos precisar dele. Em sistemas sem testes, comum encontrarmos centenas de linhas
que jamais sero invocadas, simplesmente porque o desenvolvedor achou que algum um dia precisaria
daquele determinado mtodo.
Captulo 5 - Test Driven Design - TDD - Vantagens do TDD - Pgina 65

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 modificar seu sistema garantindo o funcionamento dele aps as mudanas quando no existem testes que garantam que seu sistema tenha o comportamento 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, podemos ver claramente as diversas vantagens dessa tcnica.

5.3

Exerccios: Identificando negociaes do mesmo dia

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.
1) Queremos ento, em nossa classe de factory, pegar uma srie de negociaes e transformar em uma lista
de candles. Para isso vamos precisar que uma negociao saiba identificar se do mesmo dia que a
dataAtual.
Para saber, conforme percorremos todas as negociaes, se a negociao atual ainda aconteceu na mesma
data que estamos procurando, vamos usar um mtodo na classe Negociacao que faz tal verificao.
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 + 1 em cima do erro e escolha Create method isMesmoDia.

E qual ser uma implementao interessante? Que tal simplificar usando o mtodo equals de Calendar?
Captulo 5 - Test Driven Design - TDD - Exerccios: Identificando negociaes do mesmo dia - Pgina 66

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

public boolean isMesmoDia(Calendar outraData) {


return this.data.equals(outraData);
}

Rode o teste! Passa?


2) Nosso teste passou de primeira! Vamos tentar mais algum teste? Vamos testar datas iguais em horas
diferentes, crie o mtodo a seguir na classe NegociacaoTest:
@Test
public void comHorariosDiferentesEhNoMesmoDia() {
// usando GregorianCalendar(ano, mes, dia, hora, minuto)
Calendar manha = new GregorianCalendar(2011, 10, 20, 8, 30);
Calendar tarde = new GregorianCalendar(2011, 10, 20, 15, 30);
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.DAY_OF_MONTH) == outraData.get(Calendar.DAY_OF_MONTH);
}

Altere o mtodo isMesmoDia na classe Negociacao e rode os testes anteriores. Passamos agora?
3) O prximo teste a implementarmos ser o que garante que para dia igual, mas ms diferente, a data no
a mesma. Quer dizer: no basta comparar o campo referente ao dia do ms, ainda necessrio que seja
o mesmo ms!
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.
4) Finalmente, o ltimo teste a implementarmos ser o que garante que para dia e meses iguais, mas anos
diferentes, a data no a mesma. Siga o mesmo procedimento para desenvolver com TDD:
Escreva o teste mesmoDiaEMesMasAnosDiferentesNaoSaoDoMesmoDia;
Rode e veja que falhou;
Implemente o necessrio para faz-lo passar.

Captulo 5 - Test Driven Design - TDD - Exerccios: Identificando negociaes do mesmo dia - Pgina 67

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

Feito esse processo, seu mtodo isMesmoDia na classe Negociacao deve ter ficado bem parecido com isso:
public boolean isMesmoDia(Calendar outraData) {
return
this.data.get(Calendar.DAY_OF_MONTH) == outraData.get(Calendar.DAY_OF_MONTH) &&
this.data.get(Calendar.MONTH) == outraData.get(Calendar.MONTH) &&
this.data.get(Calendar.YEAR) == outraData.get(Calendar.YEAR);
}

5.4

Exerccios: Separando os candles

1) 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

mtodo
CandlestickFactoryTest:

paraNegociacoesDeTresDiasDistintosGeraTresCandles

na

classe

@Test
public void paraNegociacoesDeTresDiasDistintosGeraTresCandles() {
Calendar hoje = Calendar.getInstance();
Negociacao
Negociacao
Negociacao
Negociacao

negociacao1
negociacao2
negociacao3
negociacao4

=
=
=
=

new
new
new
new

Negociacao(40.5,
Negociacao(45.0,
Negociacao(39.8,
Negociacao(42.3,

100,
100,
100,
100,

hoje);
hoje);
hoje);
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();

Captulo 5 - Test Driven Design - TDD - Exerccios: Separando os candles - Pgina 68

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

List<Candlestick> candles = fabrica.constroiCandles(negociacoes);


Assert.assertEquals(3, candles.size());
Assert.assertEquals(40.5, candles.get(0).getAbertura(), 0.00001);
Assert.assertEquals(42.3, candles.get(0).getFechamento(), 0.00001);
Assert.assertEquals(48.8, candles.get(1).getAbertura(), 0.00001);
Assert.assertEquals(49.3, candles.get(1).getFechamento(), 0.00001);
Assert.assertEquals(51.8, candles.get(2).getAbertura(), 0.00001);
Assert.assertEquals(52.3, candles.get(2).getFechamento(), 0.00001);
}

A chamada ao mtodo constroiCandles no compila pois o mtodo no existe ainda. Ctrl + 1 e Create
method.
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 fique 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);
Captulo 5 - Test Driven Design - TDD - Exerccios: Separando os candles - Pgina 69

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

return candles;
}

Rode o teste!

5.5

Exerccios opcionais

1) 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 errados. Apesar da especificao 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 crescente, lanamos uma exception, a IllegalStateException.
Crie o naoPermiteConstruirCandlesComNegociacoesForaDeOrdem e configure o teste para verificar 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, modificamos o cdigo adicionando as linhas em negrito ao mtodo constroiCandles:


for (Negociacao negociacao : todasNegociacoes) {
if (negociacao.getData().before(dataAtual)) {
Captulo 5 - Test Driven Design - TDD - Exerccios opcionais - Pgina 70

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

throw new IllegalStateException("negociaes em ordem errada");


}
// se no for mesmo dia, fecha candle e reinicia variveis
...

2) Vamos criar um gerador automtico de arquivos para testes da bolsa. Ele vai gerar 30 dias de candle e
cada candle pode ser composto de 0 a 19 negociaes. Esses preos podem variar.
public class GeradorAleatorioDeXML {
public static void main(String[] args) throws IOException {
Calendar data = Calendar.getInstance();
Random random = new Random(123);
List<Negociacao> negociacoes = new ArrayList<Negociacao>();
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));
}
Captulo 5 - Test Driven Design - TDD - Exerccios opcionais - Pgina 71

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

Se voc olhar o resultado do XML, ver que, por usarmos o mesmo objeto Calendar em vrios lugares, o
XStream coloca referncias no prprio XML evitando a cpia do mesmo dado. Mas talvez isso no seja
to interessante na prtica, pois mais comum na hora de integrar sistemas, passar um XML simples com
todos os dados.
A opo XStream.NO_REFERENCES serve para indicar ao XStream que no queremos que ele crie referncias
a tags que j foram serializadas iguaizinhas. Voc pode passar esse argumento para o mtodo setMode do
XStream. Faa o teste sem e com essa opo para entender a diferena.

Desafio - Ordene a lista on demand


1) Faa com que uma lista de Negociacao seja ordenvel pela data das negociaes.
Ento poderemos, logo no incio do mtodo, ordenar todas as negociaes com Collections.sort e no
precisamos mais verificar se os negociaes esto vindo em ordem crescente!
Perceba que mudamos uma regra de negcio, ento teremos de refletir isso no nosso teste unitrio que
estava com expected=IllegalStateException.class no caso de vir em ordem errada. O resultado agora
com essa modificao tem de dar o mesmo que com as datas crescentes.

Captulo 5 - Test Driven Design - TDD - Exerccios opcionais - Pgina 72

Captulo 6

Acessando um Web Service


Nenhum homem uma ilha isolada; cada homem uma partcula do continente, uma parte da terra
John Donne

6.1

Integrao entre sistemas

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.

6.2

Consumindo dados de um Web Service

Para consumir dados vindos de outra aplicao, a primeira coisa importante saber onde essa aplicao se
encontra. Em termos tcnicos, qual a URL desse web service. Em nosso projeto a URL especfica da aplicao
ser http://argentumws.caelum.com.br/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

6.3

Criando o cliente Java

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://argentumws.caelum.com.br/negociacoes");

Conhecendo a URL falta agora que uma requisio HTTP seja feita para ela. Faremos isso atravs do mtodo 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://argentumws.caelum.com.br/negociacoes");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();

Dessa conexo pediremos um InputStream que ser usado pelo nosso LeitorXML.
URL url = new URL("http://argentumws.caelum.com.br/negociacoes");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
InputStream content = connection.getInputStream();
List<Negociacao> negociacoes = new LeitorXML().carrega(content);
Captulo 6 - Acessando um Web Service - Criando o cliente Java - Pgina 74

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 encapsularmos 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://argentumws.caelum.com.br/negociacoes";
}

Por ltimo, e no menos importante, declararemos um mtodo que retorna uma lista de negociaes, justamente o que usaremos no projeto.
public class ClienteWebService {
private static final String URL_WEBSERVICE =
"http://argentumws.caelum.com.br/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 6 - Acessando um Web Service - Criando o cliente Java - Pgina 75

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 aprofundamento no curso FJ-31 | Curso Java EE avanado e Web Services.

HttpClient
Existe uma biblioteca capaz de lidar com dados de uma forma simples e mais especfica do que
utilizar diretamente a API do Java. Para trabalhar com o protocolo HTTP h a biblioteca HttpClient que faz parte do Apache Software Foundation:
http://hc.apache.org/httpcomponents-client-ga/index.html
Com ela ganhamos uma API que fornece toda funcionalidade do protocolo HTTP e poderamos 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 6 - Acessando um Web Service - Criando o cliente Java - Pgina 76

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

Web Service - SOAP, JSON e outros


Por definio um Web Service alguma lgica de negcio acessvel usando padres da Internet. O mais comum usar HTTP como protocolo de comunicao e XML para o formato que
apresenta os dados - justamente o que praticaremos aqui. Mas nada impede o uso de outros
formatos.
Uma tentativa de especificar mais ainda o XML dos Web Services so os padres SOAP e WSDL.
Junto com o protocolo HTTP, eles definem a base para comunicao de vrios servios no
mundo de aplicaes Enterprise. O SOAP e WSDL tentam esconder toda comunicao e gerao do XML, facilitando assim o uso para quem no conhece os padres Web. No treinamento
FJ-31 veremos os detalhes sobre publicao e a criao de clientes baseados no Web Services
SOAP/WSDL.
Outro formato bastante popular nos Web Services o JSON. JSON parecido com XML, mas
um pouco menos verboso e fcil de usar com JavaScript. JSON ganhou popularidade atravs das
requisies AJAX e conquistou o seu espao nos Web Services tambm. Alm de ser bastante
difundido no desenvolvimento mobile por ser mais leve no trfego via rede.

6.4

Exerccios: Nosso cliente Web Service

1) 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. Vamos criar tambm uma constante com a URL para onde ser feita a requisio.
public class ClienteWebService {
private static final String URL_WEBSERVICE =
"http://argentumws.caelum.com.br/negociacoes";
}

2) Agora vamos criar o mtodo getNegociacoes(), que retorna a nossa lista de negociaes:
public class ClienteWebService {
private static final String URL_WEBSERVICE =
"http://argentumws.caelum.com.br/negociacoes";
public List<Negociacao> getNegociacoes() {
HttpURLConnection connection = null;
URL url = new URL(URL_WEBSERVICE);

Captulo 6 - Acessando um Web Service - Exerccios: Nosso cliente Web Service - Pgina 77

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

connection = (HttpURLConnection)url.openConnection();
InputStream content = connection.getInputStream();
return new LeitorXML().carrega(content);
}
}

3) 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://argentumws.caelum.com.br/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();
}
}
}

6.5

Discusso em aula: Como testar o cliente do web service?

Captulo 6 - Acessando um Web Service - Discusso em aula: Como testar o cliente do web service? - Pgina 78

Captulo 7

Introduo ao JSF e Primefaces


Eu no temo computadores, eu temo a falta deles
Isaac Asimov
Durante muitos anos, os usurios se habituaram com aplicaes Desktop. Este tipo de aplicao instalada
no computador local e acessa diretamente um banco de dados ou gerenciador de arquivos. As tecnologias
tpicas para criar uma aplicao Desktop so Delphi, VB (Visual Basic) ou, no mundo Java, Swing.
Para o desenvolvedor, a aplicao Desktop construda com uma srie de componentes que a plataforma de
desenvolvimento oferece para cada sistema operacional. Esses componentes ricos e muitas vezes sofisticados
esto associados a eventos ou procedimentos que executam lgicas de negcio.
Problemas de validao de dados so indicados na prpria tela sem que qualquer informao do formulrio
seja perdida. De uma forma natural, esses componentes lembram-se dos dados do usurio, inclusive entre
telas e aes diferentes.
Nesse tipo de desenvolvimento so utilizados diversos componentes ricos, como por exemplo, calendrios,
menus diversos ou componentes drag and drop (arrastar e soltar). Eles ficam associados a eventos, ou aes,
e guardam automaticamente seu estado, j que mantm os valores digitados pelo usurio.

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

Esses componentes no esto, contudo, associados exclusivamente ao desenvolvimento de aplicaes Desktop. Podemos criar a mesma sensao confortvel para o cliente em uma aplicao web, tambm usando
componentes ricos e reaproveitveis.

7.1

Desenvolvimento desktop ou web?

Existem algumas desvantagens no desenvolvimento desktop. Como cada usurio tem uma cpia integral da
aplicao, qualquer alterao precisaria ser propagada para todas as outras mquinas. Estamos usando um
cliente gordo, isto , com muita responsabilidade no lado do cliente.
Note que, aqui, estamos chamando de cliente a aplicao que est rodando na mquina do usurio.
Para piorar, as regras de negcio rodam no computador do usurio. Isso faz com que seja muito mais difcil
depurar a aplicao, j que no costumamos ter acesso to fcil maquina onde a aplicao est instalada.
Em geral, enfrentamos problemas de manuteno e gerenciabilidade.

Captulo 7 - Introduo ao JSF e Primefaces - Desenvolvimento desktop ou web? - Pgina 80

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

O desenvolvimento Web e o protocolo HTTP


Para resolver problemas como esse, surgiram as aplicaes baseadas na web. Nessa abordagem h um servidor central onde a aplicao executada e processada e todos os usurios podem acess-la atravs de um
cliente simples e do protocolo HTTP.
Um navegador web, como Firefox ou Chrome, que far o papel da aplicao cliente, interpretando HTML,
CSS e JavaScript -- que so as tecnologias que ele entende.
Enquanto o usurio usa o sistema, o navegador envia requisies (requests) para o lado do servidor (server
side), que responde para o computador do cliente (client side). Em nenhum momento a aplicao est salva
no cliente: todas as regras da aplicao esto no lado do servidor. Por isso, essa abordagem tambm foi
chamada de cliente magro (thin client).

Isso facilita bastante a manuteno e a gerenciabilidade, pois temos um lugar central e acessvel onde a aplicao executada. Contudo, note que ser preciso conhecer HTML, CSS e JavaScript, para fazer a interface
com o usurio, e o protocolo HTTP para entender a comunicao pela web. E, mais importante ainda, no
h mais eventos, mas sim um modelo bem diferente orientado a requisies e respostas. Toda essa base
precisar ser conhecida pelo desenvolvedor.
Comparando as duas abordagens, podemos ver vantagens e desvantagens em ambas. No lado da aplicao
puramente Desktop, temos um estilo de desenvolvimento orientado a eventos, usando componentes ricos,
porm com problemas de manuteno e gerenciamento. Do outro lado, as aplicaes web so mais fceis
de gerenciar e manter, mas precisamos lidar com HTML, conhecer o protocolo HTTP e seguir o modelo
requisio/resposta.

Captulo 7 - Introduo ao JSF e Primefaces - Desenvolvimento desktop ou web? - Pgina 81

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

Mesclando desenvolvimento Desktop e Web


Em vez de desenvolver puramente para desktop, uma tendncia mesclar os dois estilos, aproveitando as vantagens de cada um. Seria um desenvolvimento Desktop para a web, tanto central quanto com componentes
ricos, aproveitando o melhor dos dois mundos e abstraindo o protocolo de comunicao. Essa justamente
a ideia dos frameworks web baseados em componentes.
No mundo Java h algumas opes como JavaServer Faces (JSF), Apache Wicket, Vaadin, Tapestry ou GWT
da Google. Todos eles so frameworks web baseados em componentes.

7.2

Caractersticas do JSF

JSF uma tecnologia que nos permite criar aplicaes Java para Web utilizando componentes visuais prprontos, de forma que o desenvolvedor no se preocupe com Javascript e HTML. Basta adicionarmos os
componentes (calendrios, tabelas, formulrios) e eles sero renderizados e exibidos em formato html.

Guarda o estado dos componentes


Alm disso o estado dos componentes sempre guardado automaticamente (como veremos mais frente),
criando a caracterstica Stateful. Isso nos permite, por exemplo, criar formulrios de vrias pginas e navegar
nos vrios passos dele com o estado das telas sendo mantidos.

Separa as camadas
Outra caracterstica marcante na arquitetura do JSF a separao que fazemos entre as camadas de apresentao e de aplicao. Pensando no modelo MVC, o JSF possui uma camada de visualizao bem separada do
conjunto de classes de modelo.

Especificao: vrias implementaes


O JSF ainda tem a vantagem de ser uma especificao do Java EE, isto , todo servidor de aplicaes Java tem
que vir com uma implementao dela e h diversas outras disponveis.
A implementao mais famosa do JSF e tambm a implementao de referncia, a Oracle Mojarra disponvel em http://javaserverfaces.java.net/. Outra implementao famosa a MyFaces da Apache Software
Foundation em http://myfaces.apache.org/.

Captulo 7 - Introduo ao JSF e Primefaces - Caractersticas do JSF - Pgina 82

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

Primeiros passos com JSF


Nosso projeto utilizar a implementao Mojarra do JSF. Ela j define o modelo de desenvolvimento e oferece
alguns componentes bem bsicos. Nada alm de inputs, botes e ComboBoxes simples.

No h componentes sofisticados dentro da especificao e isso proposital: uma especificao tem que ser
estvel e as possibilidades das interfaces com o usurio crescem muito rapidamente. A especificao trata do
que fundamental, mas outros projetos suprem o que falta.
Para atender a demanda dos desenvolvedores por componentes mais sofisticados, h vrias extenses do
JSF que seguem o mesmo ciclo e modelo da especificao. Exemplos dessas bibliotecas so PrimeFaces,
RichFaces e IceFaces. Todas elas definem componentes JSF que vo muito alm da especificao.

Cada biblioteca oferece ShowCases na web para mostrar seus componentes e suas funcionalidades. Voc
pode ver o showcase do PrimeFaces no endereo http://www.primefaces.org.
Captulo 7 - Introduo ao JSF e Primefaces - Caractersticas do JSF - Pgina 83

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

Na sua demo online, podemos ver uma lista de componentes disponveis, como inputs, painis, botes diversos, menus, grficos e componentes drag & drop, que vo muito alm das especificaes, ainda mantendo a
facilidade de uso:

Captulo 7 - Introduo ao JSF e Primefaces - Caractersticas do JSF - Pgina 84

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

Para a definio da interface do projeto Argentum usaremos Oracle Mojarra com PrimeFaces, uma combinao muito comum no mercado.

Preparao do ambiente
Nossa aplicao Argentum precisa de uma interface web. Para isso vamos preparar uma aplicao web comum
que roda dentro de um Servlet Container. Qualquer implementao de servlet container seria vlida e, no
curso, usaremos o Apache Tomcat 7. Uma outra boa opo seria o Jetty.

Configurao do controlador do JSF


O JSF segue o padro arquitetural MVC (Model-View-Controller) e faz o papel do Controller da aplicao. Para
comear a us-lo, preciso configurar a servlet do JSF no web.xml da aplicao. Esse Servlet responsvel
por receber as requisies e deleg-las ao JSF. Para configur-lo basta adicionar as seguintes configuraes
no web.xml:
<servlet>
<servlet-name>FacesServlet</servlet-name>
Captulo 7 - Introduo ao JSF e Primefaces - Caractersticas do JSF - Pgina 85

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>FacesServlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>

Ao usar o Eclipse com suporte a JSF 2 essa configurao no web.xml j feita automaticamente durante a
criao de um projeto.

Faces-config: o arquivo de configurao do mundo JSF


Alm disso, h um segundo XML que o arquivo de configurao relacionado com o mundo JSF, o
faces-config.xml.
Como o JSF na verso dois encoraja o uso de anotaes em vez de configuraes no XML, este arquivo tornase pouco usado. Ele era muito mais importante na primeira verso do JSF. Neste treinamento, deixaremos
ele 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.

7.3

Exerccios: Instalando o Tomcat e criando o projeto

1) Primeiramente, precisamos instalar o Tomcat. Usaremos a verso 7.x:


a) V no Desktop e entre na pasta Caelum e em seguida na pasta 22.
b) Copie o arquivo zip do TomCat e cole ele na sua pasta Home.
c) Clique com o boto direito e escolha Extract here.

Captulo 7 - Introduo ao JSF e Primefaces - Exerccios: Instalando o Tomcat e criando o projeto - Pgina 86

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

d) O Tomcat j est pronto para o uso!


2) O prximo passo criar o nosso projeto no Eclipse.
a) Crie um novo projeto web usando o ctrl + 3 Dynamic Web Project.
b) Em Project name coloque fj22-argentum-web.
c) Na seo Configuration clique em Modify para acrescentarmos suporte ao JSF.

d) Na tela que abre, marque o checkbox com JavaServer Faces 2.0 e clique d ok:

Captulo 7 - Introduo ao JSF e Primefaces - Exerccios: Instalando o Tomcat e criando o projeto - Pgina 87

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

e) De volta tela de criao do projeto, clique em Next. Nessa tela, faremos como no incio do curso: removeremos a source folder padro (src) e adicione as source folders src/main/java e src/test/java.

f) D Next mais duas vezes at chegar tela de JSF Capabilities. Nessa tela, escolha a opo Disable
Library Configuration para indicarmos para o Eclipse que ns mesmos copiaremos os JARs do JSF.
Ainda nessa tela, na parte URL Mapping Patterns, remova o mapeamento /faces/* e adicione um novo
mapeamento como *.xhtml

Captulo 7 - Introduo ao JSF e Primefaces - Exerccios: Instalando o Tomcat e criando o projeto - Pgina 88

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

g) Clique em Finish e o projeto est criado.


3) O prximo passo configurar o Tomcat no Eclipse, para que possamos control-lo mais facilmente.
a) Dentro do Eclipse, abra a view Servers. Para isso, pressione ctrl + 3, digite Servers e escolha a view. Ela
ser aberta na parte inferior do seu Eclipse.
b) Dentro da aba Servers clique com o boto direito do mouse e escolha New -> Server. Se no quiser
usar o mouse, voc pode fazer ctrl+3 New server.

c) Dentro da Janela New Server escolha Apache Tomcat v7.0 Server e clique em Next.

Captulo 7 - Introduo ao JSF e Primefaces - Exerccios: Instalando o Tomcat e criando o projeto - Pgina 89

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

d) O prximo passo dizermos ao Eclipse em qual diretrio instalamos o Tomcat. Clique no boto
Browse... e escolha a pasta na qual voc descompactou o Tomcat.

e) Clique em Next e, na prxima tela, selecione o projeto fj22-argentum-web no box Available (da esquerda), pressione o boto Add > (mover para o box Configured da direita) e depois Finish.
Captulo 7 - Introduo ao JSF e Primefaces - Exerccios: Instalando o Tomcat e criando o projeto - Pgina 90

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

f) Clique em Finish.
4) Por fim, precisamos importar do projeto anterior as classes como Negociacao ou Candlestick. J o temos pronto na pasta /caelum/cursos/22/, com o nome de modelo-argentum.zip. Precisamos apenas
import-lo:
Para import-lo, use ctrl + 3 Archive File e escolha a opo Import (Archive file).
Em Browse..., selecione o nosso arquivo modelo-argentum.zip e finalize-o.

Note que, com esse import, trouxemos tambm os jars da implementao Mojarra do JSF e do Primefaces, que usaremos daqui pra frente.

Captulo 7 - Introduo ao JSF e Primefaces - Exerccios: Instalando o Tomcat e criando o projeto - Pgina 91

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

Para casa...
Se voc est fazendo esse exerccio em casa, certifique-se que seu projeto anterior est funcionando corretamente e simplesmente copie os pacotes dele para o novo.
No esquea de copiar tambm o jar do XStream para a pasta WebContent/WEB-INF/lib/.
Alm disso, no zip da aula ainda h os jars do JSF e do PrimeFaces, que usaremos a seguir. Nesta
verso da apostila estamos usando as verses 2.x.x e 3.5.x, respectivamente. Links para o download:
JSF: https://javaserverfaces.java.net/download.html
Primefaces: http://primefaces.org/downloads.html

5) Nossas classes de teste (src/test/java) ainda apresentam problemas relacionados ao JUnit. Falta adicion-lo
ao Build Path.
Abra a classe CandlestickFactoryTest e d ctrl + 1 na anotao @Test. Escolha a opo Add JUnit 4 library
to the build path.

6) Finalmente, para evitar confuses mais para a frente, feche o projeto que fizemos nos outros dias de curso.
Clique com o boto direito no fj22-argentum-base e escolha a opo Close project

7.4

A primeira pgina com JSF

Como configuramos, na criao do projeto, que o JSF ser responsvel por responder s requisies com
extenso .xhtml. Dessa forma, tabalharemos com arquivos xhtml no restante do curso.
Captulo 7 - Introduo ao JSF e Primefaces - A primeira pgina com JSF - Pgina 92

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

Vale relembrar uma diferena fundamental entre as duas formas de desenvolvimento para a web. A abordagem action based, como no SpringMVC e no VRaptor, focam seu funcionamento nas classes que contm as
lgicas. A view meramente uma camada de apresentao do que foi processado no modelo.
Enquanto isso, o pensamento component based adotado pelo JSF leva a view como a pea mais importante
-- a partir das necessidades apontadas pelos componentes da view que o modelo chamado e populado
com dados.
As tags que representam os componentes do JSF esto em duas taglibs principais (bibliotecas de tags): a core
e a html.
A taglib html contm os componentes necessrios para montarmos nossa tela gerando o HTML adequado.
J a core possui diversos componentes no visuais, como tratadores de eventos ou validadores. Por ora,
usaremos apenas os componentes da h:html

Importando as tags em nossa pgina


Diferente da forma importao de taglibs em JSPs que vimos no curso de Java para a web (FJ-21), para importar as tags no JSF basta declararmos seus namespaces no arquivo .xhtml. 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:h="http://java.sun.com/jsf/html">
<!-- aqui usaremos as tags do JSF -->
</html>

Definindo a interface da aplicao


Como qualquer outro aprendizado de tecnologia, vamos comear a explorar o JSF criando nossa primeira
tela com uma mensagem de boas vindas para o usurio.
Como todo arquivo HTML, todo o cabealho deve estar dentro da tag head e o que ser renderizado no
navegador deve ficar dentro da tag body. Uma pgina padro para ns seria algo como:
<html ...>
<head>
<!-- cabealho aqui -->
</head>
<body>
<!-- informaes a serem mostradas -->
</body>
</html>
Captulo 7 - Introduo ao JSF e Primefaces - A primeira pgina com JSF - Pgina 93

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

Quando estamos lidando com o JSF, no entanto, precisamos nos lembrar de utilizar preferencialmente as
tags do prprio framework, j que, medida que utilizarmos componentes mais avanados, o JSF precisar gerenciar os prprios body e head para, por exemplo, adicionar CSS e javascript que um componente
requisitar.
Assim, usando JSF preferiremos utilizar as tags estruturais do HTML que vm da taglib http://java.sun.com/
jsf/html, nosso html vai ficar mais parecido com esse:
<html ...>
<h:head>
<!-- cabealho aqui -->
</h:head>
<h:body>
<!-- informaes a serem mostradas -->
</h:body>
</html>

Mostrando informaes com h:outputText


Como queremos mostrar uma saudao para o visitante da nossa pgina, podemos usar a tag h:outputText.
atravs do seu atributo value que definimos o texto que ser apresentado na pgina.
Juntando tudo, nosso primeiro exemplo uma tela simples com um 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: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>

7.5

Interagindo com o modelo: Managed Beans

O h:outputText uma tag com um propsito aparentemente muito bobo e, no exemplo acima, exatamente
equivalente a simplesmente escrevermos Ol JSF! diretamente. E, de fato, para textos fixos, no h problema
em escrev-lo diretamente!
Contudo, se um pedao de texto tiver que interagir com o modelo, uma lgica ou mesmo com outros componentes visuais, ser necessrio que ele tambm esteja guardado em um componente.
Captulo 7 - Introduo ao JSF e Primefaces - Interagindo com o modelo: Managed Beans - Pgina 94

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

Exemplos dessas interaes, no caso do h:outputText: mostrar informaes vindas de um banco de dados,
informaes do sistema, horrio de acesso, etc.
Para mostrar tais informaes, precisaremos executar um cdigo Java e certamente no faremos isso na
camada de visualizao: esse cdigo ficar separado da view, em uma classe de modelo. Essas classes de
modelo que interagem com os componentes do JSF so os Managed Beans.
Estes, so apenas classezinhas simples que com as quais o JSF consegue interagir atravs do acesso a seus
mtodos. Nada mais so do que POJOs anotados com @ManagedBean.

POJO (Plain Old Java Object)


POJO um termo criado por Martin Fowler, Rebecca Parsons e Josh Mackenzie que serve para
definir um objeto simples. Segundo eles, o termo foi criado pois ningum usaria objetos simples
nos seus projetos pois no existia um nome extravagante para ele.
Se quisermos, por exemplo, mostrar quando foi o acesso do usurio a essa pgina, podemos criar a seguinte
classe:
@ManagedBean
public class OlaMundoBean {
public String getHorario() {
SimpleDateFormat sdf = new SimpleDateFormat("hh:mm:ss");
return "Atualizado em " + sdf.format(new Date());
}
}

E, bem semelhantemente forma padro nas JSPs vistas no treinamento de Java para a Web, acessaremos o
getter atravs da Expression Language. Existe apenas uma pequena diferena: para chamar os mtodos no
JSF, em vez do cifro ($), usaremos a cerquilha (#).
<h:outputText value="#{olaMundoBean.horario}" />

Ao fazer colocar o cdigo acima, estamos dizendo que h uma classe gerenciada pelo JSF chamada OlaMundoBean que tem um mtodo getHorario -- e que o retorno desse mtodo ser mostrado na pgina. uma
forma extremamente simples e elegante de ligar a view a mtodos do model.

7.6

Recebendo informaes do usurio

Agora que j sabemos conectar a pgina camada de modelo, fica fcil obter dados do usurio! Por nossa
vivncia com aplicaes web, at mesmo como usurios, sabemos que a forma mais comum de trazer tais
dados para dentro da aplicao atravs de formulrios.
Captulo 7 - Introduo ao JSF e Primefaces - Recebendo informaes do usurio - Pgina 95

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

A boa notcia que no JSF no ser muito diferente! Se para mostrar dados na pgina usamos a tag
h:outputText, para trazer dados do usurio para dentro da aplicao, usaremos a tag h:inputText. Ela
far a ligao entre o atributo do seu bean e o valor digitado no campo.
Note que a ideia a mesma de antes: como o JSF precisar interagir com os dados desse componente, no
podemos usar a tag HTML que faria o mesmo trabalho. Em vez disso, usaremos a taglib de HTML provida
pelo prprio JSF, indicando como a informao digitada ser guardada no bean.
<h:outputLabel value="Digite seu nome:"/>
<h:inputText value="#{olaMundoBean.nome}"/>

Apenas com esse cdigo, j podemos ver o texto Digite seu nome e o campo de texto onde o usurio digitar.
Sabemos, no entanto, que no faz sentido ter apenas um campo de texto! preciso ter tambm um boto
para o usurio confirmar que acabou de digitar o nome e um formulrio para agrupar todas essas tags.

Boto e o formulrio em JSF


Esse um pequeno ponto de divergncia entre o HTML puro e o JSF. Em um simples formulrio HTML,
configuramos a action dele na prpria tag form e o papel do boto apenas o de mandar executar a ao j
configurada.
Para formulrios extremamente simples, isso o bastante. Mas quando queremos colocar dois botes com
aes diferentes dentro de um mesmo formulrio, temos que recorrer a um JavaScript que far a chamada
correta.
Como dito antes, no entanto, o JSF tem a proposta de abstrair todo o protocolo HTTP, o JavaScript e o CSS.
Para ter uma estrutura em que o formulrio marcado apenas como um agregador de campos e cada um
dos botes internos pode ter funes diferentes, a estratgia do JSF foi a de deixar seu form como uma tag
simples e adicionar a configurao da ao ao prprio boto.
<h:form>
<h:outputLabel for="nome" value="Digite seu nome:"/>
<h:inputText id="nome" value="#{olaMundoBean.nome}"/>
<h:commandButton value="Ok" action="#{olaMundoBean.digaOi}"/>
</h:form>

Quando o usurio clica no boto Ok, o JSF chama o setter do atributo nome do OlaMundoBean e, logo em
seguida, chama o mtodo digaOi. Repare que esta ordem importante: o mtodo provavelmente depender
dos dados inseridos pelo usurio.
Note, tambm, que teremos um novo mtodo no managed bean chamado digaOi. Os botes sempre esto
atrelados a mtodos porque, na maior parte dos casos, realmente queremos executar alguma ao alm da
chamada do setter. Essa ao pode ser a de disparar um processo interno, salvar no banco ou qualquer outra
necessidade.
Captulo 7 - Introduo ao JSF e Primefaces - Recebendo informaes do usurio - Pgina 96

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

O que fazer enquanto no ainda houver informao?


Sabendo que, antes de chamar o mtodo correspondente ao do boto, o JSF preenche os
atributos atravs dos setters, sabemos que teremos a informao a ser mostrada para o usurio.
No entanto, muitas vezes no gostaramos de mostrar um campo enquanto ele no estiver preenchido e, felizmente, o JSF tem uma forma bastante simples de s mostrar um h:outputText
na tela apenas se a informao estiver preenchida! Basta usar o atributo rendered:
<h:outputText value="Oi #{olaMundoBean.nome}"
rendered="#{not empty olaMundoBean.nome}"/>

7.7

Exerccios: Os primeiros componentes JSF

1) Use ctrl + N HTML para criar o arquivo olaMundo.xhtml na pasta WebContent da sua aplicao. Escolha
Next e, na prxima tela, escolha o template xhtml 1.0 transitional, usualmente a ltima opo da lista:

Selecione a mesma opo da imagem acima e pressione Finish.


Implemente nosso primeiro cdigo JSF com apenas uma sada de texto:

Captulo 7 - Introduo ao JSF e Primefaces - Exerccios: Os primeiros componentes JSF - Pgina 97

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

<!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:h="http://java.sun.com/jsf/html">
<h:head>
<title>Argentum</title>
</h:head>
<h:body>
<h:outputText value="Ola Mundo" />
</h:body>
</html>

2) Inicie o Tomcat e acesse a URL: http://localhost:8080/fj22-argentum-web/olaMundo.xhtml


3) Verifique o cdigo fonte gerado pela pgina. Repare que ele no nada mais que simples HTML. Para
isso, na maior parte dos navegadores, use ctrl + U.
Repare no uso das tags <h:head>, <h:body> e <h:outputText>: elas no aparecem no html gerado! Sua
funo apenas indicar para o JSF como gerar o cdigo HTML necessrio para o exemplo funcionar.
4) Alm de usar mensagens fixas, poderamos fazer com que a mensagem seja devolvida de uma classe
responsvel por prover objetos para uma view: um dos chamados ManagedBeans. Vamos comear criando
essa classe contendo apenas a mensagem inicial.
Crie uma classe chamada OlaMundoBean, com apenas o atributo mensagem j inicializada, seu getter e no
esquea de anotar a classe com @ManagedBean
@ManagedBean
public class OlaMundoBean {
private String mensagem = "Quem voc?";
public String getMensagem() {
return mensagem;
}
}

5) Alteremos o arquivo xhtml, ento, para que ele use a mensagem Quem voc? que escrevemos hard-coded
na classe OlaMundoBean. Usaremos a Expression Language especfica do JSF para isso, que capaz de pegar
informaes de qualquer classe configurada como um ManagedBean.
Basta alterar o value da tag h:outputText:
...
<h:body>
<h:outputText value="#{olaMundoBean.mensagem}" />
</h:body>
Captulo 7 - Introduo ao JSF e Primefaces - Exerccios: Os primeiros componentes JSF - Pgina 98

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

6) Agora, se quisermos pegar a resposta do usurio e cumpriment-lo propriamente, podemos adicionar


nossa pgina um campo de texto para que o usurio digite seu nome. Ento, trocaremos a mensagem
cumprimentando ele. Comecemos pelas alteraes no olaMundo.xhtml, adicionando um h:inputText e
um boto para o usurio enviar seu nome, como abaixo.
Ateno! No esquea da tag h:form em volta do formulrio. Lembre-se que, sem ela, os botes no
funcionam.
...
<h:body>
<h:form>
<h:outputText value="#{olaMundoBean.mensagem}" /><br />
<h:inputText value="#{olaMundoBean.nome}" />
<h:commandButton action="#{olaMundoBean.nomeFoiDigitado}"
value="Ok"/>
</h:form>
</h:body>

7) Essa alterao, no entanto, no suficiente. Se voc rodar o servidor agora, notar que a pgina, que
antes funcionava, agora lana uma ServletException informando que Property nome not found on type
br.com.caelum.argentum.bean.OlaMundoBean.
Isto , falta adicionarmos o atributo nome e seu getter pgina, como fizemos com a mensagem, no outro
exerccio. Adicione classe OlaMundoBean o atributo e seu getter.
@ManagedBean
public class OlaMundoBean {
...
private String nome;
public String getNome() {
return nome;
}
...
}

8) Agora sim podemos ver a mensagem, o campo de texto e o boto. Contudo, ao apertar o boto, levamos
uma javax.el.PropertyNotFoundException informando que nome um atributo no altervel.
Faltou adicionarmos o setter do atributo OlaMundoBean, para que o JSF possa preench-lo! Alm disso,
o boto chamar o mtodo nomeFoiDigitado, que tambm no existe ainda.
Complete a classe com o setter faltante e o mtodo nomeFoiDigitado, reinicie o servidor e teste!
@ManagedBean
public class OlaMundoBean {
// ...tudo o que j existia aqui

Captulo 7 - Introduo ao JSF e Primefaces - Exerccios: Os primeiros componentes JSF - Pgina 99

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

public void setNome(String nome) {


this.nome = nome;
}
public void nomeFoiDigitado() {
System.out.println("\nChamou o boto");
}
}

9) (Opcional) Para entender melhor o ciclo de execuo de cada chamada ao JSF, adicione
System.out.println("nome do mtodo") a cada um dos mtodos da sua aplicao e veja a ordem das
chamadas pelo console do Eclipse.

7.8

A lista de negociaes

Agora que j aprendemos o bsico do JSF, nosso objetivo listar em uma pgina as negociaes do web service
que o Argentum consome. Nessa listagem, queremos mostrar as informaes das negociaes carregadas -isto , queremos uma forma de mostrar preo, quantidade e data de cada negociao. E a forma mais natural
de apresentar dados desse tipo , certamente, uma tabela.
At poderamos usar a tabela que vem na taglib padro do JSF, mas ela bastante limitada e no tem prdefinies de estilo. Isto , usando a taglib padro, teremos sim uma tabela no HTML, mas ela ser mostrada
da forma mais feia e simples possvel.
J falamos, contudo, que a proposta do JSF abstrair toda a complexidade relativa web -- e isso inclui CSS,
formataes, JavaScript e tudo o mais. Ento, em apoio s tags bsicas, algumas bibliotecas mais sofisticadas
surgiram. As mais conhecidas delas so PrimeFaces, RichFaces e IceFaces.
Taglibs como essas oferecem um visual mais bacana j pr-pronto e, tambm, diversas outras facilidades. Por
exemplo, uma tabela que utilize as tags do Primefaces j vem com um estilo bonito, possibilidade de colocar
cabealhos nas colunas e at recursos mais avanados como paginao dos registros.
O componente responsvel por produzir uma tabela baseada em um modelo se chama dataTable. Ele funciona de forma bem semelhante ao for do Java 5 ou o forEach da JSTL: itera em uma lista de elementos
atribuindo cada item na varivel definida.
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>Argentum</title>
</h:head>
<h:body>
<p:dataTable var="negociacao" value="#{argentumBean.negociacoes}">

Captulo 7 - Introduo ao JSF e Primefaces - A lista de negociaes - Pgina 100

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

</p:dataTable>
</h:body>
</html>

O cdigo acima chamar o mtodo getNegociacoes da classe ArgentumBean e iterar pela lista devolvida
atribuindo o objeto varivel negociacao. Ento, para cada coluna que quisermos mostrar, ser necessrio
apenas manipular a negociao do momento.
E, intuitivamente o bastante, cada coluna da tabela ser representada pela tag p:column. Para mostrar o
valor, voc pode usar a tag que j vimos antes, o h:outputText. Note que as tags do Primefaces se integram
perfeitamente com as bsicas do JSF.
<p:dataTable var="negociacao" value="#{argentumBean.negociacoes}">
<p:column headerText="Preo">
<h:outputText value="#{negociacao.preco}"/>
</p:column>
... outras colunas
</p:dataTable>

Falta ainda implementar a classe que cuidar de devolver essa lista de negociaes. O cdigo acima sugere
que tenhamos uma classe chamada ArgentumBean, gerenciada pelo JSF, que tenha um getter de negociaes
que pode, por exemplo, trazer essa lista direto do ClienteWebService que fizemos anteriormente:
@ManagedBean
public class ArgentumBean {
public List<Negociacao> getNegociacoes() {
return new ClienteWebService().getNegociacoes();
}
}

Da forma acima, o exemplo j funciona e voc ver a lista na pgina. No entanto, nesse exemplo simples o JSF
chamar o mtodo getNegociacoes duas vezes durante uma mesma requisio. Isso no seria um problema
se ele fosse um getter padro, que devolve uma referncia local, mas note como nosso getNegociacoes vai
buscar a lista diretamente no web service. Isso faz com que, para construir uma simples pgina, tenhamos
que esperar a resposta do servio... duas vezes!
Esse comportamento no interessante. Ns gostaramos que o Argentum batesse no servio em busca
dos dados apenas uma vez por requisio, e no a cada vez que o JSF chame o getter. Isso significa que o
acesso ao servio no pode estar diretamente no mtodo getNegociacoes, que deve apenas devolver a lista
pr-carregada.
No JSF, o comportamento padro diz que um objeto do ManagedBean dura por uma requisio. Em outras
palavras, o escopo padro dos beans no JSF o de requisio. Isso significa que um novo ArgentumBean
Captulo 7 - Introduo ao JSF e Primefaces - A lista de negociaes - Pgina 101

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

ser criado a cada vez que um usurio chamar a pgina da listagem. E, para cada chamada a essa pgina,
precisamos buscar a lista de negociaes no servio apenas uma vez. A resposta para esse problema, ento,
bastante simples e apareceu logo no incio do aprendizado do Java orientado a objetos.
Basta colocar a chamada do web service naquele bloco de cdigo que chamado apenas na criao do objeto,
isto , no construtor. Ao armazenar a listagem em um atributo, o getter de negociaes passa a simplesmente
devolver a referncia, evitando as mltiplas chamadas a cada requisio.
@ManagedBean
public class ArgentumBean {
private List<Negociacao> negociacoes;
public ArgentumBean() {
ClienteWebService cliente = new ClienteWebService();
this.negociacoes = cliente.getNegociacoes();
}
public List<Negociacao> getNegociacoes() {
return this.negociacoes;
}
}

Juntando as informaes dessa seo, j conseguimos montar a listagem de negociaes com os dados vindos
do web service. E o processo ser muito frequentemente o mesmo para as diversas outras telas: criamos a
pgina usando as tags do Primefaces em complemento s bsicas do JSF, implementamos a classe que cuidar
da lgica por trs da tela e a anotamos com @ManagedBean.

7.9

Formatao de Data com JSF

A tabela j funcional, mas com a data mal formatada. O componente no sabe como gostaramos de formatar a data e chama por de baixo dos planos o mtodo toString da data para receber uma apresentao
como String.

A forma clssica de resolver esse problema seria atravs de um getter que traria a data formatada por um
SimpleDateFormat. Mas, assim como a JSTL vista no curso de Java para a Web, o JSF tambm tem uma tag
Captulo 7 - Introduo ao JSF e Primefaces - Formatao de Data com JSF - Pgina 102

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

para formatar valores, nmeros e, claro, datas. Essas tags e muitas outras, so parte da biblioteca fundamental
de tags lgicas do JSF e, para us-las, ser necessrio importar tal taglib.
Assim como as bibliotecas de tags de HTML e do Primefaces, para utilizar essas ser necessrio declar-las
no namespace da sua pgina.
Da, podemos facilmente mudar a forma padro de exibio usando o componente de formatao
f:convertDateTime que define um pattern para a data. importante lembrar que, internamente, o
f:convertDateTime acaba fazendo uma chamada ao SimpleDateFormat e, assim, s podemos formatar objetos do tipo java.util.Date com ele. Por essa razo, chamaremos o mtodo getTime que devolve a representao em Date do Calendar em questo. Mais uma vez podemos omitir a palavra get com expression
language. Segue a tabela completa:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:body>
<p:dataTable var="negociacao" value="#{argentumBean.negociacoes}">
... outras colunas, e ento:
<p:column headerText="Data">
<h:outputText value="#{negociacao.data.time}">
<f:convertDateTime pattern="dd/MM/yyyy"/>
</h:outputText>
</p:column>
</p:dataTable>
</h:body>
</html>

7.10

Exerccios: p:dataTable para listar as Negociaes do


Web Service

1) Use ctrl + N HTML para criar um novo arquivo na pasta WebContent chamado index.xhtml. Como j
fizemos antes, clique em Next e, na tela seguinte, escolha o template xhtml 1.0 transitional.
O Eclipse vai gerar um arquivo com um pouco de informaes a mais, mas ainda muito parecido com o
seguinte, onde mudamos o title:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Argentum Web</title>
</head>
Captulo 7 - Introduo ao JSF e Primefaces - Exerccios: p:dataTable para listar as Negociaes do Web Service - Pgina 103

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

<body>
</body>
</html>

2) Como vamos usar o JSF nesse arquivo e j temos at mesmo o JAR primefaces-3.x.jar adicionado ao projeto (veja em WebContent/WEB-INF/lib) basta declarar os namespaces das taglibs do JSF e do Primefaces,
que usaremos no exerccio.
Alm disso, para que os componentes consigam incluir seu CSS nossa pgina, altere as tags head e body
de forma a usar suas verses gerenciadas pelo JSF:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>Argentum Web</title>
</h:head>
<h:body>
</h:body>
</html>

3) Agora, dentro do h:body, vamos comear a montar nossa tabela de negociaes. O componente que
usaremos para isso o p:datatable, do Primefaces. Ele precisar da lista de negociaes e, assim como
um forEach, uma varivel para que cada coluna seja preenchida.
<p:dataTable var="negociacao" value="#{argentumBean.negociacoes}">
</p:dataTable>

4) Esse cdigo acima diz que o componente dataTable do Primefaces chamar o mtodo getNegociacoes()
da classe ArgentumBean e, para cada linha da tabela, disponibilizar a negociao da vez na varivel
negociacao.
O problema que o managed bean ArgentumBean ainda no existe e, claro, nem o mtodo
getNegociacoes() dela. E como cada vez que a pgina index.xhtml for requisitada ela far algumas
chamadas ao getNegociacoes, faremos a chamada ao webservice no construtor e, a cada chamada ao
getter, apenas devolveremos a referncia mesma lista.
a) Crie a classe ArgentumBean com ctrl + N Class, no pacote br.com.caelum.argentum.bean e anote ela
com @ManagedBean.
@ManagedBean
public class ArgentumBean {
}
Captulo 7 - Introduo ao JSF e Primefaces - Exerccios: p:dataTable para listar as Negociaes do Web Service - Pgina 104

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

b) Adicione o construtor que faa a chamada ao webservice atravs do ClienteWebservice, guarde a lista
em um atributo e crie o getter que o componente chamar.
@ManagedBean
public class ArgentumBean {
private List<Negociacao> negociacoes;
public ArgentumBean() {
negociacoes = new ClienteWebService().getNegociacoes();
}
public List<Negociacao> getNegociacoes() {
return negociacoes;
}
}

5) Agora, nossa pgina j no d erro, mas nada mostrado na tela, quando a acessamos. Falta indicarmos
quais colunas queremos na nossa tabela -- no nosso caso: preo, quantidade, volume e data. Em cada
coluna, adicionaremos um ttulo e cada uma delas tambm mostrar o valor de texto.
Para criar a coluna com o ttulo, usaremos o componente p:column e, como j fizemos antes, para mostrar
o valor necessrio, usaremos a h:outputText.
<p:dataTable var="negociacao" value="#{argentumBean.negociacoes}">
<p:column headerText="Preo">
<h:outputText value="#{negociacao.preco}"/>
</p:column>
<p:column headerText="Quantidade">
<h:outputText value="#{negociacao.quantidade}"/>
</p:column>
<p:column headerText="Volume">
<h:outputText value="#{negociacao.volume}"/>
</p:column>
<p:column headerText="Data">
<h:outputText value="#{negociacao.data}"/>
</p:column>
</p:dataTable>

6) Reinicie o Tomcat e acesse em seu navegador o endereo http://localhost:8080/fj22-argentum-web/index.


xhtml . O resultado deve ser algo parecido com:

Captulo 7 - Introduo ao JSF e Primefaces - Exerccios: p:dataTable para listar as Negociaes do Web Service - Pgina 105

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

7) As informaes de preo, quantidade e volume esto legveis, mas a data das negociaes est mostrando
um monte de informaes que no nos interessam. Na verdades, o que precisamos na coluna data de
informaes de dia, ms, ano e, no mximo, horrio de cada movimentao.
Adicione a tag f:convertDateTime coluna da data. Essa tag modificar o comportamento da
h:outputText para mostr-lo formatado de acordo com o padro passado. Note que a tag h:outputText
passar a ser fechada depois da formatao da data:
...
<p:column headerText="Data">
<h:outputText value="#{negociacao.data.time}">
<f:convertDateTime pattern="dd/MM/yyyy"/>
</h:outputText>
</p:column>
...

7.11

Para saber mais: paginao e ordenao

O componente p:dataTable sabe listar items, mas no pra por a. Ele j vem com vrias outras funcionalidades frequentemente necessrias em tabelas j prontas e fceis de usar.

Muitos dados
Por exemplo, quando um programa traz uma quantidade muito grande de dados, isso pode causar uma
pgina pesada demais para o usurio que provavelmente nem olhar com ateno todos esses dados.
Uma soluo clssica para resultados demais mostr-los aos poucos, apenas conforme o usurio indicar
que quer ver os prximos resultados. Estamos, claro, falando da paginao dos resultados e o componente
de tabelas do Primefaces j a disponibiliza!
Para habilitar a paginao automtica, basta adicionar o atributo paginator="true" sua p:dataTable e
definir a quantidade de linhas por pgina pelo atributo rows. A definio da tabela de negociaes para
paginao de 15 em 15 resultados ficar assim:
<p:dataTable var="negociacao" value="#{argentumBean.negociacoes}"
paginator="true" rows="15">
Captulo 7 - Introduo ao JSF e Primefaces - Para saber mais: paginao e ordenao - Pgina 106

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

<!-- colunas omitidas -->


</p:dataTable>

Essa pequena mudana j traz uma visualizao mais legal para o usurio, mas estamos causando um problema silencioso no servidor. A cada vez que voc chama uma pgina de resultados, a cada requisio, o
ArgentumBean recriado e perdemos a lista anterior. Assim, na criao da nova instncia de ArgentumBean,
seu construtor chamado e acessamos novamente o webservice.
Como recebemos a lista completa do webservice, podamos aproveitar a mesma lista para todas as pginas
de resultado e, felizmente, isso tambm bastante simples.
O comportamento padro de um ManagedBean durar apenas uma requisio. Em outras palavras, o escopo
padro de um ManagedBean de request. Com apenas uma anotao podemos alterar essa durao. Os trs
principais escopos do JSF so:
RequestScoped: o escopo padro. A cada requisio um novo objeto do bean ser criado;
ViewScoped: escopo da pgina. Enquanto o usurio estiver na mesma pgina, o bean mantido. Ele
s recriado quando acontece uma navegao em s, isto , um boto abre uma pgina diferente ou
ainda quando acessamos novamente a pgina atual.
SessionScoped: escopo de sesso. Enquanto a sesso com o servidor no expirar, o mesmo objeto do
ArgentumBean atender o mesmo cliente. Esse escopo bastante usado, por exemplo, para manter o
usurio logado em aplicaes.
No nosso caso, o escopo da pgina resolve plenamente o problema: enquanto o usurio no recarregar a
pgina usaremos a mesma listagem. Para utiliz-lo, basta adicionar ao bean a anotao @ViewScoped. No
exemplo do Argentum:
@ManagedBean
@ViewScoped
public class ArgentumBean {
...

Tirando informaes mais facilmente


Outra situao clssica que aparece quando lidamos com diversos dados precisarmos v-los de diferentes
formas em situaes diversas.
Considere um sistema que apresenta uma tabela de contatos. Se quisermos encontrar um contato especfico
nela, melhor que ela esteja ordenada pelo nome. Mas caso precisemos pegar os contatos de todas as pessoas
de uma regio, melhor que a tabela esteja ordenada, por exemplo, pelo DDD.
Essa ideia de ordenao extremamente til e muito presente em aplicaes. Como tal, essa funcionalidade tambm est disponvel para tabelas do Primefaces. Apenas, como podemos tornar diversar colunas
ordenveis, essa configurao fica na tag da coluna.
Captulo 7 - Introduo ao JSF e Primefaces - Para saber mais: paginao e ordenao - Pgina 107

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

Para tornar uma coluna ordenvel, preciso adicionar um simples atributo sortBy tag h:column correspondente. Esse atributo torna o cabealho dessa coluna em um elemento clicvel e, quando clicarmos nele,
chamar a ordenao.
Contudo, exatamente pela presena de elementos clicveis, ser necessrio colocar a tabela dentro de uma
estrutura que comporte botes em HTML: um formulrio. E, como quem configurar o que cada clique vai
disparar o JSF, ser necessrio usar o formulrio da taglib de HTML dele. Resumidamente, precisamos
colocar a tabela inteira dentro do componente h:form.
Se quisssemos tornar ordenveis as colunas da tabela de negociaes, o resultado final seria algo como:
<h:form id="listaNegociacao">
<p:dataTable var="negociacao" value="#{argentumBean.negociacoes}">
<p:column sortBy="#{negociacao.preco}" headerText="Preo" >
<h:outputText value="#{negociacao.preco}" />
</p:column>
<!-- outras colunas omitidas -->
</p:dataTable>
<h:form>

Se permitirmos ordenar por qualquer coluna do modelo Negociacao, teremos um resultado bem atraente:

Note que no foi necessrio adicionar cdigo algum classe ArgentumBean! Note tambm que at possvel
usar ambas as funcionalidades na mesma tabela. E essas so apenas algumas das muitas facilidades que o
p:dataTable oferece. Vale a pena verificar o showcase e documentao no site do Primefaces.

7.12

Exerccio opcional: adicione paginao e ordenao


tabela

1) Vamos colocar paginao na tabela. Adicione os atributos paginator="true" e rows="15". Adicione os


atributos paginator e rows:
Captulo 7 - Introduo ao JSF e Primefaces - Exerccio opcional: adicione paginao e ordenao tabela - Pgina 108

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

<p:dataTable var="negociacao" value="#{argentumBean.negociacoes}"


paginator="true" rows="15">

Salve a pgina, suba o servidor e acesse no seu navegador o endereo http://localhost:8080/


fj22-argentum-web/index.xhtml . Agora voc j consegue ver resultados paginados de 15 em 15 negociaes:

2) Para evitar chamar o webservice a cada vez que pedimos os prximos resultados paginados, adicione a
anotao @ViewScoped classe ArgentumBean:
@ManagedBean
@ViewScoped
public class ArgentumBean {
...
}

3) Deixe as colunas ordenveis, use o atributo sortBy em cada atributo. Por exemplo, para a coluna que
mostra o preo da negociao:
<p:column sortBy="#{negociacao.preco}" headerText="Preo" >
<h:outputText value="#{negociacao.preco}" />
</p:column>

Repare que usamos a expression language #{negociacao.preco} do JSF dentro do sortBy para definir o
valor a ordenar.
4) Como estamos permitindo a ordenao das colunas da nossa tabela, temos que colocar nossa
p:dataTable dentro de um h:form:
<h:form id="listaNegociacao">
<p:dataTable var="negociacao" value="#{argentumBean.negociacoes}">
<p:column sortBy="#{negociacao.preco}" headerText="Preo" >
<h:outputText value="#{negociacao.preco}" />
</p:column>
Captulo 7 - Introduo ao JSF e Primefaces - Exerccio opcional: adicione paginao e ordenao tabela - Pgina 109

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

<!-- outras colunas omitidas -->


</p:dataTable>
<h:form>

Salve a pgina e veja o resultado recarregando a pgina (F5) no seu navegador.

h:form sempre usar HTTP POST


importante saber que diferente da tag form no HTML, o h:form sempre envia uma requisio
HTTP do tipo POST. Ele nem nos d a possibilidade de escolher usar requisies GET.
Isso ocorre porque o JSF tenta abstrair o mundo HTTP e assim fica mais perto do desenvolvimento Desktop tradicional. Ele esconde do desenvolvedor o fato de que uma URL est sendo
chamada. Em vez disso, para o desenvolvedor, como se botes efetivamente chamassem mtodos ou eventos dentro de um Managed Bean.
A deciso automtica pelo POST foi a forma encontrada para abstrair o HTTP.

Captulo 7 - Introduo ao JSF e Primefaces - Exerccio opcional: adicione paginao e ordenao tabela - Pgina 110

Captulo 8

Refatorao: os Indicadores da bolsa


Nunca confie em um computador que voc no pode jogar pela janela.
Steve Wozniak

8.1

Anlise Tcnica da bolsa de valores

Munehisa Homna, no sculo 18, foi quem comeou a pesquisar os preos antigos do arroz para reconhecer
padres. Ele fez isso e comeou a criar um catlogo grande de figuras que se repetiam.
A estrela da manh, Doji, da figura abaixo, um exemplo de figura sempre muito buscada pelos analistas:

Ela indica um padro de reverso. Dizem que quando o preo de abertura e fechamento praticamente igual
(a estrela), essa uma forte indicao de que o mercado se inverta, isto , se estava em uma grande baixa,
tender a subir e, se estava em uma grande alta, tender a cair.
Baseada nessas ideias, surgiu a Anlise Tcnica Grafista: uma escola econmica que tem como objetivo
avaliar o melhor momento para compra e venda de aes atravs da anlise histrica e comportamental do

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

ativo na bolsa.
Essa forma de anlise dos dados gerados sobre dados das negociaes (preo, volume, etc), usa grficos na
busca de padres e faz anlise de tendncias para tentar prever o comportamento futuro de uma ao.
A anlise tcnica surgiu no incio do sculo 20, com o trabalho de Charles Dow e Edward Jones. Eles criaram
a empresa Dow Jones & Company e foram os primeiros a inventarem ndices para tentar prever o comportamento do mercado de aes. O primeiro ndice era simplesmente uma mdia ponderada de 11 ativos famosos
da poca, que deu origem ao que hoje conhecido como Dow-Jones.
A busca de padres nos candlesticks uma arte. Atravs de critrios subjetivos e formao de figuras, analistas podem determinar, com algum grau de acerto, como o mercado se comportar dali para a frente.

8.2

Indicadores Tcnicos

Uma das vrias formas de aplicar as premissas da anlise tcnica grafista 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, determinstico e de fcil clculo por um computador. at de praxe que analistas financeiros programem diversas
dessas frmulas em macros VBScript, para v-las dentro do Excel.
comum, na mesma visualizao, termos uma combinao de grficos, indicadores e at dos candles:

Diversos livros so publicados sobre o assunto e os principais homebrokers fornecem softwares que traam
esses indicadores e muitos outros. Alm disso, voc encontra uma lista com os indicadores mais usados e
como calcul-los em: http://stockcharts.com/school/doku.php?id=chart_school:technical_indicators

Captulo 8 - Refatorao: os Indicadores da bolsa - Indicadores Tcnicos - Pgina 112

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

8.3

As mdias mveis

H diversos tipos de mdias mveis usadas em anlises tcnicas e elas so frequentemente usadas para investidores 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.

Mdia mvel simples


A mdia mvel simples calcula a mdia aritmtica de algum dos valores das candlesticks do papel para um
determinado intervalo de tempo -- em geral, o valor de fechamento. Basta pegar todos os valores, somar e
dividir pelo nmero de dias.
A figura a seguir mostra duas mdias mveis simples: uma calculando a mdia dos ltimos 50 dias e outra
dos ltimos 200 dias. O grfico do valor das aes da antiga Sun Microsystems em 2001.

Repare que a mdia mvel mais curta, a de 50 dias, responde mais rpido aos movimentos atuais da ao,
mas pode gerar sinais pouco relevantes a mdio prazo.
Usualmente, estamos interessados na mdia mvel dos ltimos N dias e queremos definir esse dia inicial. Por
exemplo, para os dados de fechamento abaixo:
DIA
dia
dia
dia
dia
dia

1:
2:
3:
4:
5:

FECHAMENTO
31
32
33
34
33
Captulo 8 - Refatorao: os Indicadores da bolsa - As mdias mveis - Pgina 113

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

dia 6:
dia 7:
dia 8:

35
34
33

Vamos fazer as contas para que o indicador calcule a mdia para os 3 dias anteriores ao dia que estamos
interessados. Por exemplo: se pegamos o dia 6, a mdia mvel simples para os ltimos 3 dias a soma do
dia 4 ao dia 6: (34 + 33 + 35) / 3 = 34. A mdia mvel do dia 3 para os ltimos 3 dias 2: (31 + 32 + 33) / 3. E
assim por diante.

O grfico anterior das mdias mveis da Sun pega, para cada dia do grfico, a mdia dos 50 dias anteriores.

Mdia mvel ponderada


Outra mdia mvel muito famosa a ponderada. Ela tambm leva em conta os ltimos N dias a partir da data
a ser calculada. Mas, em vez de uma mdia aritmtica simples, faz-se uma mdia ponderada onde damos
mais peso para o valor mais recente e vamos diminuindo o peso dos valores conforme movemos para valores
mais antigos.
Por exemplo, para os dias a seguir:
DIA
dia
dia
dia
dia
dia
dia
dia
dia

1:
2:
3:
4:
5:
6:
7:
8:

FECHAMENTO
11
12
14
18
15
13
12
16

Vamos calcular a mdia mvel para os ltimos 3 dias, onde hoje tem peso 3, ontem tem peso 2 e anteontem
tem peso 1. Se calcularmos a mdia mvel ponderada para o dia 6 temos: (13*3 + 15*2 + 18*1) / 6 = 14.50.
Captulo 8 - Refatorao: os Indicadores da bolsa - As mdias mveis - Pgina 114

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

A mdia ponderada nos d uma viso melhor do que est acontecendo no momento com a cotao da minha
ao, mostrando com menos importncia os resultados atrasados, portanto menos relevantes para minhas
decises de compra e venda atuais. Essa mdia, contudo, no to eficiente quando estudamos uma srie a
longo prazo.

8.4

Exerccios: criando indicadores

1) 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 getUltimaPosicao() {
return this.candles.size() - 1;
}
}
MediaMovelSimples,
dentro
do
novo
pacote
br.com.caelum.argentum.indicadores. Essa classe ter o mtodo calcula que recebe a posio

2) Vamos

criar

classe

Captulo 8 - Refatorao: os Indicadores da bolsa - Exerccios: criando indicadores - Pgina 115

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

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;
}
}

A ideia passarmos para o mtodo calcula a SerieTemporal e o dia para o qual queremos calcular a mdia
mvel simples. Por exemplo, se passarmos que queremos a mdia do dia 6 da srie, ele deve calcular a
mdia dos valores de fechamento dos dias 6, 5 e 4 (j que nosso intervalo de 3 dias).
Como essa uma lgica um pouco mais complexa, comearemos essa implementao pelos testes.
3) Seguindo a ideia do TDD, faremos o teste antes mesmo de implementar a lgica da mdia. Assim como
voc j vem fazendo, use o ctrl + N -> JUnit Test Case para criar a classe de teste MediaMovelSimplesTest
na source folder src/test/java, pacote br.com.caelum.argentum.indicadores.
Ento, crie um teste para verificar que a mdia calculada corretamente para a sequncia de fechamentos
1, 2, 3, 4, 3, 4, 5, 4, 3.
Note que, para fazer tal teste, ser necessrio criar uma srie temporal com candles cujo fechamento
tenha tais valores. Criaremos uma outra classe para auxiliar nesses testes logo em seguida. Por hora, no
se preocupe com o erro de compilao da 5a. linha do cdigo abaixo:
1

public class MediaMovelSimplesTest {

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

3
4
5
6
7
8

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);

9
10
11
12
13
14
15

16
17

Captulo 8 - Refatorao: os Indicadores da bolsa - Exerccios: criando indicadores - Pgina 116

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

4) Ainda necessrio fazer esse cdigo compilar! Note que, pelo que escrevemos, queremos chamar um
mtodo esttico na classe GeradorDeSerie que receber diversos valores e devolver a srie com Candles
respectivas.
Deixe que o Eclipse o ajude a criar essa classe: use o ctrl + 1 e deixe que ele crie a classe para voc
e, ento, adicione a ela o mtodo criaSerie, usando o recurso de varargs do Java para receber diversos
doubles.

Varargs
A notao double... valores (com os trs pontinhos mesmo!) que usaremos no mtodo a
seguir indicao do uso de varargs. Esse recurso est presente desde o Java 5 e permite que
chamemos o mtodo passando de zero a quantos doubles quisermos! Dentro do mtodo, esses
argumentos sero interpretados como um array.
Varargs vieram para oferecer uma sintaxe mais amigvel nesses casos. Antigamente, quando
queramos passar um nmero varivel de parmetros de um mesmo tipo para um mtodo, era
necessrio construir um array com esses parmetros e pass-lo como parmetro.
Leia mais sobre esse recurso em: http://docs.oracle.com/javase/1.5.0/docs/guide/language/
varargs.html
Na classe GeradorDeSerie, faa o seguinte mtodo:
Ateno: no necessrio copiar o JavaDoc.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

/**
* 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
devolve zero!
5) Volte classe principal MediaMovelSimples e implemente agora a lgica de negcio do mtodo calcula,
que j existe. O mtodo deve ficar parecido com o que segue:
Captulo 8 - Refatorao: os Indicadores da bolsa - Exerccios: criando indicadores - Pgina 117

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

public class MediaMovelSimples {

public double calcula(int posicao, SerieTemporal serie) {


double soma = 0.0;
for (int i = posicao; i > posicao - 3; i--) {
Candlestick c = serie.getCandle(i);
soma += c.getFechamento();
}
return soma / 3;
}

3
4
5
6
7
8
9
10
11

Repare que iniciamos o for com posicao e iteramos com i--, retrocedendo nas posies enquanto elas
forem maiores que os trs dias de intervalo. Isso significa que estamos calculando a mdia mvel apenas
dos ltimos 3 dias.
Mais para frente, existe um exerccio opcional para parametrizar esse valor.
6) Crie a classe MediaMovelPonderada anloga a MediaMovelSimples. Essa classe d peso 3 para o dia atual,
peso 2 para o dia anterior e o peso 1 para o dia antes desse. O cdigo interno muito parecido com o da
mdia mvel simples, s precisamos multiplicar sempre pela quantidade de dias passados.
A implementao do mtodo calcula deve ficar bem parecida com isso:
1

public class MediaMovelPonderada {

public double calcula(int posicao, SerieTemporal serie) {


double soma = 0.0;
int peso = 3;

3
4
5
6

for (int i = posicao; i > posicao - 3; i--) {


Candlestick c = serie.getCandle(i);
soma += c.getFechamento() * peso;
peso--;
}
return soma / 6;

7
8
9
10
11
12

13
14

Repare que o peso comea valendo 3, o tamanho do nosso intervalo, para o dia atual e vai reduzindo
conforme nos afastamos do dia atual, demonstrando a maior importncia dos valores mais recentes.
A diviso por 6 no final a soma dos pesos para o intervalo de 3 dias: (3 + 2 + 1 = 6).
7) Depois a classe MediaMovelPonderada deve passar pelo seguinte teste:
public class MediaMovelPonderadaTest {

Captulo 8 - Refatorao: os Indicadores da bolsa - Exerccios: criando indicadores - Pgina 118

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

@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
Assert.assertEquals(14.0/6,
Assert.assertEquals(20.0/6,
Assert.assertEquals(26.0/6,
Assert.assertEquals(32.0/6,

+3*3 = 14. Divide por 6, da 14/6


mmp.calcula(2, serie), 0.00001);
mmp.calcula(3, serie), 0.00001);
mmp.calcula(4, serie), 0.00001);
mmp.calcula(5, serie), 0.00001);

}
}

Rode o teste e veja se passamos!


8) (opcional) Crie um teste de unidade em uma nova classe SerieTemporalTest, que verifique se essa classe
pode receber uma lista nula. O que no deveria poder.
Aproveite o momento para pensar quais outros testes poderiam ser feitos para essa classe.

8.5

Refatorao

"Refatorao uma tcnica controlada para reestruturar um trecho de cdigo existente, alterando sua estrutura
interna sem modificar seu comportamento externo. Consiste em uma srie de pequenas transformaes que
preservam o comportamento inicial. Cada transformao (chamada de refatorao) reflete em uma pequena
mudana, mas uma sequncia de transformaes pode produzir uma significante reestruturao. Como cada
refatorao pequena, menos provvel que se introduza um erro. Alm disso, o sistema continua em pleno
funcionamento depois de cada pequena refatorao, reduzindo as chances do sistema ser seriamente danificado
durante a reestruturao. -- Martin Fowler
Em outras palavras, refatorao o processo de modificar um trecho de cdigo j escrito, executando pequenos passos (baby-steps) sem modificar o comportamento do sistema. uma tcnica utilizada para melhorar
a clareza do cdigo, facilitando a leitura ou melhorando o design do sistema.
Note que para garantir que erros no sero introduzidos nas refatoraes, bem como para ter certeza de
que o sistema continua se comportando da mesma maneira que antes, a presena de testes fundamental.
Com eles, qualquer erro introduzido ser imediatamente apontado, facilitando a correo a cada passo da
refatorao imediatamente.
Algumas das refatoraes mais recorrentes ganharam nomes que identificam sua utilidade (veremos algumas
nas prximas sees). Alm disso, Martin Fowler escreveu o livro Refactoring: Improving the Design of
Existing Code, onde descreve em detalhes as principais.
Algumas so to corriqueiras, que o prprio Eclipse inclui um menu com diversas refatoraes que ele
Captulo 8 - Refatorao: os Indicadores da bolsa - Refatorao - Pgina 119

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

capaz de fazer por voc:

8.6

Exerccios: Primeiras refatoraes

1) 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.
Use ctrl + shift + T para localizar e abrir a classe Candlestick.
Seja no Package Explorer ou na classe aberta no editor, coloque o cursor sobre o nome da classe e use
o atalho alt + shift + R, que renomeia. Esse atalho funciona para classes e tambm para mtodos,
variveis, etc.

2) No mtodo calcula da classe MediaMovelSimples, temos uma varivel do tipo Candle que s serve para
que peguemos o fechamento desse objeto. Podemos, ento, deixar esse mtodo uma linha menor fazendo
o inline dessa varivel!
Captulo 8 - Refatorao: os Indicadores da bolsa - Exerccios: Primeiras refatoraes - Pgina 120

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

Na linha 4 do mtodo abaixo, coloque o cursor na varivel c e use o alt + shift + I. (Alternativamente,
use ctrl + 1 Inline local variable)
1
2
3
4
5
6
7
8

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 ficar 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)!


3) 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 dizem para
isolar ento essa parte repetida em um novo mtodo que, alm de poder ser chamado vrias vezes, ainda
tem um nome que ajuda a compreender o algoritmo final.
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.

Captulo 8 - Refatorao: os Indicadores da bolsa - Exerccios: Primeiras refatoraes - Pgina 121

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

Repare como a IDE resolve os parmetros e ainda substitui as chamadas ao cdigo repetido pela chamada
ao novo mtodo.
4) 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.
Para isso, usaremos a refatorao Extract Local Variable atravs do Eclipse. Selecione a primeira chamada
para negociacao.getPreco() e pressione alt + shift + L.
Um box vai aparecer perguntando o nome da varivel que ser criada, mantenha o nome aconselhado
pelo Eclipse e pressione OK.
O Eclipse vai alterar o cdigo de forma que fique parecido com:
Captulo 8 - Refatorao: os Indicadores da bolsa - Exerccios: Primeiras refatoraes - Pgina 122

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

// ...
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.
5) (Opcional) Aproveite e mude os nomes das outras classes que usam a palavra Candlestick: a Factory e
os Testes.

Refatoraes disponveis
Para quem est comeando com a usar o Eclipse, a quantidade de atalhos pode assustar. Note,
contudo, que os atalhos de refatorao comeam sempre com alt + shift!
Para ajudar um pouco, comece memorizando apenas o atalho que mostra as refatoraes disponveis dado o trecho de cdigo selecionado: alt + shift + T.

8.7

Refatoraes maiores

As refatoraes que fizemos 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
aplicao. Algumas refatoraes ainda mais complexas chegam a modificar at a arquitetura do sistema! Mas,
quanto mais complexa a mudana para chegar ao resultado final, mais importante quebrar essa refatorao
em pedaos pequenos e rodar os testes a cada passo.
Nos prximos captulos faremos refatoraes que flexibilizam nosso sistema e tornam muito mais fcil 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;
Captulo 8 - Refatorao: os Indicadores da bolsa - Refatoraes maiores - Pgina 123

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

Trocar uma implementao domstica por uma biblioteca;


Extrair uma biblioteca de dentro de um projeto;
etc...

8.8

Discusso em aula: quando refatorar?

Captulo 8 - Refatorao: os Indicadores da bolsa - Discusso em aula: quando refatorar? - Pgina 124

Captulo 9

Grficos interativos com Primefaces


A nica pessoa educada aquela que aprendeu a aprender e a mudar.
Carl Rogers

9.1

Por que usar grficos?

Nossa aplicao apresenta os dados das negociaes tabularmente atravs do componente p:dataTable. Essa
forma de mostrar informaes interessante para analisarmos dados um a um, mas no ajudam muito
quando queremos ter uma ideia do que acontece com dados coletivamente.
Grficos comprovadamente ajudam no entendimento mais abrangente dos dados e so mais fceis de analisar
do que nmeros dentro de uma tabela. simples reconhecer padres de imagens, por exemplo na anlise
tcnica de valores da bolsa.
Para o projeto Argentum, apresentaremos os valores da SerieTemporal em um grfico de linha, aplicando
algum indicador como abertura ou fechamento. Continuaremos com a biblioteca Primefaces que j vem
com suporte para vrios tipos de grficos.

Exemplos de grficos
O Primefaces j possui diversos componentes para grficos: possvel utiliz-lo para desenhar grficos de
linha, de barra, de pizza, de rea, grficos para atualizao dinmica e at para Candles, entre outros. Tambm
possvel exportar e animar grficos.

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

9.2

Grficos com o Primefaces

Vamos usar o Primefaces para gerar um grfico que mostra a evoluo dos valores da srie.
Nosso projeto est configurado e j podemos decidir qual grfico utilizar. Para facilitar a deciso e ao mesmo
tempo ver as possibilidades e tipos de grficos disponveis, o showcase do Primefaces nos ajudar muito:
http://www.primefaces.org/showcase/ui/home.jsf
Nele encontramos o resultado final e tambm o cdigo utilizado para a renderizao. Vamos programar usando o componente p:lineChart que deve mostrar os valores de abertura ou de fechamento da
SerieTemporal.

Captulo 9 - Grficos interativos com Primefaces - Grficos com o Primefaces - Pgina 126

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

O uso de componente simples, veja 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 definir 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 (value) atravs da
Expression Language que chama o Managed Bean #{chartBean.categoryModel}.

9.3

Propriedades para personalizar o grfico

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 Y
title - o ttulo do grfico
fill - true ou false, preenche o grfico, no renderiza uma linha apenas
showMarkers - true ou false, habilita detalhes em cada ponto do grfico
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 grficos
no qual podemos ver as classes relacionadas, atributos do componentes com exemplos de utilizao. Segue
uma parte da documentao oficial do Primefaces:

Captulo 9 - Grficos interativos com Primefaces - Propriedades para personalizar o grfico - Pgina 127

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

A documentao do Primefaces est disponvel na internet e na forma de um guia do usurio em PDF. Ela
far parte do dia-a-dia do desenvolvedor, que a consultar sempre que necessrio:
http://www.primefaces.org/documentation.html
Tambm h o tradicional Javadoc disponvel em: http://www.primefaces.org/docs/api/3.5/. 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 fundamental ter acesso ao Javadoc e documentao da biblioteca para saber quais classes, atributos e mtodos
utilizar.
Captulo 9 - Grficos interativos com Primefaces - Propriedades para personalizar o grfico - Pgina 128

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

JSF e CSS
O Primefaces ajuda o desenvolvedor atravs de seu suporte a temas, mas nem sempre ele suficiente, inclusive quando h uma equipe de designers responsvel em determinar a apresentao
da aplicao.
Apesar de trabalharmos com componentes, no final o que enviado para o cliente puro HTML.
Assim, quem conhece CSS pode aplicar estilos para sobrescrever o visual da aplicao.
A Caelum oferece o curso Desenvolvimento Web com HTML, CSS e JavaScript, para aqueles que querem aprender a criar interfaces Web com experincia rica do usurio, estruturao
correta e otimizaes SEO.

Aplicando ao nosso projeto


Para mostrarmos o grfico no Argentum, usaremos a tag do Primefaces vista acima, colocando o ttulo Indicadores e a legenda de quais indicadores esto sendo traados esquerda do grfico.
No p:lineChart, passaremos essas informaes pelos atributos title, que recebe o ttulo como texto, e
legendPosition, que usa direes geogrficas para definir a posio da legenda. Isto , se queremos que ela
fique esquerda indicaremos que a legenda vai na poro oeste (west) do grfico.
<p:lineChart legendPosition="w" title="Indicadores"/>

Da forma como est, no entanto, no h nada a ser mostrado no grfico. Ainda falta indicarmos para o
componente que os dados, o modelo do grfico, ser disponibilizado por nosso ManagedBean. Em outras
palavras, faltou indicarmos que o value desse grfico ser produzido em argentumBean.modeloGrafico.
Nossa adio ao index.xhtml ser, portanto:
<p:lineChart value="#{argentumBean.modeloGrafico}"
legendPosition="w" title="Indicadores"/>

9.4

Definio do modelo do grfico

J temos uma noo de como renderizar grficos atravs de componentes do Primefaces. O desenvolvedor
no precisa se preocupar como detalhes de JavaScript, imagem ou animaes. Tudo isso encapsulado no
prprio componente, seguindo boas prticas do mundo orientado a objetos.
Apenas, ser necessrio informar ao componente quais so os dados a serem plotados no grfico em questo.
Esses dados representam o modelo do grfico e devem ser disponibilizados como o value para o p:lineChart
em um objeto do tipo org.primefaces.model.chart.ChartModel.
Captulo 9 - Grficos interativos com Primefaces - Definio do modelo do grfico - Pgina 129

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

Essa a classe principal do modelo e h classes filhas especializadas dela como CartesianChartModel,
PieChartModel ou BubbleChartModel. No JavaDoc podemos ver todas as filhas da ChartModel e ainda no
showcase possvel ver o ManagedBean responsvel por cada modelo de grfico. Assim, saberemos qual delas
devemos usar de acordo com o grfico escolhido:
Javadoc: http://www.primefaces.org/docs/api/3.5/org/primefaces/model/chart/ChartModel.html
No nosso projeto, utilizaremos o CartesianChartModel, j que queremos plotar pontos em um grfico de
linha. Um CartesianChartModel recebe uma ou mais ChartSeries e cada ChartSeries representa uma
linha no grfico do componente p:lineChart. Uma ChartSeries, por sua vez, contm todos os pontos de
uma linha do grfico, isto , os valores X e Y que sero ligados pela linha do grfico.
Vejo como fica o cdigo fcil de usar:
ChartSeries serieGrafico = new ChartSeries("Abertura");
serieGrafico.set("dia 1", 20.9);
serieGrafico.set("dia 2", 25.1);
serieGrafico.set("dia 3", 22.6);
serieGrafico.set("dia 4", 24.6);
CartesianChartModel modeloGrafico = new CartesianChartModel();
modeloGrafico.addSeries(serieGrafico);

Uma ChartSeries recebe no construtor a legenda da linha que ela representa (label) e, atravs do mtodo set,
passamos os valores de cada ponto nos eixos horizontal e vertical, respectivamente. No exemplo acima, os valores colocados so fixos, mas na nossa implementao do Argentum, claro, iteraremos pela SeriaTemporal
calculando os indicadores sobre ela.
Isto , uma vez que temos a SerieTemporal, nosso cdigo para plotar a mdia mvel simples do fechamento
em uma ChartSeries ser semelhante a este:
SerieTemporal serie = ...
ChartSeries chartSeries = new ChartSeries("MMS do Fechamento");
MediaMovelSimples indicador = new MediaMovelSimples();
for (int i = 2; i < serie.getUltimaPosicao(); i++) {
double valor = indicador.calcula(i, serie);
chartSeries.set(i, valor);
}
CartesianChartModel modeloGrafico = new CartesianChartModel();
modeloGrafico.addSeries(chartSeries);

Conseguir a srie temporal um problema pelo qual j passamos antes. Relembre que a SerieTemporal
apenas um wrapper de uma lista de Candles. E a lista de Candles gerada pelo CandlestickFactory
resumindo uma lista com muitas Negociacoes.
Captulo 9 - Grficos interativos com Primefaces - Definio do modelo do grfico - Pgina 130

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

Se procurarmos o local no nosso cdigo onde pegamos a lista de negociaes do web service, vamos notar
que isso acontece no construtor da ArgentumBean. Seu cdigo completo ficaria assim;
public ArgentumBean() {
this.negociacoes = new ClienteWebService().getNegociacoes();
List<Candle> candles = new CandleFactory().constroiCandles(negociacoes);
SerieTemporal serie = new SerieTemporal(candles);
ChartSeries chartSeries = new ChartSeries("MMS do Fechamento");
MediaMovelSimples indicador = new MediaMovelSimples();
for (int i = 2; i < serie.getUltimaPosicao(); i++) {
double valor = indicador.calcula(i, serie);
chartSeries.set(i, valor);
}
this.modeloGrafico = new CartesianChartModel();
modeloGrafico.addSeries(chartSeries);
}

Note, no entanto, que esse trecho de cdigo est com responsabilidades demais: ele busca as negociaes no
web service, cria a srie temporal, plota um indicador e disponibiliza o modelo do grfico. E, pior ainda, esse
cdigo ainda est no construtor do ArgentumBean!
Com todo esse cdigo no construtor do bean, teramos um cdigo mais sujo, pouco coeso e muito difcil de
testar. O que acontece aqui que no estamos separando responsabilidades o bastante e nem encapsulando
a lgica de gerao de grfico corretamente.

9.5

Isolando a API do Primefaces: baixo acoplamento

O que acontecer se precisarmos criar dois grficos de indicadores diferentes? Vamos copiar e colar todo
aquele cdigo e modificar apenas as partes que mudam? E se precisarmos alterar algo na gerao do modelo?
Essas mudanas no sero fceis se tivermos o cdigo todo espalhado pelo nosso programa.
Os princpios de orientao a objetos e as boas prticas de programao vm ao nosso socorro aqui. Vamos
encapsular a maneira como o modelo do grfico criado na classe GeradorModeloGrafico.
Essa classe deve ser capaz de gerar o ChartModel para nosso grfico de linhas, com os pontos plotados pelos
indicadores com base nos valores de uma srie temporal. Isto , nosso GeradorModeloGrafico precisa receber
a SerieTemporal sobre a qual plotar os indicadores.
Captulo 9 - Grficos interativos com Primefaces - Isolando a API do Primefaces: baixo acoplamento - Pgina 131

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

Se quisermos restringir o grfico a um perodo menor do que o devolvido pelo web service, uma boa recebermos as posies de incio e fim que devem ser plotadas. Esse intervalo tambm serve para que no
tentemos calcular a mdia da posio zero, por exemplo -- note que, como a mdia dos trs ltimos valores, tentaramos pegar as posies 0, -1 e -2, o que causaria uma IndexOutOfBoundsException.
Como essas informaes so fundamentais para qualquer grfico que plotemos, o gerador do modelo do grfico receber tais informaes no construtor. Alm delas, teremos tambm o objeto do
CartesianChartModel, que guardar as informaes do grfico.
public class GeradorModeloGrafico {
private
private
private
private

SerieTemporal serie;
int comeco;
int fim;
CartesianChartModel modeloGrafico;

public GeradorModeloGrafico(SerieTemporal serie, int comeco, int fim) {


this.serie = serie;
this.comeco = comeco;
this.fim = fim;
this.modeloGrafico = new CartesianChartModel();
}
}

E, quem for usar essa classe, far:


SerieTemporal serie = //...
GeradorModeloGrafico g = new GeradorModeloGrafico(serie, inicio, fim);

Repare como o cdigo que usa o GeradorModeloGrafico no possui nada que o ligue ao ChartModel especificamente. O dia em que precisarmos mudar o grfico a ser plotado ou mesmo mudar a tecnologia que gerar
o grfico, s precisaremos alterar a classe GeradorModeloGrafico. Relembre o conceito: esse o poder do
encapsulamento!
E nossa classe no se limitar a isso: ela encapsular tudo o que for relacionado ao grfico. Por exemplo, para
criar o grfico, precisamos ainda de um mtodo que plote os pontos calculados por um indicador, como
o plotaMediaMovelSimples abaixo. Ele passa por cada posio do comeco ao fim da serie, chamando o
clculo da mdia mvel simples.
public void plotaMediaMovelSimples() {
MediaMovelSimples indicador = new MediaMovelSimples();
LineChartSeries chartSerie = new LineChartSeries("MMS - Fechamento");

Captulo 9 - Grficos interativos com Primefaces - Isolando a API do Primefaces: baixo acoplamento - Pgina 132

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

for (int i = comeco; i <= fim; i++) {


double valor = indicador.calcula(i, serie);
chartSerie.set(i, valor);
}
this.modeloGrafico.addSeries(chartSerie);
}

O mtodo plotaMediaMovelSimples cria um objeto da MediaMovelSimples e varre a SerieTemporal recebida para calcular o conjunto de dados para o modelo do grfico.
Por fim, ainda precisaremos de um mtodo getModeloGrafico que devolver o modelo para o ArgentumBean,
j que o componente p:lineChart que precisar desse objeto preenchido. Repare que o retorno do tipo
ChartModel, super classe do CartesianChartModel. boa prtica deixar nossa classe a mais genrica possvel
para funcionar com qualquer tipo de mtodo.

Effective Java: refira-se a objetos pela sua interface


O item 34 do Effective Java discorre sobre preferir referenciar objetos pela sua interface, em vez
de pelo seu prprio exato, sempre que este for relevante para o restante do sistema.
O livro tambm menciona que, na falta de uma interface adequada, uma superclasse pode ser
utilizada, o que nosso caso com a superclasse abstrata ChartModel. Referir-se a um objeto da
forma mais genrica possvel uma boa ideia, j que isso faz com que futuras mudanas limitemse ao mximo classe que as encapsula.
Veja como fica o programa dentro do ArgentumBean e note que essa classe apenas delega para a outra toda
a parte de criao do grfico:
public class ArgentumBean {
private
private
private
private

List<Negociacao> negociacoes;
String indicadorBase;
String media;
ChartModel modeloGrafico;

public ArgentumBean() {
this.negociacoes = new ClienteWebService().getNegociacoes();
List<Candle> candles = new CandleFactory().constroiCandles(negociacoes);
SerieTemporal serie = new SerieTemporal(candles);
GeradorModeloGrafico geradorGrafico =
new GeradorModeloGrafico(serie, 2, serie.getUltimaPosicao());
geradorGrafico.plotaMediaMovelSimples();
this.modeloGrafico = geradorGrafico.getModeloGrafico();

Captulo 9 - Grficos interativos com Primefaces - Isolando a API do Primefaces: baixo acoplamento - Pgina 133

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

}
public List<Negociacao> getNegociacoes() {
return negociacoes;
}
public ChartModel getModeloGrafico() {
return modeloGrafico;
}
}

Note que, para quem usa o GeradorModeloGrafico nem d para saber como ele gera o modelo. um cdigo
encapsulado, flexvel, pouco acoplado e elegante: usa boas prticas da Orientao a Objetos.

9.6

Para saber mais: Design Patterns Factory Method e Builder

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 ajudam a criar objetos complicados.
A factory usada pelo GeradorDeSerie dos testes. A ideia que criar um objeto SerieTemporal diretamente
complicado. Ento criaram um mtodo de fbrica que encapsula essas complicaes e j devolve o objeto
prontinho para uso.
O padro Builder o que estamos usando na classe GeradorModeloGrafico. Queremos encapsular a criao
complicada do modelo e que pode mudar depois com o tempo. Entra a o objeto construtor da nossa classe
Builder: seu nico objetivo descrever os passos para criao do nosso objeto final (o grfico) e encapsular
a complexidade disso.
Leia mais sobre esses e outros Design Patterns no livro do GoF.

Captulo 9 - Grficos interativos com Primefaces - Para saber mais: Design Patterns Factory Method e Builder - Pgina 134

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

JFreeChart
O JFreeChart uma biblioteca famosa para desenho de grficos, independente da tecnologia
JSF. um projeto de software livre iniciado em 2000 e que tem ampla aceitao pelo mercado,
funcionando at em ambientes antigos que rodam Java 1.3.
Alm do fato de ser livre, possui a vantagem de ser bastante robusta e flexvel. possvel us-la
para desenhar grficos de pontos, de barra, de torta, de linha, grficos financeiros, gantt charts,
em 2D ou 3D e muitos outros. Consegue dar sada em JPG, PNG, SVG, EPS e at mesmo exibir
em componentes Swing.

O site oficial possui links para download, demos e documentao:


http://www.jfree.org/jfreechart/
Existe um livro oficial do JFreeChart escrito pelos desenvolvedores com exemplos e explicaes
detalhadas de vrios grficos diferentes. Ele pago e pode ser obtido no site oficial. Alm disso,
h muitos tutoriais gratuitos na internet.

9.7

Exerccios: Grficos com Primefaces

src/main/java crie a classe GeradorModeloGrafico


br.com.caelum.argentum.grafico para encapsular a criao do modelo do grfico.

1) Dentro

da

pasta

no

pacote

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 9 - Grficos interativos com Primefaces - Exerccios: Grficos com Primefaces - Pgina 135

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;
}
}

2) Agora que j temos uma classe que criar o modelo do grfico, falta us-la para renderizar o grfico na
tela usando a tag do Primefaces. Abra a pgina index.xhtml que se encontra na pasta WebContent.
Na pgina procure o componente h:body. Logo depois da abertura da tag h:body e antes do h:form da
lista de negociaes, adicione o componente p:lineChart:
<p:lineChart value="#{argentumBean.modeloGrafico}"
legendPosition="w" title="Indicadores"/>

3) Na classe ArgentumBean, procure o construtor. nele que criaremos uma SerieTemporal baseada na lista
de negociaes do Web Service. Depois usaremos o GeradorModeloGrafico para criar o modelo grfico:
public ArgentumBean() {
this.negociacoes = new ClienteWebService().getNegociacoes();
List<Candle> candles = new CandleFactory().constroiCandles(negociacoes);
SerieTemporal serie = new SerieTemporal(candles);
GeradorModeloGrafico geradorGrafico =
new GeradorModeloGrafico(serie, 2, serie.getUltimaPosicao());
geradorGrafico.plotaMediaMovelSimples();
this.modeloGrafico = geradorGrafico.getModeloGrafico();
}

4) Voc deve estar vendo um erro de compilao na ltima linha do seu construtor. Ele acontece porque
Captulo 9 - Grficos interativos com Primefaces - Exerccios: Grficos com Primefaces - Pgina 136

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

faltou criarmos um novo atributo que representa o modelo do grfico. Use o ctrl + 1 para criar o atributo
e, ao mesmo tempo, fazer o import da classe.
private ChartModel modeloGrafico;

Gere tambm o getter para este atributo, para que o componente p:lineChart consiga pegar o modelo
do grfico quando necessitar.
Para isso, na classe ArgentumBean, escreva getM e aperte ctrl + espao. O Eclipse sugerir o getter para o
atributo modeloGrafico.
Salve o projeto. Reinicie o Tomcat e acesse em seu navegador: http://localhost:8080/fj22-argentum-web/
index.xhtml

Captulo 9 - Grficos interativos com Primefaces - Exerccios: Grficos com Primefaces - Pgina 137

Captulo 10

Aplicando Padres de projeto


Estamos todos na sarjeta, mas alguns de ns esto olhando para as estrelas.
Oscar Wilde

10.1

Nossos indicadores e o design pattern Strategy

Nosso gerador de grficos j est interessante, mas no momento ele s consegue plotar a Mdia Mvel Simples
do fechamento da srie. Nosso cliente certamente precisar de outros indicadores tcnicos como o de Mdia
Mvel Ponderada ou ainda indicadores mais simples como os de Abertura ou de Fechamento.
Esses indicadores, similarmente MediaMovelSimples, devem calcular o valor de uma posio do grfico
baseado na SerieTemporal que ele atende.
Se tivermos esses indicadores todos, precisaremos que o GeradorModeloGrafico consiga plotar cada um desses grficos. Terminaremos com uma crescente classe GeradorModeloGrafico com mtodos extremamente
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);
}
//...
}

O problema que cada vez que criarmos um indicador tcnico diferente, um novo mtodo dever ser criado
na classe GeradorModeloGrafico. Isso uma indicao clssica de acoplamento no sistema.
Como resolver esses problemas de acoplamento e de cdigo parecidssimo nos mtodos? Ser que conseguimos criar um nico mtodo para plotar e passar como argumento qual indicador tcnico queremos plotar
naquele momento?
Note que a diferena entre os mtodos est apenas no new do indicador escolhido e na legenda do grfico. O
restante precisamente igual.

A orientao a objetos nos d a resposta: polimorfismo! Repare que nossos dois indicadores possuem a
mesma assinatura de mtodo, parece at que eles assinaram o mesmo contrato. Vamos definir ento a interface Indicador:
Captulo 10 - Aplicando Padres de projeto - Nossos indicadores e o design pattern Strategy - Pgina 139

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

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 grfico que recebe um Indicador
qualquer. O objeto do indicador ser responsvel por calcular o valor no ponto pedido (mtodo calcula) e,
tambm, pela legenda do grfico (mtodo toString)
public class GeradorModeloGrafico {
public void plotaIndicador(Indicador indicador) {
LineChartSeries chartSerie = new LineChartSeries(indicador.toString());
for (int i = comeco; i <= fim; i++) {
double valor = indicador.calcula(i, serie);
chartSeries.set(i, valor);
}
this.modeloGrafico.addSeries(chartSeries);
}
}

Na hora de desenhar os grficos, chamaremos sempre o plotaIndicador, passando como parmetro qualquer 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 polimorfismo e poder trocar os indicadores. Nosso mtodo
plota qualquer Indicador, isto , quando criarmos ou removermos uma implementao de indicador, no
precisaremos mexer no GeradorModeloGrafico: ganhamos flexibilidade e aumentamos a coeso. Podemos
ainda criar novos indicadores que implementem a interface e pass-los para o grfico sem que nunca mais
mexamos na classe GeradorModeloGrafico.
Por exemplo, imagine que queremos um grfico simples que mostre apenas os preos de fechamento. Podemos 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();
}
}
Captulo 10 - Aplicando Padres de projeto - Nossos indicadores e o design pattern Strategy - Pgina 140

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

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. Note que o plotaIndicador no recebe dados, mas sim a forma de manipular esses
dados, a estratgia para trat-los. Esse o design pattern chamado de Strategy.

Design Patterns

Design Patterns so aquelas solues catalogadas para problemas clssicos de orientao a objetos, como este que temos no momento: encapsular e ter flexibilidade.
A fbrica de Candles apresentada em outro captulo e o mtodo que nos auxilia a criar sries
para testes na GeradorDeSerie so exemplos, respectivamente, dos padres Abstract Factory e
Factory Method. No caso que estamos estudando agora, o Strategy est nos ajudando a deixar a
classe GeradorModeloGrafico isolada das diferentes formas de clculo dos indicadores.

10.2

Exerccios: refatorando para uma interface e usando


bem os testes

1) 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 + 3 Extract interface. Selecione o mtodo calcula e d o
nome da interface de Indicador:
Ateno: A interface deve ficar dentro do pacote br.com.caelum.argentum.indicadores:

Captulo 10 - Aplicando Padres de projeto - Exerccios: refatorando para uma interface e usando bem os testes - Pgina 141

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

Effective Java
Item 52: Refira a objetos pelas suas interfaces
2) Na classe MediaMovelPonderada coloque agora o implements Indicador nela.
public class MediaMovelPonderada implements Indicador {
...
}

3) Vamos criar tambm uma classe para, por exemplo, ser o indicador do preo de fechamento, o
IndicadorFechamento, no pacote br.com.caelum.argentum.indicadores, que implementa a interface
Indicador.
Note que, ao adicionar o trecho implements Indicador classe, o Eclipse mostra um erro de compilao.
Usando o ctrl + 1, escolha a opo Add unimplemented methods para que ele crie toda a assinatura do
mtodo calcula.
No final, faltar preencher apenas a linha destacada:
public class IndicadorFechamento implements Indicador {
@Override
public double calcula(int posicao, SerieTemporal serie) {
return serie.getCandle(posicao).getFechamento();
}
}

criar o IndicadorAbertura,
tambm
br.com.caelum.argentum.indicadores, que implementa a interface Indicador:

4) De

maneira

anloga

vamos

no

pacote

Captulo 10 - Aplicando Padres de projeto - Exerccios: refatorando para uma interface e usando bem os testes - Pgina 142

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

public class IndicadorAbertura implements Indicador {


@Override
public double calcula(int posicao, SerieTemporal serie) {
return serie.getCandle(posicao).getAbertura();
}
}

5) Volte para a classe GeradorModeloGrafico e altere o mtodo plotaMediaMovelSimples usando o atalho


alt + shift + C. Voc precisar alterar o nome para plotaIndicador e adicionar um parmetro. Veja com
ateno o screenshot abaixo:

Ignore o erro e, quando essa refatorao terminar, remova a linha que declarava o indicador. Seu mtodo
terminar assim:
public void plotaIndicador(Indicador indicador) {
LineChartSeries chartSeries = new LineChartSeries(indicador.toString());
for (int i = comeco; i <= fim; i++) {
double valor = indicador.calcula(i, serie);
chartSeries.set(i, valor);
}
modeloGrafico.addSeries(chartSeries);
}

6) Repare que estamos chamando o mtodo toString() do indicador no mtodo plotaIndicador(). Vamos sobrescrev-lo em todos os indicadores criados.
Sobrescreva na classe MediaMovelSimples:

Captulo 10 - Aplicando Padres de projeto - Exerccios: refatorando para uma interface e usando bem os testes - Pgina 143

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

public class MediaMovelSimples implements Indicador{


// mtodo calcula
public String toString() {
return "MMS de Fechamento";
}
}

Sobrescreva na classe MediaMovelPonderada:


public class MediaMovelPonderada implements Indicador{
// mtodo calcula
public String toString() {
return "MMP de Fechamento";
}
}

Tambm na classe IndicadorFechamento:


public class IndicadorFechamento implements Indicador {
// mtodo calcula
public String toString() {
return "Fechamento";
}
}

E por ltimo na classe IndicadorAbertura:


public class IndicadorAbertura implements Indicador {
// mtodo calcula
public String toString() {
return "Abertura";
}
}

10.3

Exerccios opcionais

1) Nossos clculos de mdias mveis so sempre para o intervalo de 3 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 ficarem desatualizados aparecero com erros de compilao.
Captulo 10 - Aplicando Padres de projeto - Exerccios opcionais - Pgina 144

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

2) Toda refatorao deve ser acompanhada dos testes para garantir que no quebramos nada! Rode os testes
e veja se as mudanas feitas at agora mudaram o comportamento do programa.
Se voc julgar necessrio, acrescente mais testes sua aplicao refatorada.

10.4

Indicadores mais elaborados e o Design Pattern Decorator

Vimos no captulo de refatorao que os analistas financeiros fazem suas anlises sobre indicadores mais elaborados, 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 colocaramos l? Provavelmente, copiaramos o cdigo que j temos e apenas trocaramos a chamada do
getFechamento pelo getAbertura e getMaximo.
A maior parte do cdigo seria a mesma e no estamos reaproveitando cdigo - copiar e colar cdigo no
reaproveitamento, uma forma de nos dar dor de cabea no futuro ao ter que manter 2 cdigos idnticos em
lugares diferentes.
Queremos calcular mdias mveis de fechamento, abertura, volume, etc, sem precisar copiar essas classes de
mdia. Na verdade, o que queremos calcular a mdia mvel baseado em algum outro indicador. J temos
a classe IndicadorFechamento e trivial implementar outros como IndicadorAbertura, IndicadorMinimo,
etc.
A MediaMovelSimples um Indicador que vai depender de algum outro Indicador para ser calculada (por
exemplo o IndicadorFechamento). Queremos chegar em algo assim:
MediaMovelSimples mms = new MediaMovelSimples(new IndicadorFechamento());
// ou...
MediaMovelSimples mms = new MediaMovelPonderada(new IndicadorFechamento());

Repare na flexibilidade desse cdigo. O clculo de mdia fica totalmente independente do dado usado e, toda
vez que criarmos um novo indicador, j ganhamos a mdia mvel desse novo indicador de brinde. Vamos
fazer ento nossa classe de mdia receber algum outro Indicador:
public class MediaMovelSimples implements Indicador {
private final Indicador outroIndicador;
public MediaMovelSimples(Indicador outroIndicador) {

Captulo 10 - Aplicando Padres de projeto - Indicadores mais elaborados e o Design Pattern Decorator - Pgina 145

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

this.outroIndicador = outroIndicador;
}
// ... 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; i > posicao - 3; i--) {
soma += outroIndicador.calcula(i, serie);
}
return soma / 3;
}

Nossa classe MediaMovelSimples recebe um outro indicador que modifica um pouco os valores de sada ele complementa o algoritmo da mdia! Passar um objeto que modifica um pouco o comportamento do seu
uma soluo clssica para ganhar em flexibilidade e, como muitas solues clssicas, ganhou um nome
nos design patterns de Decorator.

Tambm um composite!
Note que, agora, nossa MediaMovelSimples um Indicador e tambm tem um outro Indicador.
J vimos antes outro tipo que se comporta da mesma forma, voc se lembra?
Assim como os componentes do Swing, nossa MediaMovelSimples se tornou tambm um exemplo de Composite.

10.5

Exerccios: Indicadores mais espertos e o Design Pattern


Decorator

1) Faremos uma grande mudana agora: nossas mdias devem receber como argumento um outro 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 preferncia:
a) Comece a escrever o nome da classe e mande autocompletar: Med<ctrl + espao>;
b) Use o criador automtico de construtores: ctrl + 3 Constructor.
Captulo 10 - Aplicando Padres de projeto - Exerccios: Indicadores mais espertos e o Design Pattern Decorator - Pgina 146

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

2) Modifique o construtor usando o atalho alt + shift + C para adicionar o parmetro do tipo Indicador
chamado outroIndicador e com valor padro new IndicadorFechamento().

Agora, com o cursor sobre o parmetro outroIndicador, faa ctrl + 1 e guarde esse valor em um novo
atributo, selecionando assign parameter to new field.
3) 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; i > posicao - 3; i--) {
soma += outroIndicador.calcula(i, serie);
}
return soma / 3;
}

4) Lembre que toda refatorao deve ser acompanhada dos testes correspondentes. Mas ao usar a refatorao
do Eclipse no construtor da nossa classe MediaMovelSimples, a IDE evitou que quebrssemos os testes j
passando o IndicadorFechamento como parmetro padro para todos eles!
Agora, rode os testes novamente e tudo deve continuar se comportando exatamente como antes da refatorao. Caso contrrio, nossa refatorao no foi bem sucedida e seria bom reverter o processo todo.
5) Modifique 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 fizemos com a MediaMovelSimples.

Captulo 10 - Aplicando Padres de projeto - Exerccios: Indicadores mais espertos e o Design Pattern Decorator - Pgina 147

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

6) (opcional)Faa um teste de unidade na classe MediaMovelSimplesTest que use receba um


IndicadorAbertura vez do de fechamento. Faa tambm para quaisquer outros indicadores que
voc crie.

Captulo 10 - Aplicando Padres de projeto - Exerccios: Indicadores mais espertos e o Design Pattern Decorator - Pgina 148

Captulo 11

A API de Reflection
At agora, ao acessar a aplicao pelo navegador, o grfico e a tabela de negociaes sero gerados automaticamente. No h nenhuma forma de personalizar o grfico, como por exemplo a opo de ver apenas um
dos indicadores por vez.
Vamos melhorar a interface e adicionar um formulrio que oferece para o usurio as seguintes opes:
Tipo de indicador (abertura ou fechamento)
Tipo de mdia (mvel simples ou mvel ponderada)

11.1

Escolhendo qual grfico plotar

Nesse momento, apesar de conseguirmos compor diversos indicadores e plotar seus grficos, o Argentum
apenas consegue mostrar o grfico da Mdia Mvel Simples do Fechamento. No entanto, ns j preparamos
diversos outros indicadores e poderamos plotar todos eles naquele mesmo grfico. O resultado disso seria
algo assim:

H informao demais nesse grfico e isso o torna menos til. Seria muito mais interessante se o usurio
pudesse escolher quais indicadores ele quer ver e mandar plotar apenas estes no grfico. Uma das formas

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

possveis para isso seria colocarmos as opes para que ele decida e um boto que disparar a gerao do
grfico. Nossa tela ficar parecida com:

Parece bom? Felizmente, colocar tais botes na tela uma tarefa bastante simples! Como diversas aplicaes
tm a necessidade desses botes, esses componentes j existem e us-los ser bem semelhante ao que j
vnhamos fazendo desde nossos primeiros exemplos com JSF.
Tais componentes so, inclusive, to comuns que existem tanto na implementao do JSF quanto no Primefaces e nas outras bibliotecas semelhantes. Esse um dilema comum quando trabalhamos com JSF: usar a
implementao padro ou a do Primefaces.
Essa escolha usualmente cai para a utilizao da biblioteca, j que seus componentes j vm com um estilo
uniforme e, como j vimos antes, frequentemente adicionam funcionalidades interessantes aos componentes.
Sabendo disso, daremos preferncia para os componentes do Primefaces, embora isso traga alguns efeitos
colaterais. Fique atento s particularidades em destaque no decorrer desse captulo.

Componentes para escolher o grfico


Para que o usurio escolha qual grfico ele quer plotar, ser necessrio que ele consiga interagir com a tela,
isto , precisamos de um componente de input de dados. H diversos deles disponveis no Primefaces: http:
//www.primefaces.org/showcase/ui/home.jsf
Como temos opes pr-definidas para as mdias e para os indicadores bsicos, usaremos um componente
de select. Voc pode descobr-los at de dentro do Eclipse, no index.xhtml: basta abrir a tag <p:select e
usar o ctrl + espao!
Para replicar a tela do screenshot acima, usaremos o componente com cara de boto que permite escolher
apenas uma opo, o p:selectOneButton. E, como qualquer select, precisamos tambm indicar quais so
os itens que serviro de opo.
<h:outputLabel value="Media Mvel: "/>
<p:selectOneButton value="#{argentumBean.nomeMedia}">
<f:selectItem itemLabel="Simples" itemValue="MediaMovelSimples" />
<f:selectItem itemLabel="Ponderada" itemValue="MediaMovelPonderada" />
</p:selectOneButton>
Captulo 11 - A API de Reflection - Escolhendo qual grfico plotar - Pgina 150

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

Marcamos, atravs do value, que esse componente est ligado ao atributo nomeMedia da classe ArgentumBean.
Quando o usurio escolher o boto desejado, o itemValue ser atribudo a esse atributo.
Semelhantemente, queremos outra listagem de indicadores possveis, mas agora com nossos indicadores
bsicos:
<h:outputLabel value="Indicador base: "/>
<p:selectOneButton value="#{argentumBean.indicadorBase}">
<f:selectItem itemLabel="Abertura" itemValue="IndicadorAbertura" />
<f:selectItem itemLabel="Fechamento" itemValue="IndicadorFechamento" />
</p:selectOneButton>

Finalmente, tambm precisamos que o usurio indique que terminou de escolher e mande efetivamente gerar
tal grfico. E a forma mais natural de fazer isso atravs de um boto com uma determinada ao -- em
outras palavras, a action desse componente indica o mtodo que ser chamado quando o usurio apertar o
boto:
<p:commandButton value="Gerar grfico"
action="#{argentumBean.geraGrafico}"/>

Note que esse boto do Primefaces muito mais atraente do que o boto padro que usamos no
olaMundo.xhtml. A folha de estilos do Primefaces realmente superior, mas no s isso que muda!

Ponto de ateno: Primefaces e o AJAX


Os botes do Primefaces no so apenas bonitos. Eles tambm trabalham por padro com chamadas via AJAX, em vez de recarregar a tela toda. Isso interessante quando temos telas complexas, com diversas informaes e o apertar de um boto altera somente um pedao dela.
Contudo, exatamente porque nossa chamada ser executada via AJAX, no haver navegao e
os outros componentes da tela no sero recarregados, a menos que explicitamente indiquemos
que tal boto deve recarregar um componente.
No nosso caso, queremos que apertar boto Gerar grfico regere o modelo do grfico e recarregue tal componente na tela, ento ainda necessrio alterar o p:commandButton para que ele atualize o grfico. Para isso,
precisamos indicar ao boto que ele ser tambm responsvel por atualizar o componente do grfico. Para
ligar um componente ao outro, usaremos um id.
<p:commandButton value="Gerar grfico" update=":grafico"
action="#{argentumBean.geraGrafico}"/>

Note o : (dois pontos). Isso indica para o boto que ele partir da tag raiz da pgina procurando algum
componente com id grafico. E, para que isso funcione, tambm necessrio que o componente do grfico
tenha tal id.
Captulo 11 - A API de Reflection - Escolhendo qual grfico plotar - Pgina 151

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

<p:lineChart value="#{argentumBean.modeloGrafico}" id="grafico"


legendPosition="w" title="Indicadores"/>

Lembre-se tambm que sempre que temos botes, precisamos que eles estejam dentro de um componente
h:form. Fora deste componente, os botes no funcionam. Outro detalhe aqui que, por padro, o Primefaces coloca cada label, select e boto em uma linha. Esse comportamento timo para formulrios mais
padro, mas se quisermos mostrar tudo em uma linha s ainda podemos utilizar um panelGrid com 5 colunas
para acomodar os 5 componentes desse menu.
<h:form>
<h:panelGrid columns="5">
<h:outputLabel value="Media Mvel: "/>
<p:selectOneButton value="#{argentumBean.nomeMedia}">
<f:selectItem itemLabel="Simples" itemValue="MediaMovelSimples" />
<f:selectItem itemLabel="Ponderada" itemValue="MediaMovelPonderada" />
</p:selectOneButton>
<h:outputLabel value="Indicador base: "/>
<p:selectOneButton value="#{argentumBean.nomeIndicadorBase}">
<f:selectItem itemLabel="Abertura" itemValue="IndicadorAbertura" />
<f:selectItem itemLabel="Fechamento" itemValue="IndicadorFechamento"/>
</p:selectOneButton>
<p:commandButton value="Gerar grfico" update=":grafico"
action="#{argentumBean.geraGrafico}"/>
</h:panelGrid>
</h:form>

E o ManagedBean?
Semelhantemente proposta do JSF, focamos apenas nos novos componentes e todas as alteraes propostas
nesse captulo esto limitadas a alteraes no index.xhtml.
Se repararmos bem, contudo, os novos componentes exigiro mudanas considerveis ao ArgentumBean:
Atributo nomeMedia, seu getter e setter;
Atributo nomeIndicadorBase, seu getter e setter;
Mtodo geraGrafico, que ser o novo responsvel pelo modelo do grfico.
Faremos tais alteraes no decorrer do prximo exerccio.

Captulo 11 - A API de Reflection - Escolhendo qual grfico plotar - Pgina 152

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

11.2

Exerccios: permitindo que o usurio escolha o grfico

1) No index.html e logo aps a tag <h:body>, adicione o formulrio que permitir que o usurio escolha
qual indicador ele gostaria de ver plotado e tambm o panelGrid que far com que seu formulrio ocupe
apenas uma linha.
<h:form>
<h:panelGrid columns="5">
</h:panelGrid>
</h:form>

2) Agora, dentro do h:panelGrid, precisamos colocar nossos selects das mdias e dos indicadores bsicos,
juntamente com as respectivas legendas dos campos:
<h:outputLabel value="Media Mvel: "/>
<p:selectOneButton value="#{argentumBean.nomeMedia}">
<f:selectItem itemLabel="Simples" itemValue="MediaMovelSimples" />
<f:selectItem itemLabel="Ponderada" itemValue="MediaMovelPonderada" />
</p:selectOneButton>
<h:outputLabel value="Indicador base: "/>
<p:selectOneButton value="#{argentumBean.nomeIndicadorBase}">
<f:selectItem itemLabel="Abertura" itemValue="IndicadorAbertura" />
<f:selectItem itemLabel="Fechamento" itemValue="IndicadorFechamento"/>
</p:selectOneButton>

3) Suba o TomCat agora e verifique que recebemos uma ServletException. Ela nos informa que ainda no
temos a propriedade nomeMedia no ArgentumBean. Precisamos criar os atributos necessrios para que
esses componentes funcionem corretamente.
Na classe ArgentumBean crie os atributos nomeMedia e nomeIndicadorBase e seus respectivos getters e
setters. Lembre-se de usar o ctrl + 3 getter para isso!
@ManagedBean
@ViewScoped
public class ArgentumBean {
private
private
private
private

List<Negociacao> negociacoes;
ChartModel modeloGrafico;
String nomeMedia;
String nomeIndicadorBase;

// agora crie os getters e setters com o ctrl+3

Ateno: se seu ArgentumBean no estiver anotado com @ViewScoped, anote-o. A explicao dos escopos
est no exerccio opcional de paginao e ordenao, no captulo de Introduo ao JSF.
Captulo 11 - A API de Reflection - Exerccios: permitindo que o usurio escolha o grfico - Pgina 153

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

4) Reinicie o TomCat e veja os selects na tela. Falta pouco! De volta ao index.xhtml coloque o boto no
mesmo formulrio, logo aps os selects. Coloque tambm o id=grafico no componente p:lineChart
que j existe, para fazer com que o clique no boto atualize tambm esse componente.
<p:commandButton value="Gerar grfico" update=":grafico"
action="#{argentumBean.geraGrafico}"/>
</h:panelGrid>
</h:form>
<p:lineChart value="#{argentumBean.modeloGrafico}" id="grafico"
legendPosition="w" title="Indicadores"/>

5) J possvel ver a tela, mas ao clicar no boto de gerar o grfico, nada acontece. Na verdade, no Console do
Eclipse possvel ver que uma exceo foi lanada porque o mtodo que o boto chama, o geraGrafico,
ainda no existe.
Esse mtodo ter que, a partir da lista de negociaes, criar as Candles, a Srie Temporal, mandar plotar
um indicador ao grfico e disponibilizar o modelo atualizado para o grfico. Note, no entanto, que nosso
construtor j faz todo esse trabalho!

Basta fazermos uma simples refatorao Extract method nessas linhas! Selecione tais linhas do construtor
da ArgentumBean e use ctrl + 3 extract method indicando que o novo mtodo deve se chamar geraGrafico
e deve ser pblico.

Captulo 11 - A API de Reflection - Exerccios: permitindo que o usurio escolha o grfico - Pgina 154

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

6) Finalmente, para verificarmos que estamos recebendo informaes corretas sobre qual indicador plotar
no momento que o mtodo geraGrafico chamado, vamos imprimir essas informaes no console com
um simples syso.
Altere o recm-criado geraGrafico, adicionando o syso:
public void geraGrafico() {
System.out.println("PLOTANDO: " + nomeMedia + " de " + nomeIndicadorBase);
List<Candle> candles = new CandleFactory().constroiCandles(negociacoes);
//...

7) Reinicie o TomCat e volte a acessar a URL do projeto: http://localhost:8080/fj22-argentum-web/index.xhtml


Teste os botes e mande gerar o grfico. Ateno! O grfico ainda no ser gerado corretamente! Falta
implementarmos essa parte no bean. Olhando no Console do Eclipse, contudo, note que nosso syso j
mostra que os atributos que escolhero qual indicador plotar j foi escolhido corretamente!
Faa o teste para algumas combinaes de mdia e indicador, observando o console.

11.3

Montando os indicadores dinamicamente

No nosso formulrio criamos dois select buttons, um para a mdia e outro para o indicador base. Ns at j
verificamos que essas informaes esto sendo preenchidas corretamente quando o usurio clica no boto.
No entanto, ainda no estamos usando essa informao para plotar o indicador escolhido pelo usurio ainda estamos plotando a mdia mvel simples do fechamento em todos os casos. Essa informao est
hard-coded no geraGrafico
public void geraGrafico() {
System.out.println("PLOTANDO: " + nomeMedia + " de " + nomeIndicadorBase);
List<Candle> candles = new CandleFactory().constroiCandles(negociacoes);
SerieTemporal serie = new SerieTemporal(candles);
GeradorModeloGrafico geradorGrafico =
new GeradorModeloGrafico(serie, 2, serie.getUltimaPosicao());
geradorGrafico.plotaIndicador(
new MediaMovelSimples(new IndicadorFechamento()));
this.modeloGrafico = geradorGrafico.getModeloGrafico();
}

Note que as informaes de qual indicador o usurio quer plotar j esto preenchidas nos atributos nomeMedia
e nomeIndicadorBase, mas esses atributos so meramente Strings passadas pelo componente de select.
Poderamos, ento, usar um conjunto de if/else para decidir qual indicador usar:

Captulo 11 - A API de Reflection - Montando os indicadores dinamicamente - Pgina 155

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

private Indicador defineIndicador() {


if ("MediaMovelSimples".equals(nomeMedia)) {
if ("IndicadorAbertura".equals(nomeIndicadorBase))
return new MediaMovelSimples(new IndicadorAbertura());
if ("IndicadorFechamento".equals(nomeIndicadorBase))
return new MediaMovelSimples(new IndicadorFechamento());
} else if ("MediaMovelPonderada".equals(nomeMedia)) {
// varios outros ifs

fcil ver que essa uma soluo extremamente deselegante. Nesse pequeno trecho escrevemos quatro ifs
e isso um sinal de mal design. Pense agora no teste para esse trecho de cdigo: esse mtodo sozinho tem
quatro caminhos possveis de se percorrer. Esse nmero tambm chamado de complexidade ciclomtica.
Quatro no um nmero ruim, mas note que, ao adicionar um novo indicador bsico ou uma nova
mdia, esse nmero aumentar de forma multiplicativa. O nmero de caminhos ser sempre igual
quantidadeDeMedias * quantidadeDeIndicadoresBase.

Complexidade Ciclomtica
Essa mtrica expe o nmero de caminhos diferentes que uma execuo pode percorrer em um
mtodo. O problema de uma complexidade ciclomtica alta que: quanto maior esse nmero
for, mais testes sero necessrios para garantir o funcionamento esperado.
Para maiores detalhes sobre essa mtrica consulte no blog da caelum esse artigo: http://blog.
caelum.com.br/medindo-a-complexidade-do-seu-codigo/

Cada vez mais indicadores


Por vantagem competitiva, nosso cliente pode pedir mais indicadores (mnimo e mximo) e outras mdias
(exponencial e adaptativa). sensvel que o cdigo nunca parar de crescer e estar sempre sujeito a alterao.
Embora seja aceitvel para um nmero bem pequeno de indicadores, conforme nosso sistema evolui fundamental que encontremos um jeito melhor de conseguir um objeto de Indicador a partir das Strings que j
temos.
Nesse caso a API de reflection cai com uma luva. Com ela podemos escrever o cdigo que cria objetos ou
chamar mtodos sem conhecer as classes antecipadamente, justamente o que precisamos para montar as
indicadores.

11.4

Introduo a Reflection

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,
Captulo 11 - A API de Reflection - Introduo a Reflection - Pgina 156

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

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 situaes em que precisamos de caractersticas dinmicas. Por exemplo, imagine permitir que, dado um nome
de mtodo que o usurio passar, ns o invocaremos em um objeto. Ou ainda, que, ao recebermos o nome de
uma classe enquanto executando o programa, possamos criar um objeto dela!
Nas prximas sees, voc vai conhecer um pouco desse recurso avanado e muito poderoso que, embora
possua diversas qualidades, aumenta bastante a complexidade do nosso cdigo e por essa razo deve ser
usado de forma sensata.

11.5

Por que reflection?

Um aluno que j cursou o FJ-21 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(...);

O XStream foi construdo para funcionar com qualquer tipo de XML e objeto. Com um pouco de ponderao
fica bvio que no h um new para cada objeto possvel e imaginvel dentro do cdigo do XStream. Mas
como ele consegue instanciar um objeto da minha classe e popular os atributos, tudo sem precisar ter new
Negociacao() escrito dentro dele?
O java.lang.reflect um pacote do Java que permite criar instncias e chamadas em tempo de execuo,
sem precisar conhecer as classes e objetos envolvidos no momento em que escrevemos nosso cdigo (tempo
de compilao). Esse dinamismo necessrio para resolvermos determinadas tarefas que s descobrimos
serem necessrias ao receber dados, isto , em tempo de execuo.
De volta ao exemplo do XStream, ele s descobre o nome da nossa classe Negociacao quando rodamos o
programa e selecionamos o XML a ser lido. Enquanto escreviam essa biblioteca, os desenvolvedores do
XStream no tinham a menor ideia de que um dia o usaramos com a classe Negociacao.
Apenas para citar algumas possibilidades com reflection:
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 especifico baseado no tipo de atributo
Invocar mtodos dinamicamente baseado no nome do mtodo como String;
Descobrir se determinados pedaos do cdigo tm annotations.
Captulo 11 - A API de Reflection - Por que reflection? - Pgina 157

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

11.6

Constructor, Field e Method

O ponto de partida da reflection 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;

Ou ainda, se tivermos o caminho completo da classe, conseguimos recuperar tal classe at atravs de uma
String:
Class classe = Class.forName("br.com.caelum.argentum.model.Negociacao");

Java 5 e Generics
A partir do Java 5, a classe Class tipada e recebe o tipo da classe que estamos trabalhando. Isso
melhora alguns mtodos, que antes recebiam Object e agora trabalham com um tipo T qualquer,
parametrizado pela classe.
A partir de um Class podemos listar, por exemplo, os nomes e valores dos seus atributos:
Class<Negociacao> classe = Negociacao.class;
for (Field atributo : classe.getDeclaredFields()) {
System.out.println(atributo.getName());
}

A sada ser:
preco
quantidade
data

Captulo 11 - A API de Reflection - Constructor, Field e Method - Pgina 158

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

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()));
}

Imprime o tipo do parmetro do nico construtor:


interface br.com.caelum.argentum.indicadores.Indicador

possvel fazer muito mais. Investigue a API de reflection usando ctrl + espao a partir das classes Method,
Constructor e Fields no Eclipse e pelo JavaDoc.

11.7

Melhorando nosso ArgentumBean

J temos os conhecimentos necessrios para melhorar nosso mtodo defineIndicador(), que ser chamado
pelo geraGrafico. A primeira necessidade 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.
Isso

se

torna

bastante

fcil

se

convencionarmos que todo indicador estar


br.com.caelum.argentum.indicadores. Assim, instanciar o indicador base muito simples.

no

pacote

String pacote = "br.com.caelum.argentum.indicadores.";


Class<?> classeIndicadorBase = Class.forName(pacote + nomeIndicadorBase);
Indicador indicadorBase = (Indicador) classeIndicadorBase.newInstance();
Captulo 11 - A API de Reflection - Melhorando nosso ArgentumBean - Pgina 159

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

Para a mdia o trabalho um pouco maior, j que precisamos passar um Indicador como parmetro na
instanciao do objeto. Isso pode ser at mais complexo se houver outros indicadores na classe em questo.
Nesse caso, no basta fazer a chamada ao mtodo newInstance(), j que este s consegue instanciar objetos
quando o construtor padro existe.
Por outro lado, j sabemos como descobrir o construtor a partir de um Class. A boa notcia que existe
como criarmos uma instncia a partir de um Constructor, pelo mesmo mtodo newInstance() que passa a
receber parmetros.
Veja o cdigo:
Class<?> classeMedia = Class.forName(pacote + nomeMedia);
Constructor<?> construtorMedia = classeMedia.getConstructor(Indicador.class);
Indicador indicador = (Indicador) construtorMedia.newInstance(indicadorBase);

Repare que esse cdigo funciona com qualquer indicador ou mdia que siga a conveno de passar o nome
da classe no itemValue do select e a conveno de pacote.
Se errarmos alguma dessas informaes, no entanto, diversos erros podem acontecer e por isso que
o cdigo acima pode lanar diversas excees: InstantiationException, IllegalAccessException,
ClassNotFoundException, NoSuchMethodException, InvocationTargetException.
Como essas excees so todas checked, seria necessrio declar-las todas com um throws na assinatura do
mtodo defineIndicador, o que pode no ser desejvel. Podemos, ento, apelar para um try/catch que
encapsule tais excees em uma unchecked para que ela continue sendo lanada, mas no suje a assinatura
do mtodo com as tantas excees. Essa uma prtica um tanto comum, hoje em dia, e linguagens mais
novas chegam a nem ter mais as checked exceptions.
Nosso mtodo, portanto, ficar assim:
private Indicador defineIndicador() {
try {
String pacote = "br.com.caelum.argentum.indicadores.";
// instancia indicador base
// instancia a mdia, passando o indicador base
return indicador;
} catch (Exception e) {
throw new RuntimeException(e);
}
}

11.8

Exerccios: indicadores em tempo de execuo

1) Na classe ArgentumBean, ache o mtodo geraGrafico e identifique a linha que plota o indicador. Ela deve
ser algo como:
Captulo 11 - A API de Reflection - Exerccios: indicadores em tempo de execuo - Pgina 160

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

geradorGrafico.plotaIndicador(new MediaMovelSimples(new IndicadorFechamento()));

Troque o parmetro do plotaIndicador por uma chamada a um novo mtodo defineIndicador():


geradorGrafico.plotaIndicador(defineIndicador());

2) Use o ctrl + 1 e escolha a opo Create method defineIndicador. O Eclipse gerar o esqueleto do mtodo
para ns e, agora, falta preench-lo.
private Indicador defineIndicador() {
String pacote = "br.com.caelum.argentum.indicadores.";
Class<?> classeIndicadorBase = Class.forName(pacote + nomeIndicadorBase);
Indicador indicadorBase = (Indicador) classeIndicadorBase.newInstance();
Class<?> classeMedia = Class.forName(pacote + nomeMedia);
Constructor<?> construtorMedia = classeMedia.getConstructor(Indicador.class);
Indicador indicador = (Indicador) construtorMedia.newInstance(indicadorBase);
return indicador;
}

3) O cdigo acima ainda no compila! As diversas excees que a API de reflection lana ainda precisam
ser tratadas. Com a ajuda do Eclipse, envolva todo esse trecho de cdigo com um try/catch que pega
qualquer Exception e a encapsula em uma RuntimeException.
private Indicador defineIndicador() {
try {
String pacote = "br.com.caelum.argentum.indicadores.";
Class<?> classeIndicadorBase = Class.forName(pacote + nomeIndicadorBase);
Indicador indicadorBase = (Indicador) classeIndicadorBase.newInstance();
Class<?> classeMedia = Class.forName(pacote + nomeMedia);
Constructor<?> construtorMedia = classeMedia.getConstructor(Indicador.class);
Indicador indicador = (Indicador) construtorMedia.newInstance(indicadorBase);
return indicador;
} catch (Exception e) {
throw new RuntimeException(e);
}
}

4) Vamos aproveitar e adicionar um comportamento padro para quando o usurio no tiver escolhido
qual grfico ele quer ainda. Antes mesmo do bloco de try/catch, podemos adicionar o comportamento
padro de, se os indicadores no estiverem escolhidos, devolvemos por padro a Mdia Mvel Simples
do Fechamento.
private Indicador defineIndicador() {
if (nomeIndicadorBase == null || nomeMedia == null)
return new MediaMovelSimples(new IndicadorFechamento());

Captulo 11 - A API de Reflection - Exerccios: indicadores em tempo de execuo - Pgina 161

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

try {
//...

5) Reinicie o TomCat e acesse o Argentum para testar o funcionamento dessa nova modificao no sistema.
Tudo deve estar funcionando!

11.9

Melhorando a orientao a objetos

O design do cdigo do exerccio anterior tem muito espao para melhorias. Note que acabamos colocando
muitas responsabilidades diferentes na classe ArgentumBean - justamente nela, que deveria servir apenas para
prover objetos para os componentes da nossa pgina.
Alm disso, nosso mtodo defineIndicador um mtodo privado na ArgentumBean e isso o torna extremamente difcil de testar.
Podemos, por exemplo, extrair essa lgica de definio do indicador para uma classe completamente
nova, que tivesse essa nica responsabilidade. Assim, nosso mtodo geraGrafico instanciaria um
IndicadorFactory, que devolveria o indicador correto:
public void geraGrafico() {
// outras linhas de cdigo
IndicadorFactory fabrica = new IndicadorFactory(nomeMedia, nomeIndicadorBase);
geradorGrafico.plotaIndicador(fabrica.defineIndicador());
this.modeloGrafico = geradorGrafico.getModeloGrafico();
}

Assim, o mtodo defineIndicador() passar a ser pblico e, portanto, muito mais facilmente testvel e
muito mais coeso - seguindo um dos princpios SOLID: mais especificamente, o princpio da responsabilidade nica

Exerccios Opcionais: refatorao para melhorar a coeso


1) (Opcional) Crie a classe IndicadorFactory e faa com que ela receba no construtor os parmetros
nomeMedia e nomeIndicadorBase. Esses valores so obrigatrios e no sero alterados, portanto eles podem ser final.
2) (Opcional) Traga para essa classe o mtodo defineIndicador, alterando ele para pblico, agora que
ele est em outra classe. Lembre-se, tambm, de arrumar erros de compilao que surgirem na classe
ArgentumBean.
3) (Opcional) Crie testes para a IndicadorFactory. Um desses testes deve verificar o comportamento
quando no passamos o nome de uma das classes. Outro, poderia motivar a melhoria do tratamento
das excees para algo mais descritivo.
Captulo 11 - A API de Reflection - Melhorando a orientao a objetos - Pgina 162

Captulo 12

Apndice Testes de interface com Selenium


Alm da magia negra, h apenas automao e mecanizao
Federico Garcia Lorca

12.1

Introduo ao teste de aceitao

Nos captulos anteriores fizemos uso dos testes de unidade, ser que eles so suficientes 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.
Verificar 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 fica difcil testar a camada de apresentao,
o resultado final. Como testar a compatibilidade entre browsers diferentes de maneira automatizada? Em
geral, como testar se a pgina renderizada tem o resultado desejado?
Para isso ser possvel, existem algumas ferramentas que permitem tal trabalho, simulando a interao de um
usurio com a aplicao. Esse o caso do Selenium que, com a assistncia do JUnit, pode facilitar o trabalho
de escrever tais testes.

12.2

Como funciona?

Para demonstrar como o Selenium funciona, testaremos se a validao do campo titulo funciona corretamente, 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 navegador.
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();

HtmlUnitDriver
H uma outra implementao do WebDriver disponvel que nem precisa abrir um navegador.
Ela se chama HtmlUnitDriver e simula o navegador em memria. Isso muito mais rpido mas
no testa a compatibilidade do navegador fidedignamente:
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 um critrio de busca. A classe 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 12 - Apndice Testes de interface com Selenium - Como funciona? - Pgina 164

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

Agora que temos o elemento, podemos preench-lo com o texto que quisermos atravs do mtodo sendKeys.
Em nosso caso, deixaremos o campo em branco passando uma string vazia:
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 fim, aps o formulrio ter sido submetido, precisamos saber se tudo saiu conforme o planejado, o que
pode ser feito atravs do mtodo esttico assertTrue da classe Assert, que recebe como parmetro um
boolean que indica a presena ou no do texto procurado pelo mtodo contains:
Captulo 12 - Apndice Testes de interface com Selenium - Como funciona? - Pgina 165

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 verificar 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();

12.3

Trabalhando com diversos testes de aceitao

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 12 - Apndice Testes de interface com Selenium - Trabalhando com diversos testes de aceitao - Pgina 166

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();
}

12.4

Para saber mais: Configurando o Selenium em casa

Caso voc esteja fazendo esse passo de casa, preciso baixar algumas JARs para o funcionamento dessa
aplicao, usaremos as seguintes verses:
commons-exec-1.1.jar
commons-logging-1.1.1.jar
guava-14.0.jar
httpclient-4.2.1.jar
httpcore-4.2.1.jar
json-20080701.jar
selenium-java-2.31.0.jar
Para mais informaes, voc pode consultar o site http://docs.seleniumhq.org/

12.5

Exerccios: Teste com Selenium

Vamos criar nosso primeiro teste com Selenium:


1) Antes de tudo vamos colocar as jars do Selenium no nosso projeto, elas se encontram na pasta
Desktop/caelum/22/selenium-jars/:

Captulo 12 - Apndice Testes de interface com Selenium - Para saber mais: Configurando o Selenium em casa - Pgina 167

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 12 - Apndice Testes de interface com Selenium - Exerccios: Teste com Selenium - Pgina 168

Material do Treinamento Laboratrio Java com Testes, JSF, Web Services e Design Patterns

2) Crie a classe usando ctrl + N Class, chamada GeraGraficoTest no source folder src/test/java e dentro do
pacote br.com.caelum.argentum.aceitacao:
3) A classe ter dois atributos. O primeiro com a URL da pgina que queremos testar e o segundo o WebDriver, 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;
}

4) 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() {
}
}

5) Usaremos o WebDriver para abrir uma nova janela do Firefox e acessar a URL do projeto, e usaremos o
mtodo driver.close() para fechar a janela
public class GeraGraficoTest {

Captulo 12 - Apndice Testes de interface com Selenium - Exerccios: Teste com Selenium - Pgina 169

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();
}
}

6) 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();
}
}

7) Vemos que usamos driver = new FirefoxDriver() para abrir uma janela (um WebDriver) do navegador, 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 sepaCaptulo 12 - Apndice Testes de interface com Selenium - Exerccios: Teste com Selenium - Pgina 170

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 12 - Apndice Testes de interface com Selenium - Exerccios: Teste com Selenium - Pgina 171

ndice Remissivo
anotaes, 37
Calendar, 13
Candlestick, 5, 8
datas, 13
Design patterns, 141
Escopos do JSF, 107
Factory pattern, 13
final, 9
h:form, 108
JUnit, 35
Negociao, 8
Reflection, 157
static import, 51
Tail, 6
TDD, 65
Test driven design, 65
testes de unidade, 34
testes unitrios, 34

172

Das könnte Ihnen auch gefallen