Preview only show first 10 pages with watermark. For full document please download

Java Magazine - Edição 038

Descrição: revista sobre java

   EMBED


Share

Transcript

 Relatórios • Eclipse • Interfaces gráficas • JGoodies • Struts • AJAX A Revista da Comunidade Java Brasileira AJAX fácil com GWT Usando o Google Web Toolkit para a criação produtiva de aplicações AJAX Google Search API Fazendo pesquisas no Google Fazendo a partir de suas aplicações Java Edição 38 - Ano V - R$ 9,90 Conversores Conv ersores no Struts S truts Estenda o framework para garantir a conversão e a formatação de dados Datas com Swing GUIs com Qualidade Boas práticas para a criação de interfaces gráficas e uma introdução ao JGoodies Usando componentes para manipulação de datas e calendários em aplicações desktop Eclipse Callisto Conheça o novo projeto do Eclipse.org que simplifica a vida do desenvolvedor Relatórios & Gráficos Usando o Eclipse BIRT para criar relatórios completos no Eclipse, passo a passo  jm38.indb 1 Agrupamentos, totalizações e gráficos com  JasperReports e iReport 17/7/2006 14:07:33  jm38.indb 2 17/7/2006 14:07:45  jm38.indb 2 17/7/2006 14:07:45 Conteúdo EXPLORANDO O CD PRODUTOS ORACLE Passos para instalação do JDeveloper 10g, Oracle Containers for J2EE e Oracle Database Express Edition, incluídos no CD-ROM. 10     s     e       õ     ç     e       S CAFEÍNA LEONARDO  GALVÃO Aprendendo programação OO com Greenfoot; Shale e Tapestry top-level; novos Groovy, Geronimo e WTK 08 BUSCAS COM A GOOGLE SEARCH API JULIO  FAERMAN Como usar a API do Google para realizar pesquisas na web, fazer correções ortográficas e obter páginas do cache     e       l     g     o     o       G 60 AJAX FÁCIL COM GOOGLE WEB TOOLKIT DOUGLAS JOSÉ RODRIGUES Conheça as tecnologias e ferramentas do Google que tornam extremamente produtivo o desenvolvimento de aplicações AJAX 64 RELATÓRIOS E GRÁFICOS NO ECLIPSE OSVALDO PINALI  DOEDERLEIN Usando o Eclipse BIRT para criar relatórios completos e gráficos comerciais dentro do IDE mais popular do mercado     a     p     a       C 22 MAIS RELATÓRIOS PASSO A PASSO ANA ABRANTES E YARA SENGER Definindo agrupamentos, calculando totais em vários níveis e criando gráficos de resumo – com JasperReports e iReport 36 DATAS NO DESKTOP FERNANDO LOZANO     p     o      t       k     s     e       D       b     e       W     e     s     p       i       l     c       E  jm38.indb 3 Manipulação de datas em aplicações Swing usando componentes de calendário do projeto NachoCalendar, e conceitos sobre JavaBeans e MVC 12 GUI S COM QUALIDADE, PARTE  1 HUGO  VIDAL  TEIXEIRA Técnicas e boas práticas para o projeto de interfaces gráficas e implementação com a API JGoodies Forms CONVERSÃO E FORMATAÇÃO NO STRUTS ARI DIAS NETO Estendendo o framework para definir conversores personalizados e garantir a formatação de números e datas 44 68 PROJETO CALLISTO FERNANDO LOZANO Detalhes sobre o novo projeto da Fundação Eclipse, que simplifica a instalação de dez plug-ins fundamentais do Eclipse.org 56 17/7/2006 14:09:05 Esp Ano V • Edição 38 • 2006 • ISSN 1676-8361 Direção Diretor Editorial Leonardo Galvão Diretor de Marketing Gladstone Matos Diretor Comercial Casseano Filho Edição Publisher e Editor-Chefe Leonardo Galvão ( [email protected] ) Editores-Adjuntos Fernando Lozano ( [email protected] ) Osvaldo Doederlein ( [email protected] ) Colaboraram nesta edição Ana Abrantes, Ari Dias Neto, Douglas José Rodrigues, Fernando Lozano, Hugo Vidal Teixeira, Julio Faerman, Leonardo Galvão, Osvaldo Doederlein, Yara Senger Arte Diretor de Arte Tarcísio Bannwart ( [email protected] ) Diagramação Jaime Peters Junior, Lais Pancote e Tersis Zonato Ilustrações Felipe Machado e Francisco Peixoto Produção Gerência de Marketing Kaline Dolabella Distribuição Fernando Chinaglia Distribuidora S.A. Rua Teodoro da Silva, 907, Grajaú - RJ CEP 20563-900, (21) 3879-7766 - (21) 2577-6362 Atendimento ao leitor A DevMedia possui uma Central de Atendimento on-line, onde você pode tirar suas dúvidas sobre serviços, enviar críticas e sugestões e falar com um de nossos atendentes.Através da nossa central também é possível alterar dados cadastrais, consultar o status de assinaturas e conferir a data de envio de suas revistas.Acesse www.devmedia.com.br/central, ou se preferir entre em contato conosco através do telefone 21 2283-9012. Edições anteriores Adquira as edições anteriores da revista Java Magazine ou de qualquer outra publicação do Grupo DevMedia de forma prática e segura, em www.devmedia.com.br/anteriores. Publicidade  [email protected] , 21 2213-0940 Anúncios – Anunciando nas publicações e nos sites do Grupo DevMedia, você divulga sua marca ou produto para mais de 100 mil desenvolvedores de todo o Brasil, em mais de 200 cidades.Solicite nossos Media Kits, com detalhes sobre preços e formatos de anúncios. Reprints Editoriais – Se foi publicado na Java Magazine um artigo que possa alavancar as suas vendas, multiplique essa oportunidade! Solicite a reimpressão da matéria junto com a capa da edição em que saiu, e distribua esse reprint personalizado entre seus clientes. Encarte de CDs – Faça como nossos maiores anunciantes.Encarte um CD com uma amostra de seus produtos na Java Magazine e atinja um público segmentado e formador de opinião. Realização A té poucos anos atrás, o suporte a relatórios em Java se encontrava muito aquém do oferecido em outras plataformas. Mas a tecnologia evoluiu muito, e hoje nos deparamos com a situação oposta: há diversas opções de qualidade e até mesmo dificuldade para escolher a melhor alternativa para cada caso. Esta edição traz dois artigos com enfoque na criação de relatórios. Um tutorial completo com diversos exemplos apresenta e explora o Eclipse BIRT, um conjunto de ferramentas que est ende o IDE Eclipse oferecendo uma solução integrada para a criação de gráficos e relatórios. O segundo artigo destacado volta-se ao par de ferramentas iReport/JavaReports, mostrando como criar totalizações, agrupamentos e gráficos. O texto demonstra recursos mais avançados dessas ferramentas, tratando de necessidades comuns em relatórios não-triviais. Freqüentemente dizemos aqui que a tecnologia Java está ganhando força no segmento de aplicações desktop. Esse movimento continua firme, com várias lacunas sendo preenchidas por ferramentas e APIs que não param de melhorar. São exemplos disso os projetos do JGoodies: há desde look-and-feels bem projetados até soluções completas de binding, além de um popular gerenciador de layouts incluído na API JGoodies Forms. Esta API é o assunto de um artigo sobre criação de GUIs, que também trata de técnicas fundamentais para o projeto de interfaces gráficas, passando gradualmente da teoria à prática. Ainda no desktop, você verá como incrementar suas aplicações Swing com os componentes NachoCalendar, que simplificam a entrada de datas, são muito configuráveis e podem dar um toque especial e profissional às suas aplicações desktop. O artigo apresenta detalhes sobre os componentes, e como fazer a instalação no Eclipse e no NetBeans. Discute também questões importantes no desenvolvimento para o ambiente desktop, como características dos JavaBeans e o modelo MVC no Swing. Na edição anterior, o artigo “10 Mais do Eclipse 3.2” colocou na primeira posição o Projeto Callisto, uma importante iniciativa que resolve problemas comuns de instalação e versionamento no Eclipse. Nesta edição são mostrados mais deta lhes sobre o projeto, incluindo o processo de instalação e possíveis problemas e soluções. Temos ainda um artigo que explica como estender o Struts, criando e registrando conversores para processar a entrada de dados e garanti r uma formatação apropriada. Além de conhecer o uso de converters no framework, você aprende técnicas que permitem mudar o funcionamento interno do Struts e resolver problemas sutis. As tecnologias do Google aparecem aqui em dose dupla, com artigos sobre o Google Web Toolkit e a Google Search API. Lançado durante o JavaOne 2006, o GWT torna possível a criação de aplicações AJAX rapidamente usando código Java. Já a API de pesquisas do Google permite integrar o maior mecanismo de busca mundial às suas aplicações. Apoio Boa leitura! Leonardo Galvão Parceiros  jm38.indb 4 17/7/2006 14:10:00  aço do Leitor Iniciando com Java G ostaria de orientações sobre como iniciar com  Java, sem que o conhecimento de conceitos fundamentais possa passar despercebido e me faltar no futuro. Por onde devo começar?  William de Jesus Rende A tecnologia Java tem várias “sub-áreas”, com cada uma formando um universo de conhecimentos bastante independente. O caminho do aprendizado vai depender muito, portanto, da área em que você pretende se especializar. Porém, alguns conhecimentos e ferramentas serão essenciais em todos os casos. Comece fazendo o download do JDK (Java SE Development Kit) em java.sun.com/javase/downloads. A versão estável mais atual é a 5.0. Somente com o JDK, você já poderá criar aplicações que usam centenas de recursos, desde a leitura e escrita de arquivos, a operações avançadas de rede, passando pelo acesso a bancos de dados relacionais e a criação de interfaces gráficas completas. Você pode passar muito tempo apenas usando o JDK, mas terá mais facilidade de evoluir no aprendizado se tiver instalado também um IDE – um ambiente integrado de desenvolvimento.Todo IDE Java inclui pelo menos um editor de código e um depurador visual (para execução passo a passo de programas, inspeção de variáveis e objetos etc.); a maioria vem também com um editor visual de interfaces e vários recursos auxiliares que facilitam o desenvolvimento, como funcionalidades para manipulação de bancos de dados e integração com ferramentas e servidores. Há uma variedade imensa de IDEs disponíveis. Entre os open source, destacam-se o Eclipse (eclipse.org) e o NetBeans ( netbeans.org). Entre os comerciais, há vários populares, como o JDeveloper da Oracle ( oracle.com/technology/products/jdev ; gratuito para uso comercial e incluído no CD desta edição), o JBuilder da Borland (borland.com/jbuilder ; também com versão gratuita, mas com restrições), o Rational Application Developer da IBM ( ibm. com/software/awdtools/developer/application ), e o IntelliJ IDEA ( jetbrains.com/idea). A maioria dos IDEs  já vem com tudo que é necessário para desenvolver com Java, mas vale a pena ter o JDK à parte, por exemplo, para executar e testar outras aplicações Java (além disso, alguns IDEs, como o NetBeans, exigem que um JDK esteja instalado). Com o JDK e um IDE, você está pronto para desenvolver praticamente qualquer tipo de aplicação Java. O próximo passo é conhecer a linguagem e suas APIs. Há vários sites dedicados a desenvolvedores Java na web, inclusive em português, como  portaljava.com.br e devmedia.com.br/javamagazine. Em inglês, alguns portais se destacam, como  java.net , onjava.com ,  java.com e  javaranch.com. Outra fonte rica de informações são as listas de discussão do grupo de usuários SouJava (cadastrese em soujava.org.br ). Na Java Magazine, já publicamos dezenas de artigos voltados ao desenvolvedor iniciante. A série “Aplicação Java Completa” nas Edições 25, 26 e 27, por exemplo, é citada e usada pelos leitores até hoje e mostra como criar uma aplicação com o NetBeans, do início ao fim. Temos ainda artigos identificados como “Primeiros Passos” em várias edições, e textos sobre várias tecnologias importantes do Java, como Swing, JSP, Servlets e JDBC. Quanto a livros, a série “Head First Java” da O’Reilly,  já traduzida para português (com título "Use a Cabeça"), é excelente para o aprendizado da linguagem. Comece com “Use a Cabeça! Java” (Alta Books), que cobre toda a sintaxe do Java e suas principais APIs, de forma clara, prática e inovadora. Depois de conhecer a sintaxe da linguagem e as APIs fundamentais, abre-se muito o leque de opções de aprendizado. Você poderia, por exemplo, decidir se especializar em programação web. Neste caso, vale a pena conhecer Struts, JSP, JSF, Servlets e AJAX. Já se seu foco é no Java corporativo (enterprise), será importante conhecer EJB, JMS, JNDI e outras tecnologias do Java Enterprise Edition. Em ambos os casos, valerá a pena dominar ferramentas muito usadas, como Ant e Hibernate. Se você pretende desenvolver para celulares, vai precisar conhecer o MIDP e suas muitas APIs, como GCF, LCDUI e MMAPI, e instalar emuladores para os dispositivos alvo. Neste ponto, como se vê, a decisão por qual caminho seguir dependerá muito mais de suas necessidades, e talvez do que o mercado pede em sua região. Edição 38 • Java Magazine 5  jm38.indb 5 17/7/2006 14:10:09 Espaço do Leitor  JDBC Quero parabenizar toda a equipe de Java Magazine pelo excelente trabalho de conteúdo e de visual da revista. Os artigos sobre JDBC nas edições 25 e 26 (“Persistência Turbinada”) são excelentes, e ajudaram a esclarecer muitas questões. Carlos Eduardo Privati Correção na Edição 36  Ao me deparar com um trecho de código na página 22 da Ediçao 36 (artigo “Qualidade Ap licada”), no código referente à escolha de polimorfismo ao  switch , há uma linha desta forma: public class Cliente { public abstract void venda() ; } Essa classe não deveria ser abstrata, e por conseqüência ela não poderia ser instanciada?  Fábio José Fernandes Realmente, houve um erro neste trecho de código: Cliente deveria ser abstract . Já a primeira versão da classe Cliente mostrada no artigo, com um atributo int tipo, é concreta. Quanto a não permitir instanciação, era essa a intenção mesmo. Somente os subtipos concretos como ClienteSimples  e ClienteEspecial  seriam instanciáveis no segundo exemplo. Mas note que isso não impede que a invocação cliente.venda() funcione. Osvaldo Doederlein Pools Em aplicações que processam várias requisições ao mesmo tempo e exigem múltiplas conexões com o banco de dados, fica clara a necessidade de um pool de conexões. Existem várias APIs que  prometem resolver o problema, mas para quem é iniciante na tecnologia fica difícil avaliar o melhor caminho. Vocês podem dar algumas sugestões?  lam conexões ao banco de dados e já incluem o suporte a pools. Somente se não quiser ou não puder usar um servidor Java EE, você precisará se preocupar com pools de conexões (e com outros pools, como os de threads). Se for esse o caso, dê uma olhada no Jakarta Commons DBCP ( jakar ta.ap ache.o rg/comm ons/d bcp ). O DBCP é construído sobre outro projeto do Jakarta, o Commons Pool, que permite construir tipos de pools adicionais. Carlos Eduardo Privati A princípio, você não precisaria se preocupar com isso, pois hoje em dia a grande maioria da s aplicações Java que acessam SGBDs diretamente, se forem construídas segundo um paradigma multicamadas, utilizam servidores Java EE para o back-end (servidor). Em qualquer servidor Java EE, desde um produto open source e limitado à web como o Tomcat até um servidor Java EE completo como o JBoss ou Weblogic,você pode utilizar o recurso de DataSources, que encapsu- Participe! Envie sua dúvida, comentário, correção ou sugestão, com nome completo, cidade e estado, para: [email protected] Cartas publicadas podem ser editadas por motivos de clareza ou extensão. 6  Java Magazine • Edição 38  jm38.indb 6 17/7/2006 14:10:22 Edição 38 • Java Magazine 7  jm38.indb 7 17/7/2006 14:10:27 Cafeín News & Bits Shale é top-level O framework web Shale foi aprovado como um projeto “top-level” da Apache Software Foundation. Com isso torna-se autônomo na ASF, em vez de um subprojeto do Apache Struts. Terá, assim, seu próprio website, listas Geronimo 1.1 A versão 1.1 do servidor Java EE da Apache traz melhorias de performance e muitas correções de bugs. Uma novidade de destaque é o suporte a plug-ins: agora aplicações Geronimo, recursos do servidor e produtos integrados podem ser distribuídos como plug-ins, que são fáceis de instalar, automaticamente fazem o download de dependências e não exigem a reinicialização do servidor. A versão 1.1 inclui ainda recursos e visualizações adicionais no console administrativo, como gráficos de utilização de memória e um wizard para a configuração remota do servidor http. Outra novidade é a distribuição “leve” do servidor, chamada Little-G, que inclui um subconjunto das funcionalidades do Geronimo. O LittleG vem com um gerenciador de transações, um container web (que pode ser Tomcat ou Jetty) e outros elementos do Geronimo, mas não é um servidor Java EE completo. Será útil para usuários que não precisam de todas as facilidades do Java EE e desejam consumo menor de memória e processamento. geronimo. apache.org. de discussão, espaço de repositório e Project Management Committee (PMC). Desenvolvido pelo mesmo criador do Struts, Craig McLanahan, o Shale é um framework focado na tecnologia JavaServer Faces (JSF) e está chegando a seu primeiro release estável. shale.apache.org. Graphics (JSR-226), Payment API (JSR-229), Advanced Multimedia Supplements (JSR234) e Mobile Internationalization API (JSR238). O novo W TK inclui ainda a SNAP Mobile API, da Nokia, que suporta a criação de jogos multiusuário em rede. O WTK 2.5 exige um JDK 1.5 ou superior. Magnolia 3 Graduação do Tapestry Um dos mais populares e maduros sistemas de gerenciamento de conteúdo corporativos (ECM), o Magnolia chega à versão 3.0 com muitos novos recursos. O Magnolia está entre os primeiros a suportar a especificação JSR-170, Java Content Repository, e inclui por padrão o Apache Jackrabbit (uma implementação open source desta JSR). Também são suportadas implementações comerciais do repositório de conteúdo. Criado por uma empresa suíça, a Obinary, o projeto fornece uma interface administrativa baseada na web, uma API extensa e bem documentada e taglibs para a criação de templates. Entre as novidades principais estão recursos para versionamento, suporte a Portlets (JSR168), autenticação integrada ( single sign-on) e uma interface gráfica renovada. O produto tem três edições, sendo a Community Edition open source. As edições Enterprise e Business Process completam as opções, oferecendo suporte profissional e funcionalidades adicionais. Há localizações para 15 idiomas. www.magnolia.info. O Tapestry se graduou para um projeto “top-level” da Apache. Antes subprojeto do projeto Jakarta, este framework web agora tem site próprio e passa a se chamar Apache Tapestry. O Tapestry é voltado à criação de aplicações web dinâmicas em Java. Divide as aplicações em conjuntos de páginas, sendo cada uma construída a partir de componentes. Essa estrutura permite que o framework cuide de tarefas comuns como a construção de URLs, validação de entradas do usuários, armazenamento de estado e localização/internacionalização. No Tapestry o desenvolvedor cria templates em HTML puro e os combina com código Java, e opcionalmente descritores XML. As aplicações lidam com objetos, métodos e propriedades, e não com URLs e requisições/respostas HTTP (que são abstraídos do desenvolvedor). A distribuição do pro jeto inclui mais de 50 componentes, que vão de simples objetos para saída de dados, até componentes complexos como grades e árvores de navegação. Atualmente na versão 4.02, o Tapestry já está com a versão 4.1 adiantada. Este novo release incluirá o dojo, um framework para desenvolvimento com AJAX, que é a base de boa parte das funcionalidades adicionais. Entre os destaques está o novo supor te a JSON (JavaScript Object Notation), widgets, novas anotações e validações no lado do cliente. tapestry.apache.org. Novo WTK Foi lançado o beta do Sun Wireless Toolkit 2.5 para CLDC, o popular kit de ferramentas para desenvolvimento de aplicações Java Micro Edition. Várias novas APIs estão implementadas, entre elas Mobile Service Architecture (JSR-248), Scalable 2D Vector 8  Java Magazine • Edição 38  jm38.indb 8 17/7/2006 14:10:34 a LEONARDO GALVÃO Groovy JSR-6 Está disponível a última versão do Groovy antes do lançamento da primeira versão Release Candidate (RC). Segundo o líder do projeto, Guillaume Laforge, estão sendo realizadas mudanças significativas no coração da implementação, o chamado Meta-Object Protocol, o que atrasou um pouco o lançamento do primeiro RC. Em compensação, as alterações estão permitindo aumentar a performance para níveis próximos do desempenho do Java. As mudanças visíveis na versão JSR-6 são Aprendendo OO com Greenfoot O basicamente correções de bugs (incluindo algumas submetidas pela Oracle), além do novo suporte a stored procedures e um esquema mais simples de carregamento de classes, bem como algumas outras funcionalidades ainda não documentadas. groovy.codehaus.org . um método sobre o mundo que afeta todos os atores; e invocar métodos de atores, por exemplo fazendo-os se mover ou realizar outras operações mais complexas. O Greenfoot está em desenvolvimento há mais de dois anos, tendo inclusive sido apresentado em congressos, mas só recentemente teve liberada sua primeira versão pública. Como o BlueJ, o Greenfoot é gratuito, mas não open source. O site do projeto oferece downloads e a documentação da API, além de um bom tutorial. greenfoot.org . BlueJ, IDE voltado ao aprendizado cas de imagens. Por ser baseado no BlueJ, o de orientação a objetos e Java, tem Greenfoot já vem com editor de código Java, um novo derivado – o Greenfoot depurador e inspetor de objetos, incluindo – que cria um ambiente gráfico bidimen- recursos que permitem atuar sobre o mosional altamente flexível para estimular o delo de objetos criado (os atores e mundos aprendizado de técnicas OO. O novo am- são objetos Java comuns com métodos, biente, assim como o BlueJ, é direcionado atributos e construtores). Pode-se, por a estudantes que estão iniciando a progra- exemplo, criar um novo ator escolhendo um mação, mas se diferencia por privilegiar um de seus construtores em um menu; executar público mais jovem, do nível colegial. Com visual bem cuidado, o Greenfoot se baseia em dois conceitos fundamentais: “mundos” e “atores” que são representados por imagens e têm seus comportamentos programados por código Java. Como mostram os vários exemplos incluídos na distribuição, atores podem ser praticamente qualquer coisa, desde pequenos mamíferos australianos até foguetes, formigas e rochas. Podem também ser programados para interagir com o mundo e com outros atores, permitindo a criação de simulações sofisticadas e até jogos. Através de uma API simples, mas já bastante extensa, o usuário pode definir novos atores e mundos, e programar rapidamente operações comuns em simulações, como deslocamento na tela, verificação de colisões, animações e tro- Greenfoot: Criação de simulações e jogos para aprender Java e orientação a objetos Edição 38 •  Java Magazine 9  jm38.indb 9 17/7/2006 14:10:36 .    o     D     d     C O    n   o    a    r    o     l    p    x     E CD encartado nesta edição inclui três produtos completos da Oracle, que são especialmente úteis para o desenvolvedor Java: o IDE  Java Oracle JDeveloper, uma ferramenta de desenvolvimento completa para a criação de aplicações Java de diversos tipos; o Oracle Containers for J2EE (ou OC4J), um runtime J2EE que é o coração do Oracle Application Server 10g; e o Oracle Database 10g Express Edition, uma versão “light” do SGBD da Oracle. Início da instalação O CD inclui um arquivo Autorun.inf, que, em alguns sistemas, fará com que a página inicial seja carregada automaticamente (veja a Figura 1). Caso não seja, abra a página index.htm na raiz do CD. Para iniciar a instalação, clique no botão “Install Now!”. Será mostrada uma lista de restrições; marque todas as checkboxes, leia a licença a seguir e, se decidir aceitá-la, clique em “I Accept”. Na próxima pági na, será mostrada uma senha para instalação, que será sempre “10gJ2EE” (para os três produtos). Ao final da página, você verá instruções para instalação, que detalhamos a seguir. descompactar, será pedida a senha fornecida no passo anterior. Isso conclui a instalação. Para inicializar o JDeveloper (no Windows), simplesmente execute  jdeveloper.exe. Ao executar o JDeveloper pela primeira vez, será mostrada uma caixa de diálogo perguntando se você deseja migrar de uma versão anterior do IDE. Responda “No”, e o IDE será aberto. É então mostrada outra caixa de diálogo exclusiva para a primeira execução (veja a Figura 2); nela você define as extensões de arquivos que serão associadas ao JDeveloper. Vale a pena selecionar pelo menos a segunda opção: .jpr. A clássica janela de dicas é a próxima a ser exibida. Depois de fechá-la, você estará com o IDE disponível para criar aplicações  Java de diversos tipos. Veja o JDeveloper em ação na Figura 3. OC4J A instalação do OC4J é igualmente simples. Descompacte o arquivo oc4j1013.zip, localizado no diretório oc4j  do CD, para uma pasta adequada do disco (exemplo: c:\Java\oc4j). Para que seja possível usar os scripts de execução do OC4J, sua variável de ambiente JAVA_HOME deve estar definida, apontando para o diretório principal  JDeveloper 10g Para instalar o IDE, expanda o arquivo  jde v1013 .zip, localizado na pasta  jdev do CD, para um diretório apropriado (por exemplo c:\Java\jdev ). Ao Figura 1. Página inicial do CD-ROM. Figura 2. Associação de extensões ao IDE JDeveloper. 10  Java Magazine • Edição 38  jm38.indb 10 17/7/2006 14:10:42 Figura 3. O JDeveloper 10g é especialmente forte no desenvolvimento de aplicações com acesso a banco de dados. O exemplo mostra o uso dos componentes ADF i ncluídos com o IDE. de um JDK 1.4.2 ou 5.0. Também é preciso definir a variável ORACLE_HOME para o diretório onde o OC4J foi descompactado. Para executar o servidor, em um prompt de comandos entre no subdiretório bin e execute o comando oc4j –start. Depois de algum processamento, será solicitada uma senha de administrador. Forneça a senha (note que ao digitar não serão mostrados caracteres, nem mesmo asteriscos), e depois de mais alguns passos o OC4J já estará em execução, pronto para a instalação de aplicações J2EE. Para testar a instalação, abra seu navegador web e entre na URL http://localhost:8888/em. Isso carrega o site de administração do servidor. Na tela de login, forneça a senha de administração criada anteriormente. O site de administração (veja a Figura 4) permite instalar e desinstalar aplicações Java EE, verificar o desempenho e investigar web services disponíveis, entre outras operações. Oracle Express O Oracle Database 10g Express Edition inclui um instalador convencional (para Windows). Descompacte o arquivo OracleXE.zip para algum local do disco e execute OracleXE.exe. Siga os primeiros passos do wizard, defina uma senha para contas de sistema e prossiga com a instalação. Para testar a instalação, selecione a opção “Ir Para a Home Page de Banco de Dados” no grupo de programas criado para o programa (ou visite diretamente a URL http://127.0.0.1:8080/apex ). Forneça o logi n “system” e a senha definida na in stalação. A página inicial de administração será exibida (veja a Figura 5). Figura 4. Acompanhando o desempenho do OC4J no site de administração do produto. Se a página de administração não for carregada, poderá ter havido problemas durante a instalação, causados por programas como o Google Desktop ou sistemas de antivírus. Desative esses programas e refaça a instalação. Se mesmo assim a página não carregar,um bom site para analisar outros erros possíveis é orablogs.com/sergio/archives/001759.html. A partir do site de administração do Oracle XE, você pode criar e manipular bases de dados, visualizar estatísticas de execução, e criar aplicações para cadastro de dados, e realizar muitas outras tarefas. Figura 5. Administração do Oracle XE: da navegação de dados à criação de apli cações. Edição Edição 38 •38 Java •  Java 11 11 Magazine Magazine  jm38.indb 11 17/7/2006 14:10:43  Java Livre Datas no Desktop Usando Componentes Swing para Manipular O Swing é uma biblioteca de componentes visuais muito rica e poderosa, permitindo criar uma grande quantidade de aplicações com qualidade profissional, usando apenas os componentes padrões inclusos no Java SE. Mas sempre haverá situações em que o desenvolvedor poderá se beneficiar de algum componente adicional. Um caso comum é o de um “date picker”, um componente que permite selecionar uma data num calendário. A maioria dos usuários prefere este tipo de interface em vez da caixa de texto formatada oferecida pelo Swing (o componente  JFormattedTextField ). O termo tecnicamente correto para qualificar componentes como um “date picker” em uma aplicação seria JavaBean, mas este termo ganhou usos comuns fora do seu sentido original, por isso preferimos o termo “componente”. Para mais detalhes sobre esta questão, veja o quadro “Componentes,  JavaBeans e POJOs”  Existem vários componentes proprietários e livres para a seleção de datas, mas decidimos focar este artigo no NachoCalendar  (nachocalendar.sf.net) para fornecer ao leitor um modelo de como incluir componentes Swing externos em suas aplicações. Veja também o quadro “Outras bi bliotecas Java para calendários”. Enquanto este artigo apresenta detalhes específicos da instalação e uso do NachoCalendar, os quadros que demonstram a integração deste componente com os IDEs NetBeans e Eclipse serão úteis também para o desenvolvedor interessado em outros componentes para aplicações Swing. Sobre o NachoCalendar O NachoCalendar é um projeto open source criado em meados de 2004 no SourceForge. Como tem licença LGPL, pode ser incluído também em aplicações distribuídas sob licenças de software proprietário, sem que isto exija a permissão dos desenvolvedores e sem obrigar a 12  Java Magazine • Edição 38  jm38.indb 12 17/7/2006 14:10:51 Datas e Calendários Saiba como usar o NachoCalendar em aplicações Swing, como integrá-lo ao NetBeans e Eclipse, e conheça conceitos gerais sobre componentes visuais em Java FERNANDO LOZANO abertura do código da aplicação que faz uso do componente. São fornecidos três componentes principais, todos no pacote net.sf.nachocalendar. components : • DateField  – Permite tanto a digitação de datas quanto a seleção em uma janela pop-up, com estilo semelhante a um combobox. • DatePanel – É basicamente o pop-up utilizado pelo DateField, mas fornecido como uma subclasse de  JPanel. Por isso pode ser posicionado livremente dentro de uma  janela para formar telas de entrada de dados customizadas (como numa agenda de compromissos). • CalendarPanel – Outra subclasse de  JPanel, que exibe múltiplos DatePanel s simultaneamente, formando uma visão de calendário que exibe diversos meses, com navegação e layout customizáveis. A Figura 1 apresenta a aplicação de demonstração inclusa com o NachoCalendar. Observe que o componente já está “localizado” para o português brasileiro, usando recursos presentes no Java SE, por meio de  java.text.DateFormat  e classes relacionadas. Os três componentes compartilham muitos recursos, de modo que a maior parte do que se aprende sobre o mais simples é válida também para os mais complexos. Assim o artigo inicia apresentando exemplos de uso do DateField, e depois passa para o DatePanel. Para evitar que o artigo fique muito longo, entretanto, não serão apresentados exemplos do CalendarPanel . No entanto, a parte principal da sua utilização será exatamente igual à do DatePanel.  A Edição 22 apresenta, na seção “Primeiros Passos”, um artigo que detalha todas as APIs de manipulação de datas do Java SE. Leitura reco- mendada para os usuários do NachoCalendar e componentes similares. Instalação do NachoCalendar Para obter o NachoCalendar, visite nachocalendar.sf.net, siga o link “Downloads” e baixe o arquivo nachocalendar-0.23. zip. Então descompacte o ZIP em uma pasta qualquer. Será criado o diretório nachocalendar-0.23  que contém, entre outros, o arquivo manual-0.23.pdf , um “QuickStart” para a utilização do componente. A documentação JavaDoc pode ser encontrada no subdiretório doc. Em lib  está o arquivo nachocalendar-0.23.jar, que deve ser adicionado ao classpath de compilação e de execução de qualquer aplicação que utilize os componentes do NachoCalendar. Para executar o programa de demonstração do projeto, execute a seguinte lin ha de comando, onde %NACHO% deve ser substituído pelo diretório contendo o JAR do NachoCalendar:  java -jar %N ACHO%\l ib\nach ocalendar- 0.23-demo.jar Usuários Linux devem executar o comando:  java -jar $NACHO /lib/ nachocalend ar-0.23-demo.jar Os quadros  “NachoCalendar no NetBeans 5” e “NachoCalendar no Eclipse VE” apresentam instruções específicas de instalação e uso para esses IDEs. Agora veremos um exemplo de uso do NachoCalendar em aplicações Swing, para depois estudarmos em mais detalhes a arquitetura do NachoCalendar e exemplos adicionais de aplicações. Exemplo de seleção de datas A Listagem 1   apresenta um exemplo  básico de uso do componente DateField do NachoCalendar, e demonstra quase tudo o que é necessário saber sobre ele para utilizá-lo em uma aplicação real. O exemplo modifica a instância de  java.text.DateFormat do componente por meio do método setDateFormat() . A razão disso é Figura 1. Aplicação de demonstração do NachoCalendar: observe no DatePanel  que a data atual pode ser indicada por uma elipse vermelha (os retângulos vermelhos indicam os componentes em si). Edição 38 •  Java Magazine 13  jm38.indb 13 17/7/2006 14:10:52  Java Livre • Datas no Desktop Outros componentes Java relacionados com calendários A qui apresentamos uma breve relação de outros componentes e bibl iotecas livres para Java, que podem substituir ou complementar o NachoCalendar, agrupados em categorias de acordo com suas finalidades. Note que são todos projetos hospedados no SourceForge, mesmo que alguns tenham seus próprios domínios DNS independentes e em alguns casos sites independentes do SourceForge. Componentes Swing para edição de datas e visualização de calendários • microba.sf.net • web.ukonline.co.uk/mseries • opensource.theotherbell.com/php/datepicker.php Componentes web para edição de datas e visualização de calendários • calendartag.sf.net •  jcal.sf.net • sf.net/projects/palooka Interação com serviços de calendário, PIMs e Groupware • k5n.us/javacaltools.php • moonbird.sf.net •  jpim.sf.net • web.mac.com/sebsto/iWeb/projects/JSCalendarSync.html •  jical.sf.net • icalgrabber.sf.net que a configuração padrão do componente exibe anos com apenas dois dígitos (por exemplo, “17/05/06”), enquanto que o formato padrão MEDIUM de DateFormat utiliza quatro dígitos. O exemplo também ilustra como inicializar e como recuperar a data editada pelo componente. Os métodos getValue() e setValue()  são declarados para receber e retornar um  java.lang.Object em vez de um  java.util.Date ou  java.util.Cale ndar. O motivo disto é tornar o componente um substituto direto para o  JFormattedTextField, que define os métodos get/setValue()  da mesma forma. Apesar de a assinatura dos métodos indicar um Object, passar qualquer coisa diferente de um  java.util.Date irá gerar uma exceção. Para compilar e executar o exemplo, antes acrescente o JAR com os componentes ao classpath do sistema, por exemplo: setCLASSPATH=%CLASSPATH%;%NACHO%\l ib\nachocalendar-0.23.jar (Usuários Linux devem usar o comando export em vez do comando set.) O resultado da execução do programa pode ser visto na Figura 2. APIs alternativas para manipulação de datas e horas •  joda-time.sf.net • recurrance.sf.net Arquitetura do NachoCalendar O manual do NachoCalendar parece in- Arquitetura MVC no Swing N o Swing, todos os componentes visuais seguem a arquitetura MVC, pela qual classes diferentes desempenham o papel de Modelo, Visualização e Controlador ( Model , View , Controller ). Isto não significa que uma aplicação Swing tenha necessariamente que seguir a arquitetura MVC, nem que o uso do Swing torne uma aplicação automaticamente aderente à arquitetura MVC. Veja a série “Uma aplicação completa com o NetBeans”, publicada nas Edições 25, 26 e 27 para mais detalhes sobre como construir uma aplicação Swing na arquitetura MVC. Dentro do Swing, a classe com a qual normalmente o desenvolvedor interage (e que para ele parece ser o próprio componente) é na verdade o controlador na arquitetura MVC. A Figura Q1 ilustra o relacionamento entre o componente e as classes auxiliares utilizadas por ele para formar a arquitetura MVC. desenvolvedores, todo componente Swing Em componentes simples como  JButton e instancia um Model e um UI Delegate padrão. É por isso que a maioria das aplicações instan JLabel, o desenvolvedor não tem necessidade de interagir com o Model, mas esta interação se cia (por exemplo) apenas um  JButton , e tudo torna necessária em componentes mais comfunciona corretamente. plexos como JList ou  JTree.   Component UI Delegate Já a interação com Model (Controller) (View) a View (chamada pelo Swing de UI Delegate ) em geral  javax.swing  javax.swing.plaf  é necessária apenas para desenvolvedores de novos lookButtonModel JButton ButtonUI and-feels, como o TinyLAF ( muntjak. de/hans/java/  tinylaf ). Para tornar Figura Q1. Uso da arquitetura MVC na arquitetura do próprio Swing, exemplificada pelo mais fácil a vida dos componente JButton 14  Java Magazine • Edição 38  jm38.indb 14 17/7/2006 14:10:54 Usando o NachoCalendar no NetBeans A Figura Q2   mostra uma versão do primeiro exemplo deste artigo sendo construída visualmente no editor Matisse do NetBeans 5.x. Observe que ele é exibido na área de desenho com seu aspecto real, e que suas propriedades aparecem na janela de propriedades. Porém não será possível expandir a seta para ver o calendário em tempo desenvolvimento (assim como não seria possível expandir um  JComboBox ). Acrescentar este componente no NetBeans é fácil: 1.   Execute o commando Tools|Palette Manager>Swing/AWT Components. 2. Clique em Add from JAR. 3 .   Localize e selecione o arquivo nachocalendar-0.23.jar . 4. Clique em Next   para ver a lista de componentes disponíveis ( available components), que lista todas as classes JavaBean encontradas no JAR selecionado. 5.  Selecione (usando Ctrl+Shift+clique) apenas os componentes “CalendarPanel”, “DateField” e “DatePanel”. (As demais classes listadas, embora pareçam para o IDE JavaBeans independentes, são na verdade classes auxiliares para os três componentes citados.) 6. Clique em Next   para ver as categorias do Palette. 7. Escolha a categoria “Beans” e clique em Finish. Será possível ver imediatamente os novos componentes na categoria Beans do Palette. Todos terão, no entanto, um ícone contendo um ponto de interrogação. O motivo é que o NachoCalendar não inclui classes BeanInfo para seus componentes. Estas classes seriam responsáveis por fornecer o ícone para uma ferramenta visual, além de editores customizados para propriedades, como dateFormat ou selectionMode, que fogem aos tipos usuais. O NetBeans contorna a falta de um customizador para propriedades ao permitir que o valor inicial de uma propriedade seja def inido por um trecho de código Java. Basta clicar no botão de reticências ao lado do valor da propriedade, e o resultado será semelhante à Figura Q3. Figura Q2. DateField  do NachoCalendar no editor visual do NetBeans 5 Note, entretanto, que este código será utilizado exatamente da maneira que foi digitado, podendo gerar erros de compilação na classe por falta de imports e por outros motivos. Havendo algum erro, ele deverá ser corrigido dentro da própria janela de propriedades, pois o trecho de código correspondente não será editável pelo editor de código Figura Q3. Editando a propriedade dateFormat  de um DateField  Java do NetBeans. Por outro lado, o desoportunidade. Um primeiro passo seria acrestaque de sintaxe e o auto-completamento centar as classes BeanInfo ao NachoCalendar, de código estarão disponíveis no editor de de modo a incluir ícones personalizados no propriedades da mesma forma como no Palette do NetBeans (ou de qualquer outro IDE editor de código.  Java com suporte à edição visual Swing). Só isto No momento que um dos componentes  já seria um acréscimo apreciado pelos usuários do NachoCalendar for inserido em qualquer do projeto. Podem também ser criados editores classe visual, o JAR correspondente será especializados para  selectio nMode  e outras proacrescentado automaticamente às proprie priedade s q ue exigem a digitaç ão de código dades do projeto. no NetBeans. Por fim, bastaria empacotar tudo em um plug-in do NetBeans (.nbm) que na sua  Se o leitor está interessado em participar instalação já acrescente automaticamente os de um projeto de software livre, eis uma ótima componentes no Palette. Edição 38 •  Java Magazine 15  jm38.indb 15 17/7/2006 14:10:55  Java Livre • Datas no Desktop Usando o NachoCalendar no Eclipse VE A Figura Q4  apresenta o primeiro exemplo deste artigo sendo construído visualmente com o Visual Editor (VE) da Fundação Eclipse, mostrando que o desenvolvedor não precisa se limitar aos componentes fornecidos com o Palette padrão do VE. O VE não fornece uma maneira direta de se acrescentar componentes ao Palette; isto é possível apenas por meio de plug-ins que estendem o próprio VE. Em compensação, é fornecido o ícone “Choose Bean” ( ), que exibe uma pequena variação de um diálogo bastante conhecido dos usuários do Eclipse (veja a Figura Q5). Nele, digita-se o início do nome de uma classe ou interface e são exibidas todas as correspondências visíveis para o projeto corrente. Esta variação do diálogo permite limitar as correspondências a apenas os JavaBeans que estendem alguma classe ou interface definida pelo Swing, o que permite encontrar rapidamente o componente desejado. Para que isto funcione, o JAR do NachoCalendar deve ser adicionado manualmente às propriedades do projeto, como qualquer biblioteca Java. Usuários experientes do Eclipse irão preferir cadastrar o NachoCalendar como uma “User Library” nas propriedades do IDE ( Figura Q6), o que torna mais simples, depois, acrescentar a biblioteca a cada projeto que venha a utilizá-la. O VE não fornece nenhum mecanismo que facilite a edição de propriedades como selectMode  e dateFormat dos componentes do NachoCalendar. Em compensação, ele não restringe a edição de nenhum bloco de código gerado pelo editor. Então é possível, por exemplo, editar manualmente o método getDateField()  para modificar o formato de data, conforme o código a seguir: return dateField; } private DateField getDateField() { if (dateField == null) { dateField = new DateField();   dateField.setShowToday(false); dateField.setDateFormat( DateFormat.getDateInstance( DateFormat.MEDIUM));     } Esta mudança será reconhecida pelo VE e incorporada à área de desenho em poucos se gundos. O VE é um editor poderoso e flexível, embora ainda não seja tão intuitivo nem eficiente quanto o Matisse do NetBeans. Figura Q4. DateField do NachoCalendar no editor visual do Eclipse 3.1.x/3.2 Figura Q5.Localizando o componente DateField  do NachoCalendar no Eclipse VE Figura Q6. Localizando o JavaBean DateField  do NachoCalendar no Eclipse VE 16  Java Magazine • Edição 38  jm38.indb 16 17/7/2006 14:10:57 dicar que o componente foge a especificação JavaBeans, ao indicar o uso de cla sses de fábrica para a criação dos componentes, por exemplo: DateField datefield = CalendarFactory.createDateField(); As classes de fábrica são úteis para reduzir a quantidade de código necessária para a configuração dos componentes, em especial quando são utilizadas as extensões de feriados e de tarefas, que fazem parte do download padrão do NachoCalendar. O fato é, no entanto, que todos os componentes do NachoCalendar são verdadeiros JavaBeans, perfeitamente aderentes à especificação, e podem ser utilizados sem se recorrer aos métodos de fábrica, como foi mostrado no primeiro exemplo deste artigo. Além disso, o NachoCalendar é construído segundo boas práticas do Swing, mantendo-se a separação de papéis. Se você não está habituado ao design de componentes desse toolkit, veja o quadro “A arquitetura MVC no Swing”. Os componentes do NachoCalendar delegam sua renderização para um UI Delegate e o gerenciamento das suas informações para uma classe de Model, que o desenvolvedor pode estender para fornecer funcionalidades adicionais. O efeito imediato da obediência do NachoCalendar à arquitetura do Swing é a compatibilidade com vários look-and-feels (LAFs) alternativos.   Muitos componentes Swing de terceiros não têm aspecto visual “correto” a não ser que sejam utilizados com o LAF padrão Metal ou o LAF nativo do Windows. Felizmente este não é o caso com o NachoCalendar. do NachoCalendar é demonstrada pelas extensões já i nclusas no download padrão, por exemplo: • Uso integrado a um  JTable: net.sf.nachocalendar.table.DateFieldTableEditor . • Exibição de feriados dentro dos calendários: net.sf.nachocalendar.holidays.HolidayModel e HolidayRenderer  dentro do mesmo pacote. • Suporte à exibição diferenciada de dias alocados para tarefas (pense em uma aplicação de gerenciamento de projetos Nos componentes DatePanel e CalendarPanel, é possível fazer seleções múltiplas de datas, inclusive de faixas descontínuas. Também é possível modificar a relação de “dias úteis”, para todos os componentes, e também alterar o formato de datas utilizado no DateField.  O cuidado na elaboração do NachoCalendar foi tanto que os componentes padrão são capazes até mesmo de incluir as fases da Lua nas visões de calendário. Figura 2. Execução do exemplo EscolheData.java, após o clique sobre o botão de seta. A flexibilidade dos componentes Listagem 1.  EscolheData.java – exemplo básico de uso do DateField  do NachoCalendar import import import import import java.util.Date; java.text.DateFormat; java.awt.BorderLayout; javax.swing.*; net.sf.nachocalendar.components.*; public class EscolheData extends JFrame { private DateField dateField; public EscolheData() throws Exception { setTitle(“Exemplo do NachoCalendar”);   setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); // será um formato DD/MM/AAAA para o Brasil DateFormat df = DateFormat.getDateInstance( DateFormat.DEFAULT); Date dia = df.parse(“17/05/2006”);           getContentPane().add(BorderLayout.NORTH, new JLabel(“Esc olha uma data:”)); dateField = new DateField(); dateField.setDateFormat(df); dateField.setValue(dia); //dateField.setPrintMoon(true);   getContentPane().add(BorderLayout.CENTER, dateField); pack(); } public static void main(String[] args) throws Exception { JFrame frame = new EscolheData();   frame.setVisible(true); } } Edição 38 •  Java Magazine 17  jm38.indb 17 17/7/2006 14:10:59  Java Livre • Datas no Desktop ou em um PIM – Personal Information  Manager – como os fornecidos em PDAs e aplicativos de Groupware). E exi bição de tooltips com a descrição das tarefas associadas ao dia sob o cursor (TaskDataModel e TaskRenderer, no pacote  net.sf.nachocalendar.task) Como se vê, estamos lidando com um componente bastante poderoso, capaz de fazer quase tudo o que se espera de um componente deste tipo, mesmo nas aplicações mais sofisticadas. Ao Listagem 2.  EventosData.java – demonstra como responder ao evento de mudança da data armazenada no componente //...imports omitidos public class EventosData extends JFrame { private DateField dateField; public EventosData() throws Exception { setTitle(“Exemplo do NachoCalendar”);   setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); getContentPane().add(BorderLayout.NORTH, new JLabel(“Escolha uma data:”)); dateField = new DateField(); dateField.setDateFormat(DateFormat.getDateInstance(DateFormat.MEDIUM)); dateField.getDateFormat().setLenient(false);     mesmo tempo, sua API básica é bastante simples, como veremos em mais detalhes nos exemplos. Eventos de edição e mudança de data Toda a navegação pelo calendário, por exemplo mudar de ano ou de mês, gera eventos específicos (veja as interfaces em net.sf.nachocalendar.event ). É fornecida uma API genérica para configuração dos componentes, cujo uso é demonstrado pelas extensões padrão de feriados e tarefas,  já citadas. Na maioria das vezes, o único listener que interessa registrar em um DateField é um  javax.swi ng.ChangeLi stener. Este listener permite agir no momento em que ocorre uma mudança de data, seja por digitação direta ou pela escolha no pop-up de calendário. Seu uso poderia ser validar dois DateField s de modo que um deles aceite apenas datas que sejam posteriores à fornecida no outro. A Listagem 2 demonstra como capturar dateField.addChangeListener(dataAlterada); getContentPane().add(BorderLayout.CENTER, dateField); pack();   } private ChangeListener dataAlterada = new ChangeListener() { public void stateChanged(ChangeEvent e) {   JOptionPane.showMessageDialog(EventosData.this, “A data escolhida foi: “ + dateField.getValue(), “Data alterada”, JOptionPane.INFORMATION_MESSAGE); } }; //...método main omitido } Figura 3. Execução do exemplo ExibeCalendario.java após um pequeno aumento no tamanho da janela. Listagem 3.  ExibeCalendario.java – mostra um calendário para o mês corrente //...imports omitidos public class ExibeCalendario extends JFrame { private DatePanel datePanel; public ExibeCalendario() throws Exception { setTitle(“Exemplo do NachoCalendar”);   setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); getContentPane().add(BorderLayout.NORTH, new JLabel(“Calendário Swing”)); datePanel = new DatePanel(); getContentPane().add(BorderLayout.CENTER, datePanel); pack();   } //...método main omitido } Figura 4. ExibeCalendario.java após a adição de um DayRenderer  customizado. 18  Java Magazine • Edição 38  jm38.indb 18 17/7/2006 14:11:02 os eventos de mudança de data por meio do ChangeListener . Note que este exemplo é quase igual ao apresentado no início deste artigo. A novidade é o tratamento do evento, e também ter deixado o DateField com o valor inicial padrão, que é a data corrente. Experimente ainda alterar o argumento da chamada a setLenient(), fornecendo datas do tipo “30/13/2006”. Exemplo de exibição de calendário A Listagem 3 apresenta um exemplo de uso do DatePanel, que simplesmente exibe um calendário para o mês corrente. Observe que a janela pode ser redimensionada, e que o calendário será redimensionado proporcionalmente (mas note que o tamanho de fonte utilizado não irá aumentar para compensar o aumento da área do calendário). A Figura 3 ilustra a aparência deste exemplo, após um pequeno aumento da janela. Caso a aparência padrão do calendário não lhe agrade, o DatePanel fornece uma forma poderosa de customização que é  bem coerente com outros componentes Swing sofisticados, por exemplo o  JTable. Em vez de definir muitas propriedades que alteram o aspecto visual do componente, é definida uma interface de renderer (renderizador) para cada parte. Por exemplo, existe o net.sf.nachocalendar.components.DayRenderer, que é o responsável pela exibição de cada célula de mês no calendário. São fornecidas pelo NachoCalendar várias implementações de DayRenderer, em especial o DefaultDayRenderer, que é uma subclasse do  JLabel  do Swing. É possível mudar a aparência do renderizador da mesma forma que se faz com um  JLabel padrão, por exemplo adicionar uma borda. A Listagem 4 ilustra como fazer esta customização simples, que tem o efeito de inserir “linhas de grade” no calendário. O resultado pode ser visto na Figura 4. O mesmo modelo da Listagem 4  pode ser utilizado para mudar a fonte e as cores de texto e de fu ndo, bem como outros atributos da exibição do calendário. Caso se deseje modificar os cabeçalhos com os dias da semana, deve ser fornecido um HeaderRenderer, que é similar ao DayRenderer. Para manter a compatibilidade com look- Listagem 4. ExibeCalendario.java – adição de um DayRenderer  customizado para exibir “linhas de grade”no calendário //...imports omitidos public class ExibeCalendario extends JFrame { private DatePanel datePanel; public ExibeCalendario() throws Exception { setTitle(“Exemplo do NachoCalendar”);   setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); DefaultDayRenderer dayRenderer = new DefaultDayRenderer(); dayRenderer.setBorder(new MatteBorder(new Insets(1, 1, 1, 1), Color.LIGHT_GRAY)); getContentPane().add(BorderLayout.NORTH, new JLabel(“Calendário Swing”)); datePanel = new DatePanel(); datePanel.setRenderer(dayRenderer); getContentPane().add(BorderLayout.CENTER, datePanel); pack();   } //...método main omitido } Listagem 5.  EscolheVariasDatas.java – como lidar com seleções múltiplas em um DatePanel  //...imports omitidos public class EscolheVariasDatas extends JFrame { private DatePanel datePanel; public EscolheVariasDatas() throws Exception { //...inicialização do JFrame e do DatePanel omitida datePanel.addChangeListener(dataAlterada); getContentPane().add(BorderLayout.CENTER, datePanel); pack();   } private ChangeListener dataAlterada = new ChangeListener() { public void stateChanged(ChangeEvent e) { Object[] datas = datePanel.getValues(); DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM); String listaDatas = “”; for (Object d : datas) listaDatas += df.format(d) + “\n”; JOptionPane.showMessageDialog(EscolheVariasDatas.this, “As datas escolhidas foram:\n” + listaDatas, “Datas alteradas”, JOptionPane.INFORMATION_MESSAGE); } }; //...método main omitido } and-feels personalizados, um renderizador deve evitar fixar cores como foi feito no exemplo. Em vez disso, deve usar preferencialmente alguma cor dependente do ambiente do usuário, por exemplo uma das definidas na classe  java.a wt.SystemColor . No exemplo, em vez de Color.LIGHT_GRAY   poderia ser utilizado SystemColor.control . Seleção de múltiplas datas Com um DateField, não se pode selecionar múltiplas datas no calendário. Mas com um DatePanel, é possível selecionar inter- valos de datas utilizando Shift+clique ou então várias datas não-contíguas utilizando Ctrl+clique, da mesma forma que se faz com  JList e  JTables. Na verdade, a configuração padrão de um DatePanel permite seleções múltiplas desse tipo. Para se restringir a seleção a uma única data, ou a uma única faixa de datas contíguas, deve ser chamado o método setSelectionMode()  do objeto DateField . Este método pode receber uma de três constantes definidas na interface net.sf.nachocalendar.model.DateSelectionModel , Edição 38 •  Java Magazine 19  jm38.indb 19 17/7/2006 14:11:03  Java Livre • Datas no Desktop cujos significados são auto-explicativos: • MULTIPLE_INTERVAL_SELECTION • SINGLE_INTERVAL_SELECTION • SINGLE_SELECTION  Um decorator  é uma classe que imita a interface de outra classe, por meio de especialização ou implementando a mesma interface, e tem por objetivo substituir esta classe apenas acrescentando alguma funcionalidade. Este design pattern é muito usado em aplicações gráficas para acrescentar algum elemento decorativo por cima de outro elemento. Daí o nome. 1 Caso seja configurada uma das duas formas de seleção múltipla, o conjunto de datas selecionadas pode ser obtido chamando o método getValues(), que retorna um array de Object. A Listagem 5   demonstra como lidar com seleções múltiplas de datas; é uma pequena modificação do exemplo na Listagem 4. Note que o ChangeListener  será chamado várias vezes (uma para cada clique) caso seja utilizado Shift+clique ou Ctrl+clique. Exibição de feriados Encerrando os exemplos de uso do NachoCalendar, será visto como acrescentar feriados ao DatePanel. O processo envolve duas etapas: 1. Fornecer um decorator1 para o DayRenderer, Componentes, JavaBeans e POJOs F reqüentemente os termos “componente” e “JavaBean” são usados como sinônimos pelos desenvolvedores Java. Além disso, os termos “POJO” e “JavaBean” também costumam ser utilizados como equivalentes. Mas, se um “POJO” ( Plain Old Java Object ) é nada mais do que um objeto/classe Java comum, sem restrições adicionais, então o que seria um componente? Há muitas definições de “componente” no meio de TI, portanto em vez de discutir livremente o conceito, vamos ver o que diz a especificação JavaBeans 1.01, na seção 2.1: “A Java Bean is a reusable software component that can be manipulated visually  in a builder tool.”  Ou seja, de acordo com a especificação, um JavaBean existe para ser manipulado por um IDE visual. Um JavaBean seria portanto análogo aos componentes fornecidos por IDEs RAD (Rapid Application Development) como Delphi ou VB. Para que seja viável a manipulação de JavaBeans por uma ferramenta, a especificação define conceitos como propriedades e eventos, além de duas maneiras pelas quais um IDE pode relacionar propriedades, eventos e métodos fornecidos pelo componente: 1. Usando introspecção 2. Usando um BeanInfo. Convenções e introspecção O uso da introspecção em JavaBeans é baseado na obediência a algumas convenções, como o uso de um construtor sem argumentos e de métodos de acesso getXxx()/setXxx()  para propriedades. Estas convenções básicas se tornaram bastante populares, ao ponto de se confundir a obediência a elas como sendo a própria definição de JavaBeans. O recurso de introspecção é uma característica única aos JavaBeans, quando comparado com os componentes fornecidos por ambientes RAD não-Java. Nestes ambientes, limitações da linguagem e da plataforma exigem a construção explícita e trabalhosa de tabelas de propriedades e eventos, de modo que a construção de um componente é um processo bem diferente do processo de construção de uma classe “comum”. Mas em Java a maior parte das classes construídas seguindo apenas as “melhores práticas” de desenvolvimento OO se tornam automaticamente JavaBeans. Assim o conceito de JavaBean como componente construído para uso num IDE visual acaba sendo esquecido por muitos. O fato de a maioria dos desenvolvedores estar trabalhando na construção de aplicações focadas em ferramentas como Ant e Maven, em vez de voltadas a recursos particulares de IDEs, também ajuda a se perder o conceito de JavaBeans como componentes para IDEs visuais. Hoje em dia, é comum que vários frameworks, como Hibernate, Struts e Spring usem o termo “JavaBean” para indicar uma classe qualquer (um POJO) que obedeça a estas convenções. BeanInfo A outra forma de se relacionar atributos, propriedades e eventos fornecidos por um JavaBean é fornecendo uma classe que implementa a interface java.beans .BeanInf o. Esta classe deve ser nomeada acrescentando-se o sufixo “BeanInfo” ao nome do JavaBean, e pode estar tanto no mesmo pacote do JavaBean descrito por ela quando num pacote em separado, configurado pelo IDE. Então o IDE pode oferecer suporte especializado para um dado componente, fornecendo uma classe BeanInfo customizada, que pode substituir ou estender a classe BeanInfo  do componente original. O IDE também pode fornecer classes BeanInfo para JavaBeans que não incluem seus próprios BeanInfos. Um JavaBean que fornece seu próprio BeanInfo não é obrigado a s eguir as convenções definidas para o uso da introspecção, permitindo por exemplo construir componentes que devam ser instanciados por métodos de fábrica. O BeanInfo  é a única maneira de se fornecer alguns recursos específicos para o uso em IDEs visuais, como um ícone para ser exibido na paleta de componentes. É uma pena, no entanto, que tantos desenvolvedores de componentes sigam o caminho mais fácil e deixem que o IDE use apenas a introspecção para configurar o suporte aos seus JavaBeans. O uso de um BeanInfo não acrescenta esforço significativo ao desenvolvimento do componente, pois a maioria dos métodos desta interface podem retornar null (nestes casos, o IDE deve recorrer ao uso da introspecção para obter as informações não fornecidas pelo BeanInfo). A especificação de JavaBeans define ainda muitos outros recursos que podem ser utilizados por JavaBeans, como as bound properties (propriedades que geram eventos sempre que seus valores forem modificados). E APIs complementares definem recursos como serialização de JavaBeans em formato XML, ou comportamentos alternativos de um JavaBean, quando executado dentro de um ambiente de desenvolvimento, em vez de numa aplicação final. No final das contas, o uso do termo “JavaBean” como sinônimo de “POJO” já pegou e não vai desaparecer tão cedo na comunidade Java. Mas a verdade é que um JavaBean pode ser muito mais do que uma classe comum, por isso neste artigo preferiu-se usar o termo “componente” para se referir a JavaBeans criados para complementar aplicações visuais em Swing. 20  Java Magazine • Edição 38  jm38.indb 20 17/7/2006 14:11:04 que cuida de modificar a cor do texto de um dia que corresponda a um feriado e de acrescentar um tooltip com o nome do feriado. Este decorator é uma instância de net.sf.nachocalendar.holidays. HolidayDecorator; 2.  Utilizar um HoliDayModel (definido no mesmo pacote do decorator) em lugar do DayModel padrão.  Note que o NachoCalendar é inconsistente na nomeação das classes e interfaces do subpacote  holidays , ora usando Holiday  , ora usando HoliDay . A Listagem 6 apresenta o código que modifica o exemplo ExibeCalendario para configurar o DatePanel  com o renderizador decorado e o modelo customizado, e acrescentar dois feriados: Independência do Brasil e Natal. A Figura 5  apresenta o resultado da execução deste último exemplo, ilustrando um dos feriados definidos. Em uma aplicação real, seria interessante obter os feriados de algum arquivo externo, e tam bém fornecer um novo HoliDayModel  capaz de calcular as datas de feriados flutuantes, como o Carnaval. Figura 5. Execução do exemplo ExibeFeriados.java, após a seleção do mês de setembro. (O cursor do mouse, que não aparece na captura, está sobre o número “7”.) Conclusões Demonstramos os cenários de uso mais freqüentes dos componentes do NachoCalendar, que podem fornecer às suas aplicações Swing com manipulação de datas aquele “toque profissional” que faltava. Vimos ainda algumas boas práticas de projeto e de uso de componentes Swing customizados, que podem ser resumidos por “imite o design dos componentes Swing padrões”. Além disso, mostramos como adicionar componentes adicionais aos IDEs livres mais populares, o NetBeans e o Eclipse. Listagem 6.  ExibeFeriados.java – exibe um calendário com diferenciação gráfica para os feriados //...imports omitidos public class ExibeFeriados extends JFrame { private DatePanel datePanel; public ExibeFeriados() throws Exception { //...configuração do JFrame e do DatePanel omitidas HoliDayModel model = new HoliDayModel(); HoliDay feriado; DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM);         feriado = new DefaultHoliDay(); feriado.setName(“Natal”); feriado.setDate(df.parse(“25/12/2006”)); feriado.setRecurrent(true); model.addHoliDay(feriado);         feriado = new DefaultHoliDay(); feriado.setName(“Independência”); feriado.setDate(df.parse(“07/09/2006”)); feriado.setRecurrent(true); model.addHoliDay(feriado); datePanel.setModel(model); datePanel.setRenderer(new HolidayDecorator(dayRenderer)); getContentPane().add(BorderLayout.CENTER, datePanel); pack();   } //...método main omitido }  nachocalendar.sf.net  Site oficial do NachoCalendar. eclipse.org/vep Página oficial do VE (Visual Editor), plug-in que permite programação visual Swing e SWT no IDE Eclipse.  java.sun.com/docs/books/tutorial/uiswing Trilha de construção de interfaces Swing do Java Tutorial da Sun.  java.sun.com/products/jfc/tsc/articles/  architecture Documento da Sun que descreve a arquitetura do Swing e seu uso da arquitetura MVC.  java.sun.com/developer/onlineTraining/  Beans Tutoriais sobre componentes JavaBeans; leitura obrigatória para construtores e usuários de componentes de extensão Swing.  java.sun.com/products/javabeans/  docs/spec.html  Especificação JavaBeans.  netbeans.org Site oficial do NetBeans, com recursos sofisticados para programação visual.  javamagazine.com.br/downloads/jm38/   jm-datasdesktop.zip Fernando Lozano ([email protected], www.lozano.eti.br ) trabalha há mais de 10 anos com desenvolvimento de sistemas de informações e integração de redes, sendo um dos pioneiros do uso do Software Livre no Brasil. Dentro da comunidade, atua como Conselheiro do L PI Brasil, Webmaster da FSF e Community Manager do Java.net. Atualmente é consultor associado à Neki Technologies (www.neki.com.br ). Edição 38 •  Java Magazine 21  jm38.indb 21 17/7/2006 14:11:13 Byte Code Relatórios e Gráficos Usando o Business Intelligence and Reporting 22  Java Magazine • Edição 38  jm38.indb 22 17/7/2006 14:11:22 com Eclipse Tools – BIRT Crie passo a passo relatórios e gráficos de vários tipos, de exemplos simples utilizando wizards a soluções sofisticadas baseadas em scripts OSVALDO PINALI DOEDERLEIN A geração de relatórios é uma necessidade comum a muitas aplicações, especialmente as que fazem acesso a bases de dados corporativas. De fato, o volume de dados acumulados pelas empresas só faz crescer a cada ano, seja devido à informatização crescente de atividades, seja por força de legislações ou práticas comerciais que exigem o controle e a armazenagem de cada vez mais informações (ex.: contratos de qualidade de serviço). Isso se traduz numa demanda cada vez maior por funcionalidades de geração de relatórios, tarefa que não costuma ser das favoritas de muitos desenvolvedores. Certamente por este motivo, o mercado de ferramentas de software há muito tempo oferece produtos de geração (semi-)automática de relatórios, desde produtos amarrados a SGBDs como o Oracle Reports Developer, a softwares independentes como Crystal Reports. E mais recentemente, opções open source como o JasperReports e iReport para Java. O BIRT (Business Intelligence and Reporting Tools), projeto da Fundação Eclipse, é uma nova opção na categoria “independente, open source e para Java”. Mas não é apenas mais um gerador de relatórios. O BIRT promete revolucionar o cenário dos relatórios para Java, especialmente devido à sua forte integração com o IDE Eclipse, o que traz vantagens de produtividade claramente além do possível para outros competidores (mesmo os que possuem plug-ins para IDEs). Apesar de relativamente novo, o BIRT tem evoluído a passos largos e já é uma tecnologia madura. Já encontramos o BIRT na sua versão 2.1, que acompanha o release do Eclipse 3.2 e faz parte do Callisto 1.0 (distribuição integrada dos principais projetos do Eclipse.org). Neste artigo, veremos como utilizar o BIRT, guiando o leitor na construção de relatórios com um tutorial prático, e examinando os recursos e características desta ferramenta. Embora o BIRT e este artigo sejam calcados no Eclipse, usuários de outros IDEs também podem usar o BIRT, graças ao RCP Report Designer (veja a seção “Instalando”). O Projeto BIRT O projeto BIRT tem o objetivo de construir ferramentas de Business Intelligence e relatórios, usando o modelo open source e as tecnologias da Fundação Eclipse. É interessante destacar algumas conseqüências menos evidentes desta definição: • O BIRT não é simplesmente um "plug-in para o IDE Eclipse". Pode-se utilizá-lo sem nenhum IDE, inclusive para a edição visual de relatórios. • O BIRT se integra à arquitetura de ferramentas do Eclipse, o que significa que haverá outros plug-ins para Eclipse a se beneficiar do BIRT, como já é o caso do TPTP 4.2 (Eclipse Test and Tools Platform). O quadro “O BIRT, outros geradores de relatórios e open source” discute o status do BIRT como projeto do Eclipse.org, e o compara com outros projetos competidores no mundo open source. Componentes do BIRT  Como toda ferramenta de business intelligence, o BIRT traz sua própria sopa de letrinhas, com muitos novos acrônimos para aprendermos. Os componentes de runtime e design do BIRT são os seguintes: • ERD (Eclipse Report Designer) – Editor visual de definições de relatórios. • WRD (Web Based Report Designer) – Equivalente ao ERD, mas com interface web (este componente ainda não está disponível). • ERE (Eclipse Report Engine) – Ge- rador de relatórios; utiliza definições produzidas pelo ERD ou WRD. • ECE (Eclipse Charting Engine) – Gerador de gráficos; também utiliza definições produzidas pelo ERD ou WRD. Instalando Existem quatro maneiras de instalar o BIRT de forma a acompanhar este artigo (utilizaremos o BIRT 2.1, que é baseado no Eclipse 3.2): 1. Instalação tradicional do Eclipse. Começando com o Eclipse 3.2 (Platform + JDT, ou SDK), instale os plug-ins EMF 2.2 e GEF 3.2 (também exigidos por vários outros plug-ins, como o WTP). Basta então  baixar o pacote birt-report-framework-2.1.zip e descompactá-lo sobre sua instalação do Eclipse. 2. Callisto.  Com o Eclipse 3.2 instalado, vá em  Help|Soft ware Updates>Find and Install>Search for new features to install, escolha “Callisto Discovery site” e selecione um mirror. Dentro da árvore de opções “Callisto Discovery Site”, abra o ramo “Charting and Reporting” e selecione a opção “Eclipse BIRT Report Designer Framework 2.1.x”. Depois clique no botão Select Required para selecionar as dependências necessárias para a operação do BIRT, e clique em Next. Aceite a licença para os componentes a serem instalados; clique em Next e depois em Finish. 3. Opção “all-in-one”. Na página de download do BIRT, baixe o pacote birt-report-designer-all-in-one-2_1.zip, que vem com tudo que você precisa, incluindo o próprio Eclipse (SDK), o EMF, o GEF e o BIRT. 4. RCP Report Designer. É a opção para quem quer usar o BIRT sem o Eclipse;  A versão embutida da base Classic Models usa o Apache Derby. Veja mais sobre es se SGBD em “Demonstrando o Apache D erby”, na Edição 29. 1 Edição 38 •  Java Magazine 23  jm38.indb 23 17/7/2006 14:11:28 Byte Code • Relatórios e Gráficos com Eclipse ideal para usuários de outros IDEs. Baixe o arquivo birt-rcp-report-designer-2_1_0.zip (ou mais recente), que contém um editor visual de relatórios auto-contido. O projeto Feita a instalação, execute o comando File|New>Project, e você verá que foi criado um novo grupo de projetos para BIRT. Escolha a opção Report Project e forneça um nome para o projeto. Isso cria um projeto “puro” de relatório, o que num primeiro momento simplificará o acompanhamento desse tutorial. Depois veremos como com binar o relatório a um projeto Java. Após a criação do projeto, o BIRT apresenta a perspectiva Report Design, tam bém conhecida como ERD (Eclipse Report Designer). No novo projeto, use New>Report  para criar um relatório. Forneça o nome carros.rptdesign e na opção de templates escolha Simple Listing. Depois de finalizar o wizard, você verá o ERD lotado de ferramentas atraentes – editor visual de relatórios, paleta de elementos, editor de propriedades etc. Mas um relatório, antes de tudo, precisa de dados de entrada, portanto o próximo passo será disponibilizar esses dados. Os dados Entre na view Data Explorer, clique com o botão direito sobre o nó Data Sources e selecione New Data Source. Depois escolha Classic Models Inc. Sample Database. Dê um nome à data source, ex.: “carrosDS”. Este  banco de dados de teste é embutido no BIRT1; por isso não é exigida nenhuma outra configuração. Num projeto real, você usaria um banco de dados externo. Se quiser já praticar este cenário mais realista, baixe o pacote birt-database-2.1.zip , que contém os scripts para criação e população do mesmo banco de dados “Classic Models”. Este  pacote contém scripts de criação de tabelas e po- 2  Para outros SGBDs, é fácil criar as tabelas a partir dos scripts create_classicmodels.sql  de uma destas versões. Já a população de dados iniciais está disponível em vários arquivos-texto (formato CSV), que podem ser importados com facilidade em muitos SGBDs, por exemplo com o Oracle SQL*Loader. 3  Para quem já usou o JasperReports, o arquivo .rptdesign é o equivalente aos arquivos .jrxml , exceto que não existe uma etapa de pré-compilação para .class.  pulação de dados para o Derby e para o MySQL 2 , e um arquivo .mdb para o Microsoft Access. Uma vez criadas as tabelas, crie a data source com a opção “JDBC Data Source”. O diálogo de criação de data sources possu i um bot ão “Manage Drivers”, que  permite cadastrar odriver JDBC para seu SGBD preferido (o driver para o Derby em modo embutido já vem registrado.) Tendo o driver configurado, basta entrar com os dados de URL, login e senha. Na mesma view, em Data Sets, precisamos criar agora um “conjunto de dados” (Data Set), que corresponde a um resultset ou cursor. Crie o Data Set com o nome “carros” e tipo “SQL Select Query”. Será apresentado o diálogo de construção visual de consultas do BIRT ( Figura 1). A database Classic Models modela uma loja de automóveis. Vamos criar um relatório simples, mostrando nome, fabricante, descrição e preço de todos os automóveis cadastrados, ordenados por fabricante e depois por nome. Os nomes da tabela e das colunas podem ser copiados para a consulta com um duplo clique (ou arrastando para a janela que contém o código SQL); pode-se também digitar os comandos SQL diretamente. Assegure que a consulta seja algo como: select PRODUCTNAME, PRODUCTVENDOR, PRODUCTDESCRIPTION, BUYPRICE from PRODUCTS order by PRODUCTVENDOR, PRODUCTNAME fizer isso, ainda poderá digitar as legendas nos cabeçalhos dos relatórios, mas este trabalho teria que ser feito repetida mente para cada novo relatório que utilize o Data Set. O relatório Como o layout básico do relatório está pronto (usamos um template que já inclui um grid de quatro colunas), só falta associar nosso Data Set ao layout. Observe que cada coluna do Grid (na aba Layout) possui as linhas ( rows) Header (cabeçalho), Detail (dados) e Footer (rodapé). Selecione, no Data Set, a coluna de resultado Fabricante, e arraste-a até a linha Detail na primeira coluna (aparece um diálogo Select Data Binding; você pode aceitar as opções default e fechá-lo). Faça o mesmo para as outras três colunas de resultado. Um último retoque é alterar o formato dos cabeçalhos, para que estes se diferenciem dos dados. Selecione com Shift+clique cada célula de cabeçalho, e no Property Editor mude o Background Color. Mas, como queremos usar o mesmo estilo para todas as células do cabeçalho, há uma forma mais fácil: passe o cursor do mouse sobre o Grid para mostrar o manipulador Table (sob o canto inferior esquerdo do Grid); clique nele, revelando os manipuladores de linhas e colunas; depois clique no da primeira linha (a do cabeçalho). Use então o Property Editor, customizando a cor de toda a linha selecionada. O resultado deverá ser parecido com a Figura 2. Para testar o relatório, clique na aba Preview. Você verá o relatório funcionan- Após a criação inicial do Data Set, o diálogo Edit Data Set permite customizar detalhes como parâmetros, colunas calculadas, cache e filtros, e também se ter um preview dos dados selecionados, de forma a verificar que a query está correta. Uma última etapa essencial é ir na aba Output Columns   (ainda no diálogo Edit Data Set) e preencher, para cada coluna do resultado, o seu Dis pl ay Na me   (ex.: BUYPRICE   = “Preço”). Se você não Figura 1. Definindo um data set a partir de uma query SQL. 24  Java Magazine • Edição 38  jm38.indb 24 17/7/2006 14:11:29 do, como na Figura 3. Este preview é uma  janela embutida do navegador web default do Eclipse: assim, o que estamos vendo é um relatório HTML. Note que a primeira visualização do preview pode demorar alguns segundos para aparecer, pois o ERE (Eclipse Report Engine) precisa a ntes ser carregado. A primeira versão do nosso relatório está pronta. Dito isto, o que foi que construímos? O projeto possui apenas o arquivo carros.rptdesign, que é um documento XML (editável diretamente na aba XML Source). Este documento descreve todos os aspectos do relatório: layout, fontes de dados, associações entre os dados e o layout, formatação e outros itens ainda não vistos. O documento pode ser utilizado como entrada para o Report Engine, que gera relatórios em aplicações web (HTML), desktop (Swing, SWT), e outros formatos como PDF3. O arquivo .rptdesign isolado só funciona porque a aba Preview do Report Designer invoca o Report Engine. Uma aplicação real precisaria de um pouco de código para invocar o engine, e apresentar o resultado ao usuário. Mas antes de fazer isso, vamos dar mais um passo fácil. No download deste artigo, o arquivo correspondente a esta etapa é o carros1.rptdesign. Gráficos Diz-se que uma imagem vale por mil palavras, mas no caso de relatórios, “por mil números” seria mais apropriado. Gráficos de relatórios (ou charts) permitem visualizar massas de dados grandes ou complexas, de forma rápida e intuitiva. Com o BIRT, também podemos criar estes gráficos sem nenhuma programação. Na view Palette, selecione o componente Chart e clique no relatório, no espaço vazio logo abaixo ou acima do Grid (coloquei acima). Um diálogo New Chart permitirá customizar uma série de opções, das quais exploraremos uma seleção. Na primeira aba, Select Chart Type, a opção mais importante é Output Format. São suportados gráficos bitmap (JPG, PNG e BMP) ou vetoriais (SVG). O SVG é teoricamente a opção ideal, mas o suporte a esse formato ainda está longe de ser universal 4). Por segurança, escolha JPG ou PNG. Figura 2. Layout já associado às colunas de resultado do data set. Figura 3. Primeiro relatório no BIRT. Na segunda aba, Select Data, você deverá associar colunas do Data Set às séries de dados que formam o gráfico. Comece marcando a opção Select Data Set / Use Data Set, escolhendo o Data Set “carrosDS” no com bobox. A tabela Preview exibirá os dados obtidos do Data Set. Selecione com o botão direito o cabeçalho da coluna Fabricante, e no menu que aparecerá ative a opção Use as Category (X) Axis. Em seguida faça o mesmo para a coluna Preço, com a opção Plot as Value (Y) Series. Veja o final desta etapa na Figura 4. Na última aba, Format Chart, você pode escolher muitas opções de formatação do Data Set e de elementos como eixos, legendas, fundo etc. Vamos fazer somente as configurações essenciais para este gráfico. Em Series / Category (X) Series > Grouping, marque Enabled, e selecione Interval = 0. Isto fará o gráfico ter uma única coluna para cada fabricante (ao invés de várias, uma por registro do mesmo fabricante). Mude também a opção  Aggregate Expres sion para Average. Em Chart Area / Chart Title, forneça o título “Preços Médios por Fabricante”. Em Chart Area / Axis / X-Axis, clique no  botão Text Format; no diálogo que se abre, selecione Label / Font > ‘...’ (outro botão, que abre o diálogo Edit Font); finalmente, neste novo diálogo, altere o valor Rotation para 90º. Isto fará as legendas do eixo X serem exibidas no sentido vertical, o que será importante para acomodar um número grande de itens. De volta ao designer, ajuste o tamanho e a posição do gráfico no relatório, e então acione novamente a aba Preview. Você verá algo... feio, com rótulos numéricos embaralhados (dígitos demais) e uma legenda vazia. Se não queremos perder nossos clientes, temos que embelezar um pouco mais. Para as legendas, de volta ao Edit Chart  / Format Chart / Series, preencha o campo 4  O Mozilla Firefox possui suporte nativo a SVG, mas o MSIE exige um plug-in da Adobe. 5  Em estatística, percentil é uma medida de posição de um valor relativamente aos demais valores do conjunto. Por exemplo, se um modelo X tem preço 72, e 90% dos modelos têm preço na faixa 0-72, então o percentil do preço de X é 90, ou seja, está na faixa de preço de 90% dos modelos. Há nomes para percentis comuns, como “primeiro quartil” ou Q1 (= percentil 25), e “Mediana” (= percentil 50). Edição 38 •  Java Magazine 25  jm38.indb 25 17/7/2006 14:11:31 Byte Code • Relatórios e Gráficos com Eclipse claro, ainda poderíamos retocar legendas, proporções, cores, fontes, e outros aspectos visuais buscando tornar o gráfico (e o relatório) mais compreensível ou bonito. Até este ponto, não escrevemos uma só linha de código Java. O BIRT faz o serviço de forma totalmente visual e interativa, sendo que as configurações que mostramos (e outras que ainda teremos espaço para apresentar neste artigo) são uma fração do total disponível. O custo disso, como o leitor certamente terá verificado a essa altura, é que o designer de relatórios do BIRT é bastante pesado. Mas se você observar um OutOfMemoryError, não significa que o BIRT seja assim tão exigente – veja o quadro “Configurando a memória para o BIRT”. No download deste artigo, o arquivo correspondente a esta etapa é o carros2.rptdesign. Figura 4. Configurando um gráfico do relatório. Figura 5. Customizando as legendas do eixo Y. Category (X) Series com “Fabricante”, e Value (Y) Series com “Preço”. Agora vamos ajustar a exibição dos rótulos numéricos dos valores, que aparecerão no tipo de cada barra. Isso está mais escondido. Em Series / Value (Y) Series, clique em Labels, que abre um diálogo de mesmo nome permitindo customizar as legendas do eixo Y, conforme a Figura 5. Você verá uma lista Values, já populada com um item: “Value Data” (pode haver várias legendas para cada item: o valor numérico, sua categoria, nome, ou percentil 5). Clique no item Value Data e então acione o pequeno botão 0.0#, que traz outro diálogo (ufa!) para editar a formatação desta legenda. Basta selecionar Data Type = Number (o default), Standard, Fraction Digits = 2. Pronto, agora nosso gráfico está razoavelmente apresentável, devendo se parecer com o mostrado na Figura 6. Nossa segunda versão do relatório, dessa vez com um gráfico, está completa. É Uma aplicação real e completa (ou quase) Antes de entrarmos em mais detalhes sobre funcionalidades do BIRT, vejamos como podemos usá-lo para criar aplicações  Java reais. Nosso exemplo será uma aplicação desktop (Swing) que invoca o Report Engine e exibe o relatório produzido numa caixa de diálogo; mas como veremos, o BIRT também pode ser utilizado por aplicações web. Instalando o Report Engine Uma vez finalizada sua aplicação, ela precisará do runtime do BIRT – o ERE, para relatórios completos, ou o ECE (Eclipse Chart Engine), somente para gráficos. O download destes runtimes, birt-runtime-2.1.zip, possui assustadores 86 Mb, mas inclui várias versões do ERE e ECE. O ECE isolado tem 3,7 Mb, na pasta /ChartEngine, e é a única opção de runtime que pode ser utilizada facilmente de maneira semelhante à maioria das bibliotecas  Java; ou seja, basta colocar todos os seus  JARs no classpath da sua aplicação. O ERE completo (incluindo o ECE) tem 28 Mb, sendo fornecidas duas versões. A primeira fica na pasta /ReportEngine. A estrutura de diretórios e arquivos do ERE é semelhante à do Eclipse, com subdiretórios como plugins, configuration, e até workspace. Você pode remover o subdiretório samples, 26  Java Magazine • Edição 38  jm38.indb 26 17/7/2006 14:11:32 mas não mais que isso (pelo menos, não sem ser um expert no BIRT). Não dá para apenas “pescar” os JARs e colocá-los no classpath da sua aplicação, pois o ERE utiliza a infraestrutura de plug-ins da plataforma Eclipse, e exige que a sua estrutura de diretórios e arquivos seja mantida intacta. A segunda distribuição do ERE é o birt.war, para implantação em servidores  Java EE. Basta instalá-lo no seu servidor de forma normal. Também há uma aplicação web, /WebViewerExample, que ilustra o uso do ERE embutido numa aplicação web Java EE, como alternativa à birt.war. (Veremos como usar esta opção de deployment mais adiante.) O tamanho dos runtimes do BIRT não é problema para implantação em servidores, mas pode tornar inviável embuti-lo em aplicações desktop com download pela internet. Para nosso tutorial, inicialmente você precisará somente do ERE no subdiretório  /ReportEngine. Instalando a documentação A documentação do BIRT é imprescindível para se utilizar sua API, mas não está disponível num download isolado. Para obtê-la, primeiro baixe o birt-report-framework-sdk-2.1.zip. Este pacote contém o mesmo framework que orientamos a instalar no Eclipse, mas inclui também a documentação, o código-fonte e exemplos. A documentação estará nos seguintes arquivos: • plugins/org.eclipse.birt.doc_versão /doc.zip • plugins/org.eclipse.birt.doc.isv_versão /doc.zip • plugins/org.eclipse.birt.chart.doc.isv_versão /  Criando o projeto Java Crie um novo projeto Java vazio, e copie para seu source folder raiz o arquivo carros. rptdesign que construímos na seção anterior. Em seguida, crie a classe TesteBIRT, conforme a Listagem 1. Esta classe utiliza a API do Report Engine, que não é trivial, mas também não é algo assustador. Observe que o exemplo gera um relatório em formato HTML; o Report Engine não possui uma opção para geração em formato de imagem ( java.awt.Image , GIF ou semelhante). Somente os gráficos produzidos pelo Chart Engine geram imagens. Assim, precisamos de um componente  JEditorPane do Swing para exibir o relatório. Outra opção seria usar um PDFRenderContext, que gera o relatório em formato PDF, o que poderia ser exibido numa aplicação Java através da biblioteca iText6, ou então apresentado lançando o visualizador de PDF instalado no sistema (como o Acrobat). O código da Listagem 1 funciona e ilustra o assunto discutido, mas não é igual ao que você faria (ou deveria fazer) numa aplicação real. O ideal seria encapsular partes repetitivas deste código em métodos ut ilitários. Por exemplo, você  poderia ter um ServiceLocator com um métodoque inicializa o ReportEngine , e também métodos que abrem o design e definem opções de renderização que tendem a ser iguais para todos os relatórios  produzidos por uma mesma aplicação. Utilizando parâmetros Nesta etapa, vamos modificar o re latório para utilizar parâmetros: além do Data Set, quase todos os relatórios reais precisam de argumentos que determinam opções como filtros de dados. Vamos criar um filtro para gerar relatórios que consideram apenas produtos de determinado tipo, como carros ou motos. Na database, isso exige um filtro como WHERE productLine = ‘Classic Cars’   para filtrar apenas os carros; porém, o argumento do WHERE  deve ser um parâmetro dinâmico. Na view Data Explorer, em   Report Parameters, acione New Parameter e preencha os valores: Name = “productLine”, Data type = “String” e Default value = “Classic Cars”. Isso cria um parâmetro de entrada do relatório, cujo valor deve ser setado pela aplicação antes de invocar o relatório. Agora, abra novamente o Edit Data Set. 6   O runtime do iText pode ser baixado pelo site de update do Callisto. Mas e ste componente, assim como um arquivo prototype.js para funcionalidade AJAX, não são incluídos nos runtimes do BIRT, talvez devido a restrições de licença. Devem ser baixados à parte; veja instruções na página de download do BIRT. doc.zip Ao extrair estes ZIPs, você poderá explorar a abundante API pública dos engines de relatórios, charts, de scripting e de extensão de IDE do BIRT. Observe, contudo, que todas estas APIs estão documentadas como provisórias, significando que podem sofrer alterações incompatíveis em releases futuros (ainda que, na prática, isto seja raro). Mas antes de enveredar por estes JavaDocs, comece pela página eclipse.org/birt/   phoenix/deploy/reportEngineAPI.php, que inclui diagramas que explicam a arquitetura geral do runtime e das APIs do BIRT. Figura 6. Relatório com um gráfico (inserido acima do grid). Edição 38 •  Java Magazine 27  jm38.indb 27 17/7/2006 14:11:33 Byte Code • Relatórios e Gráficos com Eclipse Listagem 1. Código Java para uma aplicação desktop mínima com o BIRT. import import import import import import java.io.File; java.io.IOException; java.util.HashMap; javax.swing.JEditorPane; javax.swing.JFrame; org.eclipse.birt.report.engine.api.*; public class TesteBIRT { public static void main (String[] args) throws EngineException, IOException { // Cria o engine (para simplificar, usamos path fixo do ERE) EngineConfig config = new EngineConfig();   config.setEngineHome(“D:/Java/BIRTRuntime/ReportEngine”); ReportEngine engine = new ReportEngine(config); // Carrega o arquivo de design IReportRunnable design = engine.openReportDesign(“carros3.rptdesign”); // Cria tarefa de renderização, configurada para para HTML IRunAndRenderTask task = engine.createRunAndRenderTask(design); HTMLRenderContext renderCtx = new HTMLRenderContext(); renderCtx.setImageDirectory(“image”); HashMap ctxMap = new HashMap(); ctxMap.put(EngineConstants.APPCONTEXT_HTML_RENDER_CONTEXT, renderCtx); task.setAppContext(ctxMap); HTMLRenderOption options = new HTMLRenderOption();     // Gera a saída num arquivo temporário File output = new File(System.getProperty(“java.io.tmpdir”), “birt.html”); options.setOutputFileName(output.getAbsolutePath()); options.setOutputFormat(“html”); task.setRenderOption(options); task.run(); engine.destroy();           // Cria um componente Swing para exibir o HTML JEditorPane htmlPane = new JEditorPane(“file:///” + output.getAbsolutePath()); htmlPane.setEditable(false); JFrame frame = new JFrame(); frame.add(htmlPane); frame.setBounds(0, 0, 640, 480); frame.setVisible(true);       // Exibe o consumo de memória do heap System.gc(); Runtime rt = Runtime.getRuntime(); System.out.println(rt.totalMemory() - rt.freeMemory());   } } Na aba Query, adicione à query a cláusula “WHERE productLine = ? ”. O ‘? ’ é o familiar indicador de parâmetro da API JDBC. Na aba Parameters, crie um parâmetro com Name = “productLine”, Data type = “String” e Direction = “Input”. Queremos que o valor deste parâmetro da query seja preenchido com o valor passado para o parâmetro productLine do relatório. São parâmetros diferentes, apesar do nome igual. Para associar um ao outro, clique em Default Value (no botão “...”), o que abre o diálogo Expression Builder, mostrado na Figura 7. O BIRT utiliza um sistema de “parâmetros em cascata”, no qual os parâmetros de um Data Set podem ser associados a valores disponíveis ou calculados num escopo mais externo, como os parâmetros do relatório. Os dois conceitos – parâmetros de relatório e de Data Set – são necessários porque um relatório pode ter vários Data Sets; os parâmetros do relatório podem ser usados em outros lugares além dos Data Sets; e os parâmetros dos Data Sets podem receber valores de outras origens além de parâmetros do relatório. Porém, o caso mais simples e comum é o de relatórios com um único Data Set e uma correspondência um-para-um entre os parâmetros. Para alimentar o parâmetro do data set com o do relatório, clique em Report Parameters ; depois na categoria ---All---, e finalmente no parâmetro {}productLine. Agora basta confirmar. O resultado é a expressão params[“productLine”]   (que você também poderia digitar à mão – o que será geralmente mais rápido após se familiarizar com o BIRT). Pronto. Se executarmos o relatório novamente, veremos que o gráfico e o grid só exibem os modelos de automóveis. Não passamos nenhum valor para o parâmetro productLine do relatório, portanto foi usado o valor default “Classic Cars”. Na aba Preview, clique em Show Re port Parameters para experimentar outros valores, como “Planes”. De volta à nossa aplicação, o cenário mais comum seria termos uma tela de seleção de parâmetros, por exemplo com um com bobox “Tipo” preenchido dinamicamente com todos os valores distintos da coluna PRODUCTLINE. Por limites de espaço, não podemos construir uma aplicação realmente completa, com uma estrutura de navegação, menus e telas de parâmetros para relatórios. Mas veremos o essencial: como definir um valor para um parâmetro interativamente. Basta alterar a classe TesteBIRT para incluir o código em destaque: ... options.setOutputFormat(“html”); task.setParameterValue(“productLine”,  JOption Pane.sh owInputD ialog ( null, “Tipo”, “Escolh a o tipo”,  JOption Pane.OK_OPTION, null, null, null)); task.setRenderOption(options); ... O novo código simula uma mini-tela de entrada de parâmetros, com uma caixa de diálogo que permite digitar o valor para o parâmetro. Executando a aplicação novamente, digite o valor “Planes” para ver um relatório dos modelos de aviões. Agora, sim, temos um relatório semelhante ao mínimo que se esperaria de uma aplicação real, com os dados de entrada variando de acordo com alguma seleção do usuário ou outra fonte.  No download deste artigo, o arquivo correspondente a esta etapa é o carros3.rptdesign. Uso em aplicações web Ainda que o BIRT dê suporte a aplicações desktop, seu maior brilho sem dúvida é no suporte a relatórios web. Para integrar o Report Engine numa aplicação web, você tem duas opções: instalar no container o birt.war, ou integrar ao WAR da sua aplicação os arquivos do Report Engine. A segunda opção é bem mais complexa, mas pode-se come- 28  Java Magazine • Edição 38  jm38.indb 28 17/7/2006 14:11:39 çar mais facilmente copiando o conteúdo do WebViewerExample  (prática familiar à cópia do struts-blank por desenvolvedores que usam o framework Struts). O uso do birt.war é bem mais simples e permite o compartilhamento do engine por diversas aplicações. Por outro lado, aplicações mais sofisticadas, especialmente aquelas com relatórios contendo scripts complexos que acessam classes Java da aplicação, irão preferir a implantação integrada, que facilita o acesso a estas classes. Vimos que a API do BIRT pode ser configurada para gerar relatórios em formato HTML, bastando então determinar o nome do arquivo e seu subdiretório de imagens, gerar o arquivo, e devolver ao cliente a URL do arquivo gerado. Isso é possível, mas tem desvantagens sérias, como gerenciar estes arquivos: deve-se evitar conflitos com outros arquivos de relatórios produzidos por usuários concorrentes, e os arquivos devem ser deletados após a visualização. Assim, em geral, esta opção de geração de relatório em arquivo só é boa para tarefas de geração em batch, ou para aplicações que já possuam mecanismos de produção e gerenciamento dinâmico de conteúdo (como ferramentas CMS). Para a maioria das aplicações, recomenda-se usar o servlet do Report Engine. Se você examinar a janela do Preview, descobrirá que o relatório é gerado invocando-se uma URL como: Para mais detalhes sobre o uso do viewer, consulte: eclipse.org/birt/phoenix/deploy/  viewerUsage.php. Scripting Como vimos, podemos ir longe no BIRT só com cliques do mouse. No outro extremo, é possível utilizar suas APIs Java para customizar a construção e a geração de relatórios ou gráficos de uma forma mais dinâmica do que seria possível somente com documentos .rptdesign estáticos. Mas a virtude, já diziam os antigos, pode estar no meio, ou seja, entre quaisquer opções extremas. O BIRT possui um abrangente suporte a scripting, permitindo que muitos recursos avançados sejam implementados com pequenos trechos de código embutido nos documentos .rptdesign. É suportada  JavaScript, linguagem que será familiar para muitos desenvolvedores de interfaces gráficas baseadas na web. Para mais detalhes sobre o suporte a scripting do BIRT, veja o quadro “Scripting no BIRT e no Eclipse”. Com a aplicabilidade dos scripts é muito ampla, vamos ilustrá-la com uma seleção de exemplos. Colunas calculadas Nossa primeira tarefa é gerar no Data Set uma coluna calculada. Ou seja, uma coluna cujo valor não é uma cópia direta de uma coluna retornada pela query, mas sim o resultado de uma expressão arbitrária (possivelmente envolvendo dados retornados pela query). Vamos demonstrar isso com uma coluna Avaliacao, cujo valor será “caro” ou “barato”, conforme o preço do modelo. No diálogo Edit Data Set, abra a aba Com puted Columns. Na primeira linha em branco, digite Column name = “Avaliacao” e Data Type = “string”. Na célula Expression, clique o botão “...” para abrir o diálogo Expression Builder. Então, clique em Avaliable Data Sets  / carros / Preço  para selecionar a coluna de preço. Um duplo-clique irá inserir a expressão row[“Preço”]  na área de edição da expressão. O Expression Builder permite criar expressões complexas sem usar o teclado – há botões para cada operador e listas de seleção para as colunas (como a que usamos), parâmetros, funções do JavaScript e do BIRT, e também para operadores. Mas como somos programadores de verdade, vamos terminar de digitar esta expressão à mão: row[“Preço”] >= 50 ? “caro” : “barato” Esta expressão (que é um mini script http://127.0.0.1:52939/viewer/run?__report=E%3A%5 COsvaldo%5Ctestws%5CBIRTJava%5Ccarros4.rptdesign& __format=html&__svg=false&__designer=true&_ _masterpage=true& __rtl=false&__maxrows=&1486415089 Aqui viewer  é o contexto de instalação do Report Engine e run é o nome do servlet de geração de relatórios; o parâmetro report contém o path completo do arquivo de design do relatório, e os demais parâmetros são as opções para o relatório. Parâmetros iniciando por dois sublinhados, como __svg, são opções do viewer. Já os parâmetros do relatório podem ser passados de forma normal, por exemplo “productLine=Planes”. Tudo que a aplicação precisa fazer, após permitir ao usuário selecionar valores para os parâmetros de um relatório, é montar a URL exigida pelo viewer. Figura 7. Parâmetros em cascata no Expression Builder. Edição 38 •  Java Magazine 29  jm38.indb 29 17/7/2006 14:11:42 Byte Code • Relatórios e Gráficos com Eclipse  JavaScript) será executada, para cada linha do Data Set, produzindo a coluna “Avaliacao”. Se clicarmos na aba Preview Results, veremos a nova coluna preenchida com valores, como na Figura 8. Poderíamos, então, utilizar esta coluna no relatório, da mesma forma como fize- mos para colunas “reais”. De que outra maneira poderíamos ter obtido o mesmo efeito? Se você voltar ao design do Grid (o componente de relatório tabular) e der u m duplo-clique na célula de detalhe da coluna Preço, verá o diálogo Select Data Binding. Observe que, neste diálogo, a coluna Preço Scripting no BIRT e no Eclipse A versão atual do BIRT suporta JavaScript (ECMAScript). Versões futuras deverão suportar outras linguagens de scripting para a JVM (como Groovy, Jython etc.), possivelmente através da JSR-223. Há anos a comunidade Eclipse vem discutindo a implementação de facilidades de scripting para o Eclipse como um todo, para automatizar qualquer operação do IDE e de todos os seus plug-ins. A falta dessas facilidades é uma das principais lacunas do Eclipse, para usuários avançados que gostam de automatizar seu trabalho com scripts. Essa deficiência já vem sendo investigada por projetos na incubadora da Fundação Eclipse (como o EclipseMonkey), além de projetos externos (como o EclipseShell). Sem falar em ferramentas que incluem suporte ad-hoc para scripting, como o próprio BIRT. A Fundação parece ter demorado para levar o assunto a sério, devido à grande ênfase do Eclipse no desenvolvimento de plug-ins. Mas mesmo uma ferramenta poderosa como o PDE não supera a facilidade de escrever scripts, que permitem inclusive cenários de “programação zero” (macros gerados pela captura de ações do usuário no IDE). Mas agora os scripts estão na moda, ganhando suporte até da plataf orma Java SE (ver JSR-223,  já incluída no Mustang, e a JSR-292). O Eclipse precisa de um suporte robusto e unificado a scripting, compartilhado por todas as ferramentas que possam se beneficiar de scripts, e suportando várias linguagens. O assunto foi discutido num painel da EclipseCon 2006, e provavelmente será materializado numa solução definitiva no Eclipse 3.3. O suporte a scripting não requer somente fazer a interface entre Java e o runtime de alguma linguagem de scripting – problema que a JSR-223 já padroniza e resolve. Boa parte do esforço é a definição de um Object Model (OM) que represente, de uma forma simples, os dados e funcionalidades do ambiente; ou seja, a plataforma Eclipse, os plug-ins instalados e os recursos gerenciados por estes plug-ins. O BIRT já faz isso para o ROM (Report Object Model, isto é, a representação em memória do documento .rptdesign ), o que permite ao script utilizar sintaxes especiais como row[nome] e params[nome ] para acessar elementos do ROM. E vai mais além: é possível escrever scripts com expressões como sum(row.BUYPRICE) , onde sum é uma função agregada semelhante à do SQL. Ela retorna a soma dos valores da coluna BUYPRICE  para todas as linhas (rows) do Data Set. Esta sintaxe não é suportada por JavaScript, mas como linguagens de scripting são por natureza fáceis de manipular, o BIRT pode criar extensões desse tipo com facilidade 8. O BIRT também permite invocar classes Java a partir do relatório. Não abordamos essa funcionalidade neste artigo, mas é uma opção bem mais complexa. O código Java não tem os benefícios do Report Object Model ou de extensões de sintaxe, sendo obrigado a utilizar APIs do BIRT, ex.: task. getParameterValue(“productLine”) . Estas APIs priorizam flexibilidade e desempenho sobre a facilidade de uso, e na versão 2.1 ainda não são APIs estáveis (com garantia contra mudanças incompatíveis em releases futuros). Em geral, você só utilizar á Java no lugar de JavaScript se tiver necessidades especia is de integração, como reusar métodos de al guma biblioteca Java. Ou de desempenho, como calcular um Data Set muito complexo (o que pode ser feito em JavaScript, mas com menos desempenho, por ser uma linguagem interpretada). 8  Ou seja, os scripts do BIRT não são realmente JavaScript puro, e sim uma extensão. Mas o BIRT faz um pré-processamento que trata estas extensões e gera código JavaScript comum, compatíveis com runtimes de JavaScript padrão, como o Mozilla Rhino. é associada à expressão dataSetRow[“Preço”]. Clicando nesta ex pressão, veremos novamente (sem muita surpresa) o Expression Builder. Agora, se você selecionar o gráfico e acionar Select Data, examinando com novos olhos esta aba do diálogo Edit Chart (Figura 4), verá que existem scripts por todo lado. Por exemplo, o campo Category (X) Series tem o valor row[“Fabricante”] – um script. O mesmo vale para as opções de valor Y, agrupamento e colunas de dados para o eixo X. Embora a prática mais comum seja derivar todos estes dados de colunas do Data Set, pode-se, no lugar disso, escrever código JavaScript arbitrário. Poderíamos ter criado no Grid a expressão que transforma um preço na string “caro” / “barato”. Mas se definirmos esta expressão no próprio Data Set, o valor resultante pode ser reusado em vários lugares; por exemplo, podemos querer exibir esta informação tanto no Grid quanto no gráfico. Calculá-la uma vez só, no Data Set, economiza tanto o esforço de edição do relatório, quanto tempo de processamento. Uma terceira alternativa para gerar valores calculados seria fazer o cálculo na própria query do Data Set; por exemplo: SELECT PRODUCTNAME, PRODUCTVENDOR, PRODUCTDESCRIPTION, BUYPRICE, ( CASE WHEN BUYPRICE >= 50 THEN ‘caro’ ELSE ‘barato’ END) AS AVALIACAO FROM PRODUCTS ORDER BY PRODUCTVENDOR, PRODUCTNAME Este tipo de programação é comum quando são usados geradores de relatórios sem capacidade de scripting. Porém apresenta alguns problemas. A sintaxe “CASE” usada no exemplo é uma extensão SQL de um SGBD específico, e mesmo essa sintaxe não permitiria implementar cálculos mais complexos (por exemplo, qualquer cálculo exigindo um loop). A solução poderia ser o uso de procedimentos armazenados (que o BIRT também pode invocar para gerar um Data Set), mas esta prática também tem seus inconvenientes, como baixa portabilidade. Além disso, transferir colunas 7  Este artigo de Joel Spolsky diz tudo sobre a questão “aparência versus funcionalidade”:  joelonsoftware.com/articles/fog0000000356.html  30  Java Magazine • Edição 38  jm38.indb 30 17/7/2006 14:11:44 calculadas no SGBD consome banda de rede desnecessariamente. É muito mais eficiente fazer uma query que retorna somente os dados brutos, e gerar os valores calculados localmente. Customizações de layout  Vamos a uma outra necessidade importante de relatórios “caprichados”: modificar dinamicamente a apresentação dos dados, para destacar informações importantes. Nunca esqueça que você é pago (principalmente) para fazer suas aplicações parecerem boas!7 Digamos que você queira que as linhas do Grid que exibem os modelos mais baratos sejam exibidas em negrito. Para fazer isso, selecione o manipulador da linha, e vá na aba Property Editor / Highlights, que permite definir regras de destaque. Clique em  Add, trazendo o diálogo New  Highlight; no primeiro campo, If following condition is true, clique o botão “...”. Lá está mais uma vez o Expression builder. Crie a expressão row[“Preço”]. De volta ao New  Highlight, no segundo combobox (para a seleção de operador) escolha Less than; e no terceiro campo, que também aceita uma expressão, digite 50. Agora, no grupo Then apply following formatting, clique no segundo botão “B” (bold); veja a Figura 9. Pronto, basta confirmar e testar novamente o relatório. O Report Engine procura oferecer uma GUI que permita fazer tudo com o mouse, selecionando opções predefinidas mesmo na edição de scripts. Usuários mais experientes, que conheçam JavaScript e já tenham aprendido palavras-chave como row e params, poderão ignorar esta interface gráfica e digitar as expressões diretamente. No caso do highlight, acho mais fácil digitar um único script no primeiro campo – row[“BUYPRICE”] < 50 – e deixar os outros como “Equals to” e “true”. Figura 8. Data set com uma coluna calculada por scri pt. Figura 9. Editando uma regra de destaque. No download deste artigo, o arquivo correspondente a esta etapa é o carros4.rptdesign. Data sources de script  Você já deve ter observado que o BIRT só gera relatórios a partir de algum Data Source; não existe uma opção de passar ao gerador uma coleção de objetos Java, como os datasets do JasperReports e do Figura 10. Definição de colunas para o data set de scripted data source. Edição 38 •  Java Magazine 31  jm38.indb 31 17/7/2006 14:11:45 Byte Code • Relatórios e Gráficos com Eclipse  JFreeChart. Mas o princípio do BIRT é explorar a generalidade do conceito de Data Source, que não precisa necessariamente ser uma fonte de dados relacional. Ao criar um Data Source, você deve ter observado que existem opções de flat files (arquivos CSV – texto com campos separados por vírgula), e XML (que usam expressões XPath para extrair um Data Set tabular de um documento XML qualquer). Estas opções são muito interessantes para a integração entre aplicações através de arquivos. Mas ainda mais poderosa é a opção de scripting. Crie um novo Data Source, com o tipo Scripted Data Source e nome “scriptDS”. Na aba Script do editor, você verá que o BIRT permite definir cinco métodos: open, close, beforeOpen, beforeClose, afterOpen e afterClose. Pode ser preciso redefinir estes métodos, por exemplo, para abrir e depois fechar uma conexão com um sistema externo. Neste exemplo, não precisaremos disso. Crie um Data Set chamado “senoidal” para este Data Source. Você verá que o diálogo Edit Data Set é mais simples que no caso de JDBC: não há query, somente colunas calculadas (na aba Output Columns). Crie duas novas colunas, angulo e seno, ambas com o tipo Float. Veja a Figura 10. Observe que o diálogo não permite a entrada de expressões para calcular o valor destas colunas, o que pode parecer estranho. Mas faz sentido, pois nosso Data Set não possui colunas de dados “primárias” a partir das quais as colunas calculadas possam ser derivadas (no caso de Data Sets  JDBC, estas colunas seriam as do resultset da query ou stored procedures. O Scripted Data Source exige o uso de scripts para tudo, inclusive para determinar quantas linhas existem, portanto, sua configuração é um pouco diferente. Na view Data Explorer, deixe o Data Set senoidal selecionado; agora, na view do .rptdesign (área central), clique na aba Script. Você verá um combobox no topo, listando todos os métodos disponíveis para o script do Data Set. Entre com o seguinte código. Para o método open: x = 0.0; E para o método fetch: if (x < 8) { row[“angulo”] = x; row[“seno”] = Math.sin(x); x = x + 0.01;  return true; } else return false; Figura 11. Data Set totalmente baseado em scripting, com o código que gera cada nova linha. Figura 12. Chart gerado a partir do data set  senoidal , calculado por um script. Para compreender a programação de um Data Set baseado em script, basta pensar que ele funciona como um  java.util.Iterator. O método open  inicializa o Data Set, e o método fetch  retorna true  se existir mais uma linha, ou false se não houver mais linhas. Além disso, o fetch deve também setar os valores de todas as colunas para a próxima linha (se houver). No nosso exemplo, queremos calcular os senos de todos os ângulos entre 0 e 8 radianos (i.e., de 0 e 1.440 graus, ou 4 voltas na circunferência trigonométrica), com incrementos de um centésimo de radiano (3,6 graus). (Utilizamos valores fixos para o ângulo inicial, final e incremento, mas poderíamos facilmente ter criado parâmetros do Data Set para estes valores.) Para fazer isso, usamos uma variável de estado do Data Set, a variável x, iniciali- 32  Java Magazine • Edição 38  jm38.indb 32 17/7/2006 14:11:48 zada no open. O valor desta variável será preservado entre as invocações de método: funciona como um atributo, não como uma variável local. O método fetch atualiza este x até chegar ao valor máximo, e se ainda não tiver chegado, calcula as colunas angulo e seno para a linha sendo retornada. Veja na Figura 11 o Report Designer durante a edição de scripts. Na Figura 12 é mostrado um relatório que podemos construir facilmente (exercício para o leitor!) utilizando este Data Set. Finalizamos observando que, embora este exemplo seja um caso extremo – o script gera o Data Set de forma completamente sintética, sem ler nenhuma fonte de dados externa – é mais comum que este recurso seja utilizado para ler dados de fontes que não sejam suportadas diretamente pelos Data Sets comuns do BIRT. Por exemplo, se os seus dados exigem fazer uma consulta a um EJB, ou uma query do Hibernate – ou quem sabe invocar DAOs  Java que montam queries JDBC – pode-se usar scripts para acessar tais dados. No download deste artigo, o arquivo correspondente a esta etapa é o senoide.rptdesign. Interatividade e ações drill-through Relatórios complexos devem não só exi bir dados, mas também permitir ao usuário navegar por esses dados. Por exemplo, ao visualizar o relatório de preços por fabricante, seria ótimo poder clicar na Escolha Type = “Mouse Click” e Action = coluna correspondente a um fabricante e “URL Redirect”. Clique no botão Edit Base imediatamente visualizar um outro relaURL, que abre o diálogo Hyperlink Options tório de preços por fabricante. Este tipo de (Figura 13). Existem vários tipos de links. funcionalidade é excelente para o usuário Você poderia, por exemplo, querer que final, pois evita a necessidade de voltar um clique na coluna de um Vendedor dia um menu de relatórios, escolher outra recionasse o usuário à página de cadastro opção e preencher muitos critérios de filtro daquele fabricante; bastaria então entrar iguais aos do relatório anterior. Já para com sua URI (que pode ser gerada dinao programador, implementar recursos micamente). Mas no nosso caso, queremos como este costuma ser bastante trabalhoso, especialmente em interfaces web, devido à dificuldade de programar qualquer tipo de interatividade envolvendo gráficos – o que exige a geração dinâmica de image maps. Felizmente, o BIRT torna funcionalidades como essas relativamente simples. Vamos ao nosso exemplo. No carros.rptdesign, volte à aba Layout, clique duas vezes no gráfico, mude para a aba Format Chart e selecione Series / Value (Y) Series. Clique no  botão Interactivity, que abre um dialogo de mesmo nome. Observe (nos combos Type e  Action) que o BIRT suporta vários tipos de eventos de mouse, foco, teclado etc., e diversos tipos de ações, como exibir uma tooltip, ocultar/exibir, destacar, ou invocar um script (que pode fazer praticamente qualquer coisa). Figura 13. Editando opções de drill-through. Configurando a memória para o BIRT O Report Designer é um ambiente pesado, e após um OutOfMemoryError, você pode querer aumentar o limite de tamanho do heap da JVM que executa o Eclipse. Isso pode ser feito adicionando ao atalho ou script que inicia o Eclipse (ou ao eclipse.ini ) as opções “-vmargs –mxXXXm” onde  XXX é o número de Mb. No entanto, esta configuração pode não funcionar, mesmo com um tamanho de heap enorme. O problema não é do Eclipse (embora haja vários bugs do Eclipse.org discutindo o assunto), e sim da JVM da Sun. É que o HotSpot possui uma região especial de memória, a “geração permanente” (PermGen), onde são alocadas classes e strings internalizadas, mas o tamanho máximo default desta região de memória é insuficiente para o Eclipse 3.2 com o BIRT (e outros plug-ins pesados, como o WTP e AJDT). O problema é contornado com outra opção do HotSpot: -XX:MaxPermSize=128m, que configura o limite máximo da PermGen. Nem é necessário usar o -Xmx. Outra solução é utilizar JVMs alternativas, como as da IBM e da BEA, que não apresentam esta limitação. Quando você ler este artigo, atualizações do BIRT, Eclipse SDK e JDK p odem ter contornado o problema de forma transparente (na dúvida, adicione esta opção somente se observar erros “java. lang.OutOfMemoryError: PermGen space”). Este problema não é exclusividade do Eclipse ou do BIRT; tem atingido outras aplicações Java peso-pesadas em número de classes. A solução é sempre a mesma: o NetBeans 5, por exemplo, aciona automaticamente a opção -XX:MaxPermSize=160m . Resta perguntar: por que o Eclipse + BIRT utilizam tanta memória para código? A funcionalidade do BIRT é impressionante, mas creio que a resposta é, em boa parte, a arquitetura nada leve utilizada pela solução como um todo. Quando você f az um preview do relatório, o BIRT carrega (na mesma JVM do Eclipse) não só todo o código do Report Engine, mas também o de suas dependências, incluindo o Mozilla Rhino, o Apache Axis, o Apache Tomcat (usado só para servir o relatório HTML para o preview!), e se estiver sendo usado o Data Source de teste “Classic Cars”, até o servidor Apache De rby embutido. Edição 38 •  Java Magazine 33  jm38.indb 33 17/7/2006 14:11:49 Byte Code • Relatórios e Gráficos com Eclipse BIRT, outros geradores de relatórios, e open source E xistem diversos geradores de relatórios puro-Java. As opções open source mais tradicionais são o JasperReports (gerador de relatórios) e iReport (editor visual de relatórios do JasperReports), cobertos nesta e na edição anterior, e o gerador de gráficos comerciais JFreeChart, tratado nas edições 24 e 25. As perguntas que podem est ar na mente de muitos leitores são: Qual é o melhor? Vale a pena migrar para o BIRT? Passados dois anos, JasperReports, iReport e JFreeChart continuam disponíveis, melhorando continuamente, e agora também contam com suporte comercial. Este é um mercado que está se expandindo, tornando-se muito mais competitivo, e sofrendo uma forte “comoditização” das funcionalidades básicas. As seguintes tendências recentes são críticas para esta competição: • Integração com IDEs. Com o sucesso de “plataformas de IDE” como o Ecli pse e o NetBeans, ferramentas visuais e integradas não são mais um l uxo – são essenciais. A vantagem de produtividade de um ambiente não só visual, mas totalmente integrado ao IDE, é evidente. •  Suporte a recursos de B.I. (Business Intelligence). Isso significa capacidades de análise e apresentação de dados mais avançadas; recursos “enterprise” como relatórios agendados, segurança, alta escalabilidade (clustering e caching), OLAP, suporte total à plataforma JEE (ex. : EJB e JCA) etc. Os recursos mais high-end nestes grupos podem não estar presentes em produtos open source ou gratuitos, mas todos os competidores adotaram a mesma estratégia, oferecendo produtos comerciais mais avançados e/ou serviços e suporte. A Actuate, empresa que criou e é a principal contribuinte do BIRT, oferece o Actuate BIRT. O produto é o mesmo; somente os serviços e suporte comerci al se diferenciam. A JasperSoft, empresa estruturada para desenvolvimento e suporte comercial do JasperReports e iReport, tem uma linha de produtos co merciais de BI. Já a Infologic produz o JasperAssistant, editor de JasperReports integrado ao Eclipse (que apesar do nome, não tem relação com a JasperSoft; é um produto comercial e de código fechado). A Pentaho oferece seu BI Suite, produto que já suporta dois engines de relatórios: JasperReports e o BIRT. Mas recentemente, a Pentaho “adotou” os projetos do JFree.org (JFreeChart e JFreeReport), que devem tornar-se preferenciais. Também não podemos desprezar a vantagem do BIRT como solução de BI oficial da Fundação Eclipse. O BIRT faz parte da distribuição integrada Callisto. É suportado por outros pesos-pesados como a IBM (que, imagino, deve estar ansiosa para excluir de seus IDEs comerciais o Crystal Reports, e parar de pagar licenças à Business Objects). No seu primeiro ano de vida pós-1.0, o BIRT já se tornou um dos sucessos da Fundação Eclipse, e é cada vez mais um diferencial competitivo. Nenhum outro IDE gratuito / open source para Java inclui capacidade nem remotamente semelhante. Por outro lado, antes de migrar cegamente de uma tecnologia que você já conhece para outra que ainda não domina, avalie bem a novidade, considerando suas necessidades particulares. Uma vantagem do JFreeChart, por exemplo, é a riqueza de recursos e grande flexibilidade de extensão, que permite customizar gráficos praticamente sem limites – ainda que a um custo de escrever muito código Java. BIRT e open source O projeto BIRT já foi criticado pela forma como entrou no mundo open source. O projeto foi uma iniciativa da Actuate, empresa do ramo de BI que ainda não tinha presença especificamente no segmento de ferramentas Java, e viu a oportunidade de ganhar este mercado “doando” ao Eclipse.org todo o desenvolvimento do BIRT. Mas por que a Actuate tinha que criar geradores de relatórios e de gráficos completamente novos, com tantas opções previamente existentes? Em parte isso parece ser um modus operandi da Fundação Eclipse, que já começa com o produto básico, o IDE, criado da mesma maneira pela IBM, sem ligar para os projetos de IDE Java open source anteriores. A Fundação incorpora, talvez emblematicamente, uma nova modalidade de open source desenvolvido primariamente por grandes empresas, que procura combinar vantagens de modelos extremos9. E é difícil não perceber as vantagens: nunca ouvimos falar que uma funcionalidade de um projeto do Eclipse.org não é implementada por “falta de recursos”, ou que a nova versão terá seu release de produção “quando estiver pronta”. Não é só o Eclipse. Este novo mo vimento “open source corporativo” inclui outros projetos – qualquer um onde 90 % dos desenvolvedores sejam pagos pela mesma empresa, o que inclui vários pro jetos open source famosos (IDEs , sistemas operacionais, servidores Java EE etc.) . Recomeçar do zero às vezes é bom ou mesmo necessário. A arquitetura do BIRT me parece superior à do JasperReports e do JFreeChart (embora esta impressão possa ser viciada pela documentação do BIRT, que é formal, vasta , de alta qualidade e gratuita). E sendo um projeto integrado à plataforma Eclipse, o BIRT é obrigado a fazer uso intenso de vários componentes desta plataforma, incluindo a SWT, JDT, EMF e GEF, portanto, seria dif ícil reutilizar muito código de projetos anteriores. Um fato interessante é que o BIRT pretende estabelecer um padrão com seu ROM (Report Object Model), que, lembrando, é o modelo dos s eus arquivos .rptdesign e dos objetos do relatório visíveis por scripts e APIs (algo semelhante ao DOM para documentos HTML). Talvez esta iniciativa não tenha sucesso – os competidores ainda não estão correndo para implementar compatibilidade com o ROM. Mas é importante devido ao esforço por trás do design e documentação desse modelo, e também porque facilita a integração do BIRT com outros projetos do Eclise.org e plug-ins de terceiros. Tra- 34  Java Magazine • Edição 38  jm38.indb 34 17/7/2006 14:11:51 duzindo: o BIRT não é só um gerador de relatórios, é uma plataforma. E na medida em que esta plataforma atrair o interesse de muitos desenvolvedores de soluções complementares, isso pode transformar o BIRT (ou pelo menos seu ROM) num padrão de fato. Não vejo as práticas de desenvolvimento do BIRT como nada de excepcional. O projeto JasperReports também é mantido por uma empresa com interesses comerciais, que aliás oferece produtos proprietários mais avançados. Quanto à duplicação de funcionalidades, os autores do JFreeChart também criaram o JFreeReport, um engine de relatórios simples, concorrendo com o JasperReports. Não se trata necessariamente de falta de colaboração: muitas vezes os líderes destes projetos podem ter motivos técnicos para criar um projeto novo, como preferir uma arquitetura diferente, ou desejar uma solução mais simples e leve (ou mais completa e ambiciosa). Ou ainda, ter em vista a evolução para um modelo de open source com exploração comercial, o que é um objetivo perfeitamente legítimo. Em qualquer caso, a proliferação de projetos open source na mesma categoria não é necessariamente um mal, pois também há vantagens na diversidade e na competição. O JasperReports e JFreeChart avançaram muito em comparação com a última vez que os utilizei seriamente (há cerca de dois anos). Ambos atingiram as versões “1.0”, com promessa de estabilidade de API, após anos de atualizações 0.x com quebras arbitrárias e freqüentes de APIs. E o JasperReports e iReport ganharam integração com a JFreeChart. Enfim, se a ameaça do BIRT tiver servido para agilizar estas melhorias, os desenvolvedores que continuarem preferindo estas outras opções só têm a agradecer. 9   Ver bazaar/  www.catb.org/esr/writings/cathedral- invocar outro relatório; então, escolha o tipo Drill-through, que é como é conhecida esta ação de navegar entre relatórios distintos, mas relacionados. O diálogo exibido permitirá selecionar o relatório de destino, bem como várias opções para invocá-lo (como seus parâmetros). Selecione o parâmetro productVendor (a coluna Parameters  já disponibiliza os parâmetros exigidos pelo .rptdesign de destino). Em Values, digite a expressão row[“Fabricante”] , para passar para este parâmetro o valor da coluna Fabricante no contexto de ocorrência do evento – ou seja, o fabricante associado à barra clicada. Clique no botão Ok e, de volta ao diálogo Interactivity, clique em  Add para inserir a nova ação na lista à esquerda.  Está feito. É só testar (omitimos somente as instruções para criar o relatório por fabricante; mas este é parecido com o relatório por tipo de produto, variando apenas as colunas filtradas e selecionadas). O suporte a scripts e eventos do BIRT também pode ser utilizado para implementar ações de drill-down (gerar o mesmo relatório com dados mais filtrados), para validar parâmetros, e outras operações. No download deste artigo, os arquivos correspondentes a esta etapa são carros5.rptdesign (relatório base) e carros5porFabricante.rptdesign (relatório filho).TTR Conclusões Este artigo pretendeu dar uma introdução abrangente ao BIRT, mas o enorme volume de recursos deste gerador de relatórios só nos permitiu abordar os itens mais essenciais ou interessantes. Ficou faltando falar de muitos outros itens, que enumeramos aqui para completar uma visão geral das capacidades do BIRT: • Relatórios tabulares (em grids) mais complexos, com agrupamentos, cabeçalhos e rodapés; • Localização/Internacionalização; • Refinamentos de layout: suporte a CSS, quebra de página, índices, bookmarks etc.; • Recursos de filtro e ordenação (geralmente desnecessários para Data Sets  JDBC que podem usar WHERE e ORDER, mas necessários para outros Data Sets); • Mapas (tabelas "de/para"); • Outros componentes importantes, como List, Image e Dynamic Text; • Páginas-mestre; • Libraries, que permitem reutilizar definições comuns (como datasets e páginas-mestre) entre vários relatórios semelhantes; Também não tivemos espaço para falar em desempenho, mas o BIRT possui uma característica muito importante que é seu cache de relatórios, que faz com que invocações freqüentes aos mesmos relatórios, com mesmos parâmetros, não exijam a repetição de todo o processamento de geração do relatório (especialmente a query ao SGBD). Esta funcionalidade muito importante faz falta em alguns geradores de relatórios, obrigando desenvolvedores de aplicação a implementar mecanismos de cache ad-hoc, tarefa que é bastante complexa e arriscada. Os recursos que pudemos explorar neste artigo já cobrem a funcionalidade de relatórios exigida por muitas aplicações, e mais importante que isso, devem ilustrar bem o ciclo de trabalho com o BIRT, e seus pontos fortes (como a facilidade de desenvolvimento) e fracos (como o tamanho do runtime). Tenha em mente este conjunto total de funcionalidades para comparar o BIRT a outras opções. O BIRT certamente será uma excelente alternativa para muitas aplicações, e considerando sua facilidade de uso, é baixo o investimento de tempo para aprender o restante de suas funcionalidades. eclipse.org Projeto Eclipse. eclipse.org/birt/phoenix/ref  Referência do BIRT  jasperreports.sf.net  JasperReports, gerador de relatórios open source  javamagazine.com.br/downloads/jm38/   jm-birt.zip Osvaldo Pinali Doederlein ([email protected]) é Mestre em Engenharia de Software Orientado a Objetos, membro individual do Java Community Process (tendo participado do Expert Group da JSR-170: Tiger/J2SE 5.0), e trabalha na Visionnaire Informática como arquiteto e desenvolvedor. Edição 38 •  Java Magazine 35  jm38.indb 35 17/7/2006 14:11:53 Mais relatórios Pas Totalizações e gráficos com iReport e Jaspe N o artigo “Relatórios na Web Passo a Passo”, publicado na edição anterior, apresentamos o JasperReports e o iReport e mostramos como criar um relatório mestre-detalhe completo, que lista detalhes dos pedidos de clientes. Neste artigo, vamos incrementar esse relatório inicial definindo grupos e acrescentando diversas totalizações. Tam-  bém mostraremos como criar e configurar gráficos no relatório Sobre o projeto de exemplo O projeto utilizado neste artigo permite a execução de um relatório a partir de uma aplicação web. Ele é baseado em quatro entidades principais: pedidos, itens de pedido, clientes e produtos. Os dados do relatório são obtidos a partir de um banco MySQL, e o modelo de dados é mostrado na Figura 1. A Figura 2 representa o resultado final desse relatório e o quadro “Como criar o relatório inicial” resume os passos para a criação. O projeto inicial completo, com todas as classes necessárias, os templates de relatorio.jrxml e o script para criação do  banco de dados, está disponível no site da Java Magazine. Os leitores que não acompanharam o artigo na edição anterior poderão obter esse exemplo pronto, e partir dele para realizar as mudanças detalhadas aqui. Será disponibilizado no download tanto o projeto inicial, como o projeto final, resultado das alterações feitas neste artigo. Agrupando pedidos por cliente Repare na Figura 2 que, quando um cliente tem diversos pedidos, os dados do cliente (no caso, o nome) aparecem repetidos para cada pedido. Vamos melhorar o relatório, agrupando todos os pedidos de um cliente e imprimindo somente uma vez os seus dados. Precisamos definir um  grupo  para fazer quebra de pedidos por cliente. Quando um grupo é criado no  Jas perReport s, automaticamente são criadas duas novas bandas: nomegrupo Header e nomegrupoFooter (por exemplo, clienteHeader e clienteFooter). Colocamos nestas bandas as informações associadas ao grupo, que neste caso são o nome e o valor total do cliente; já os dados de cada item do grupo permanecem na  banda detail (são eles os pedidos e os itens de pedido do cliente). Também é preciso definir uma expressão de agrupamento, que é utilizada pelo  JasperReports para fazer a quebra do gru36  Java Magazine • Edição 38  jm38.indb 36 17/7/2006 14:11:58 Aprenda a definir agrupamentos agrupament os e calcular totais em vários níveis, num relatório mestredetalhe, e como criar gráficos de resumo so a Passo r Reports ANA ABRANTES E YARA SENGER po. Usamos o nome do cliente. Para que os grupos sejam apresentados da maneira esperada, é preciso que a fonte de dados também esteja ordenada corretamente, correta mente, ou seja, a consulta SQL deve ter a cláusula “order by” (ou se for usado u sado um datasource de JavaBeans, deve-se passar uma coleção com os objetos já ordenados de forma compatível com os grupos desejados, neste caso o nome do cliente). Pode haver vários grupos “aninhados”; por exemplo um grupo Região, que englo ba todos os clientes de uma u ma determinada região; dentro deste um grupo Estado, e assim por diante. Quando o grupo mais “externo”” for reinicializado, “externo reinicia lizado, todos os grupos contidos nele também o serão. se rão. Os passos para a criação do grupo são os seguintes: 1. No iReport, abra o arquivo do relatório, RelatorioPedidos.jrxml. 2.  Clique no ícone de grupos na barra de ferramentas, e depois em New. Na janela que aparece, configure o grupo conforme a Figura 3 e clique em OK . 3 .   Mova o textfield que mostra o nome do cliente da  ba nd a detail   para a banda clienteHeader, que acabou de ser criada. Na aba Text Field  das propriedades do textfield, altere a Textfield expression para: Figura 1. Modelo de dados do projeto de exemplo. “Cliente:“+$F{nomeCliente} 4.   Na banda detail, apague o elemento static text com a descrição “Cliente”. Este texto não será mais necessário, pois o nome do cliente só aparece uma vez para cada grupo. 5. Como iremos agrupar os pedidos por cliente, a fonte de dados deve ter os dados ordenados por algum campo do cliente que o diferencie; no nosso caso a consulta SQL deve ter a cláusula cl áusula “order by c.nome”. Desta forma, à medida que o JasperReports Como criar o relatório inicial S iga estes passos para criar os relatórios que utilizaremos e que foram criados conforme o último artigo. 1. Crie um banco de dados de nome “ecommerce” no MySQL conforme o diagrama na Figura 1; 2. Abra o iReport; 3. Crie um novo relatório chamado “RelatorioPedidos”; 4. Defina a conexão de dados a ser usada; 5.  Configure a consulta do relatório com a seguinte string SQL: SELECT p.data, p.numero, c.nome as nomeCliente FROM pedidos p JOIN clientes c ON p.id_cliente = c.id ORDER BY p.numero 6. Somente as bandas  pageHeade r , detail  e  serão usadas; as demais devem ser  pageFooter  serão desativadas zerando-se sua band height ; 7.  Insira os elementos textfield (com os campos do datasource), static text, imagem e subreport até que o relatório fique com a aparência da primeira imagem da Figura 2; 8.   Crie os parâmetros subReport   do tipo net.sf.jasperreports.engine.JasperReport   para serem passados o arquivo do sub-relatório e  pageRoot  do  do tipo java.lang.String  para o caminho do projeto quer será usado na localização de imagens e outros recursos; 9.  Nas propriedades do elemento subre po rt , em Connection/Datas Connection/Datasource ource expression, coloque Use connection expression , em Subreport expression coloque $P{subReport} e Subreport Expression Class  igual a net.sf.jasperreports.engine.JasperReport; em Subreport parameters  adicione um parâmetro de nome numeroPedido  com Default value expression  igual a $F{numeroPedido}; 10. Crie um novo relatório chamado Rela- torioItens ; 11.. O relatório não deve ter margens, e so11 mente as bandas columnHeader  e  e detail  serão   serão usadas; as demais devem ser desativadas zerando sua band height; 12. Configure a consulta deste relatóri o com a seguinte string SQL: SELECT it.quantidade, pro.nome as nomeProduto, pro.preco FROM pedidos_itens it JOIN pedidos ped ON ped.numero = it.numero_pedido JOIN produtos pro ON pro.id = it.id_produto WHERE it.numero_pedido do = $P{numeroPedido} 10. Insira os elementos textfield e static text até que o relatório fique com a aparência da segunda imagem da Figura 2; 11.. Crie o parâmetro numeroPedido  do tipo 11  java.lang. Integer ; 12. Ao executar, o relatório ficará como mostrado ao final da Figura 2. Edição 38 •  Java Magazine Magazine 37  jm38.indb 37 17/7/2006 14:11:59 Mais relatórios Passo a Passo Total por pedido Queremos agora exibir o valor total de cada pedido, ou seja, a soma dos valores de todos os seus itens. Como os dados do pedido estão no subrelatório RelatorioItens.jrxml, RelatorioPedidos.jrxml vamos declarar uma variável e exibí-la neste relatório. 1 .   Abra o RelatorioItens.  jrxml , RelatorioItens.jrxml 2 .   Clique em Visualizar |Variáveis, e depois no botão Novo. 3.  Configure uma nova variável fazendo seu atributo name  igual a total e Calculation Type = Sum. Mude o tipo da variável (campo Variable class Type) para  jav a.l ang. Double. Indique também que a variável deve ser reinicializada sempre que o relatório for executado, configurando ResetType para Report. 4.  Ainda falta especificar como a variável total   será calculada, ou seja, definir a soma dos valores de cada item do pedido. Para isso, utilizamos o campo Variable expression da variável, fornecendo uma expressão (que deve necessariamente ser do tipo Double, devido à configuração feita no passo anterior). . Relatório e sub-relatório iniciais (como criados na edição anterior), e Figura 2 resultado da execução do relatório Como o campo quantidade é do tipo  java.la ng.Integ er e  preco  é do tipo percorre a fonte de dados, poderá iden java.lang .Double , precisamos converter estificar quais são itens que pertencem ao ses campos para o tipo primitivo double, mesmo grupo: uma mudança no valor de realizar a multiplicação e armazenar o resultado em um objeto  java.lang.Double , ou nomeCliente indicará o início de um novo agrupamento. Vá em Data|Consultas do seja, a expressão ficará assim: Relatório|Report Query e altere a consulta new Double ($F{quantidade}.doubleValue() SQL acrescentando o nome do cliente na   *$F{preco}.doubleValue()) cláusula order by: 5. A variável deve ser inicializada com SELECT p.data, p.numero, c.nome as nomeCliente 0; por isto definimos o campo Initial Value FROM pedidos p Expression como new Double(0). JOIN clientes c ON p.id_cliente = c.id ORDER BY c.nome, p.numero 6. Clique em OK para finalizar. Veja os resultados na Figura 5. Veja na Figura 4 como ficam o layout e o resultado da execução do relatório. Feito isso, vamos mostrar o valor obti- do na variável total, após listar todos os itens: 1. Vá em Editar|Propriedades do Relatório e altere a altura para 60 pixels. 2 .   É necessário ativar a banda columnFooter: selecione Visualizar|Bandas do Relatório e altere na banda columnFooter a sua band height para 20; clique no botão  Apply. 3. Adicione um textfield à banda columnFooter e altere o campo Evaluation time para Report, indicando que o valor do textfield deve ser avaliado ao término da execução do relatório (no caso, o sub-relatório que contém todos os itens do pedido). Para que a variável total seja apresentada com formato de moeda, vamos utilizar o formatador obtido através do método getCurrencyInstance() da classe  java .tex t.Nu mbe rFor mat , com a seguinte expressão no campo Textfield expression: “Total do Pedido: “ + java.text.NumberFormat. java.text.NumberFormat.   getCurrencyInstance().format($V{total}.doubleValue())  O identificador iden tificador do pacote, “java.text”, “java.text”, poderia ser omitido nesta expressão; o JasperReports é capaz de encontrar sozinho a classe no Java SE. Veja na Figura 6 como ficam o layout l ayout e o resultado da execução. Total por cliente Nosso próximo objetivo é apresentar o Tela de configuração do grupo de quebra de Figura 3. Tela pedidos por cliente. 38  Java Magazine Magazine • Edição 38  jm38.indb 38 17/7/2006 14:12:01 RelatorioPedidos.jrxml Figura 4. Relatório depois de da criação do grupo cliente. Figura 5.Tela de configuração da variável que totaliza o valor de um pedido. valor total dos pedidos de cada cliente. Primeiro será necessário criar uma variável totalCliente  no relatório principal, RelatorioPedidos.jrxml. Siga estes passos: 1. Crie uma variável vari ável com campo name = totalCliente. 2.  Configure o tipo da variável ( Variable Class type) para java.lan  java.lang.Do g.Double uble(pois o total dos pedidos é desse tipo). 3. Faça Calculation type = System: não queremos que o JasperReports faça nenhum tipo de cálculo, mas sim que receba o valor retornado pelo sub-relatório (explicaremos isso a seguir). 4.  É necessário também fazer que a variável seja reinicializada a cada grupo, pois queremos o total por cliente. Neste caso o campo Reset type deve ser igual a  group e Reset group = cliente (que é o nome do grupo definido anteriormente). Veja como fica o relatório na Figura 7. Como o valor total de cada pedido está sendo calculado no sub-relatório RelatorioItens.jrxml, através de sua variável total, vamos usar este valor para incrementar a variável totalCliente no relatório principal, RelatorioPedidos.jrxml, enquanto estiver sendo processado o mesmo cliente (na geração do relatório). Para fazer esta ligação entre as variáveis, criamos um parâmetro de retorno no elemento subreport no RelatorioPedidos.jrxml, do seguinte modo: 1.   No relatório RelatorioPedidos.jrxml, abra a janela de propriedades do elemento subreport, que está na banda detail; clique na aba Subreport (Other) e dentro dela mude para a aba Subreport return values. 2.  Clique no botão  Add e digite o nome da variável do sub-relatório ( Subreport variable) que contém o valor que queremos somar, neste caso a variável total. 3. Indique o nome da variável que deve estar definida no relatório principal onde a totalização será armazenada (Local destination variable), ou seja, totalCliente. 4.  Indique também que o cálculo representa uma soma: Calculation type igual a Sum. Esta configuração está representada na Figura 8. Falta apenas exibir a variável total- “Total do Cliente: “ + java.text.Num java.text.NumberFormat.getCurr berFormat.getCurrencyInstance( encyInstance( new Locale(“pt”,”br”)).format(   $V{totalCliente}.doubleValue()) Veja como ficam o layout do relatório e o resultado da execução na Figura 9. Total geral O próximo passo é apresentar o valor total dos pedidos de todo o relatório. Novamente usaremos a variável com o valor total de cada pedido (no sub-relatório) e teremos de criar uma variável vari ável no relatório RelatorioPedidos.jrxml  para armazenar o total geral, da mesma forma que foi feito com a variável de total por cliente. c liente. Execute os seguintes passos em RelatorioPedidos.jrxml: 1.  Crie uma variável com campo name igual a totalGeral. 2.  Configure o tipo da variável ( Variable Class type) para java.lang.Doub  java.lang.Double. le. 3. Defina Calculation type = System. 4. A variável deve ser reinicializada sempre que o relatório é executado; então altere o campo Reset type para Report. Veja o resultado na Figura 10. A seguir, é preciso configurar em RelatorioPedidos.jrxml mais um parâmetro de retorno no elemento subreport, para que o valor da variável total do sub-rela- Cliente  no final do grupo cliente, ou seja, na banda clienteFooter (criada automaticamente ao criar o grupo cliente): 1 .   Adicione um textfield à banda clienteFooter. Altere seu Evaluation time para  gr ou oupp   e faça Evaluation Group = cliente, indicando que o textfield deve ser avaliado ao final desse grupo. 2.   Configure a Textfield expression de forma que o valor seja apresentado como moeda, da seguinte forma: RelatorioItens.jrxml Figura 6. Relatório com total por pedido. Edição 38 •  Java Magazine Magazine 39  jm38.indb 39 17/7/2006 14:12:02 Mais relatórios Passo a Passo tório também seja passado para a variável totalGeral  do relatório principal. Faça o seguinte: 1. No relatório principal RelatorioPedidos.  jrxml, abra a janela de propriedades do elemento subreport; clique na aba Subreport (Other) e dentro dela selecione a aba Subre port return values. 2.  Clique no botão  Add e digite o nome da variável do sub-relatório ( Subreport variable) que contém o valor a ser somado: total. 3. Indique o nome da variável que deve estar definida no relatório principal onde a totalização será armazenada ( Local destination variable), ou seja, a variável totalGeral. 4.  Indique também que o cálculo representa uma soma, fazendo Calculation type = Sum. Veja essas configurações na Figura 11. Resta apenas exibir a variável totalGeral no final do relatório: 1.   Coloque na banda summary um textfield com Evaluation time = Report; isso faz com que o textfield seja avaliado ao final da geração do relatório. 2.   Configure a Textfield expression de modo que o valor seja apresentado como moeda, novamente utilizando o formatador de moedas, da seguinte maneira: “Total Geral: “ + java.text.NumberFormat.getCurrencyInstance( new Locale(“pt”,”br”)).format($V{totalGeral}.doubleValue()) Veja na Figura 12 como ficam o layout e o resultado da execução. SELECT c.nome as nomeCliente, SUM(it.quantidade * pro.preco) as totalCliente FROM pedidos_itens it JOIN pedidos ped ON ped.numero = it.numero_pedido JOIN produtos pro ON pro.id = it.id_produto JOIN clientes c ON ped.id_cliente = c.id GROUP BY c.nome Depois clique em OK   para salvar as alterações. Ao ser definida a consulta, os campos retornados serão automaticamente declarados no subdataset. Gráfico de vendas por cliente O JasperReports tem suporte a gráficos, O elemento de gráfico através de um elemento de relatório que  Já podemos incluir o gráfico no relausa a biblioteca JFreeChart ( jf ree.org / tório: 1.  Vá em Visualizar|Bandas do Relatório,  jfreechart). Este elemento também está disponível na barra de ferramentas do iReport, e permite a configuração de um subconjunto das propriedades visuais suportadas pelo JFreeChart. Como exemplo, vamos acrescentar um gráfico de barras que mostra o valor total consumido por cada cliente em todos os pedidos realizados por esse RelatorioPedidos.jrxml cliente no final do relatório RelatorioPedidos.jrxml, na banda summary.  Subdataset  Precisamos que os valores se jam agrupados pelo cliente, ou seja, é necessário criar uma consulta SQL diferente da definida no relatório principal. Por isso iremos usar um subdataset. Um subdataset é um elemento do JasperReports usado para fornecer uma fonte de dados Figura 9. Relatório com total por cliente. secundária para um gráfico. Subdatasets têm seus próprios parâmetros, variáveis e fields, e podem ter também Figura 7.Tela de configuração da variável que totaliza o uma consulta SQL executada (ou um valor de pedidos por cliente. outro datasource, que neste caso viria de um dos campos do datasource principal). O conceito é muito parecido com o de um subreport, e é possível ter vários subdatasets num mesmo relatório. Para criar o subdataset: 1. Vá até Editar|Subdatasets e clique em New. 2.  Clique em Create. Isso habilita os demais botões da janela. 3. Clique em Query, e insira a seguinte Figura 8. Configuração de parâmetro de retorno do subreport. consulta SQL: Figura 10. Tela de configuração da variável de total geral. 40  Java Magazine • Edição 38  jm38.indb 40 17/7/2006 14:12:03 Figura 11.Configuração de parâmetro de retorno do subreport. RelatorioPedidos.jrxml Figura 12. Relatório com total geral. Figura 13. Tela de criação e edição de um subdataset. Figura 14. Layout do relatório com o gráfico já in serido. aumente a altura da banda summary para 385 e clique em Apply. 2.  Vá em Editar|Propriedades do Relatório e, na aba  More, selecione Sumário a cada nova página (que deveria ter sido traduzido como “Sumário numa nova página”). 3.  Em seguida, adicione um elemento de gráfico , escolha o gráfico de barras, e ajuste suas dimensões para que ocupe a maior parte possível da banda. Veja na Figura 14 como ficará o layout. Agora vamos configurar o gráfico: 1.   Clique com o botão direito sobre o gráfico e selecione Chart properties. 2.  Altere o campo Chart title expression para “Valores por Cliente”; este valor será exibido no título do gráfico. 3.   Faça  Orientation =  Horizontal, o que vai ajudar na leitura dos nomes dos clientes. 4.   Faça  Category axis label expression = “cliente”; esta é a descrição que aparecerá no eixo em que ficam os nomes dos clientes. 5.  Altere Value axis label expression para “valores”, que é a descrição a ser mostrada no eixo dos valores. 6.  Selecione Show labels, para que apareçam os valores correspondentes a cada uma das barras. Veja na Figura 15   as configurações realizadas. Após configurar visualmente o gráfico, temos que indicar os dados a serem exibidos. Esses dados estão definidos no subdataset criado anteriormente. É importante observar que ao utilizar um subdataset, somente os campos, parâmetros e variáveis definidos no subdataset estarão disponíveis para o gráfico. Porém, os campos, parâmetros e variáveis do relatório principal não estarão di sponíveis. Vamos então vincular o gráfico ao subdataset seguindo os seguintes passos: 1.  Clique na aba Chart data desta mesma  janela de propriedades do gráf ico para configurar a fonte de dados do gráf ico. 2.  Na caixa Dataset run da aba Dataset, selecione o subdataset que criamos no combobox Subdataset. 3.   Clique na aba Connection/Datasource ex p  e selecione Use connection expression . Isso faz com que o iReport utilize a mesma conexão do relatório, Figura 15.Tela de configuração das propriedades de um gráfico. Figura 16.Configuração da fonte de dados do subdataset do gráfico. Figura 17.Configuração dos campos do subdataset usados pelo gráfico. Edição 38 •  Java Magazine 41  jm38.indb 41 17/7/2006 14:12:04 Mais relatórios Passo a Passo Como executar o relatório declarando automaticamente a expressão $P{REPORT_CONNECTION} . Veja a Figura 16. D entro do diretório do projeto, temos os seguintes subdiretórios: • reports para os arquivos .jrxml ; • src para as classes Java; • web para os arquivos JSP; • web/WEB-INF para o web.xml ; • web/WEB-INF/lib para os arquivos JAR necessários. Por fim, selecione a aba Details e depois clique no botão  Add , para incluir uma Category series: 1. Faça Series expression igual a “valores” (o nome da série). 2 .   Altere   Category expression  para $F{nomeCliente}; esta é a expressão que será avaliada para obter os nomes mostrados no eixo de categorias. 3 .   Mude   V a l u e e x p r e s s i o n   para $F{totalCliente}, que é a expressão a ser avaliada para obter os valores exibidos no eixo de valores. Veja a Figura 17. Veja como fica o gráfico após a execução do relatório na Figura 18. Com isso, chegamos ao final deste tutorial. O relatório e o gráfico  já podem ser compilados e executados conforme instruções do quadro “Como executar o relatório”. Conclusões Neste tutorial mostramos como fazer agrupamentos e totalizações e como criar gráficos, em um relatório mestre-detalhe. Vimos também como definir variáveis e a importância de indicar o tipo de cálculo e de reinicialização adequados para cada tipo de variável. O momento de avaliação Vamos usar o Ant para efetuar algumas operações; para isso criamos um arquivo build.xml  que está no diretório raiz do projeto inicial (incluído nos downloads deste artigo). Primeiro precisamos compilar os dois templates de relatório. Abra uma janela de prompt de do textfield que utiliza uma variável (e, se for o caso, também o grupo) é essencial para se obter o resultado desejado. O uso de variáveis é de extrema utilidade e dificilmente teremos relatórios mais elaborados sem a sua utilização. Vimos ainda como criar um gráfico simples, que também utiliza totais, e percebemos que este é um recurso que ainda tem algumas limitações de configuração no JasperReports. Mas o JasperReports já está integrado o suficiente ao JFreeCha rt, a ponto de nos oferecer um resultado satisfatório com facilidade. comando no Windows ou terminal no Linux, vá até o diretório do projeto e digite: ant compile. Depois devemos compilar a classe do servlet, que fará a execução do relatório. Na mesma  janela de prompt, digite ant javac . Para finalizar, geramos o arquivo ecommerce.war. Vá ao prompt de comando e digite: ant war. Em seguida, copie o WAR para a pasta weba pps do Tomcat. Feito isso, inicie o Tomcat, abra o seu navegador web e digite a seguinte URL: http://localhost:8080/ecommerce . Clique no link que aparece na tela, e o relatório será gerado.  jasperreports.sf.net  Site da biblioteca JasperReports, onde se pode encontrar downloads do software, documentação,fóruns e mais.  ireport.sf.net  Site da ferramenta iReport, também com downloads, novidades etc.  jfree.org/jfreechart  JFreechart, biblioteca usada para a criação de gráficos no JasperReports/iReport  javamagazine.com.br/downloads/jm38/  jm-maisrelatorios.zip Ana Abrantes ([email protected]  ) é desenvolvedora Java na Globalcode, co-autora do curso de JasperReports/iReport e possui algumas certificações em Java (SCJA, SCJP e SCWCD). É formada pela FATEC-SP e atua na área de informática há mais de 15 anos.  Yara M. H. Senger ( [email protected] ) é formada em Ciências da Computação na USP em São Carlos, especialista em desenvolvimento web; possui as certificações SCJA, SCJP e SCWCD. Atualmente é Instrutora e Diretora Educacional da Globalcode, criadora e coordenadora de diversos cursos das carreiras Academia do Java e Academia do Web Developer. Figura 18.Última página do relatório gerado, com gráfico inserido. 42  Java Magazine • Edição 38  jm38.indb 42 17/7/2006 14:12:10 Edição 38 •  Java Magazine 43  jm38.indb 43 17/7/2006 14:12:16 Interfaces Gráficas co Parte 1: Conceitos e Técnicas Fundamentais, e a O projeto de interfaces gráficas eficazes exige mais do que conhecimento sobre componentes visuais ou outras questões relacionadas à tecnologia. São detalhes mais humanos que fazem a diferença, e que precisam ser compreendidos antes mesmo de se digitar qualquer linha de código. Os efeitos que cada elemento visual produz sobre nossos olhos revelam detalhes que complementam o significado das informações e auxiliam o usuário a entender o conteúdo da imagem observada. Este artigo apresenta a primeira parte de uma série voltada para a qualidade das interfaces gráficas, apresentando técnicas fundamentais para um bom projeto visual. Começaremos analisan- do a importância do projeto visual para o desenvolvimento de GUIs (Graphic User Interfaces; interfaces gráficas com o usuário). Em seguida, abordaremos erros comuns e técnicas de organização de interfaces. E veremos como utilizar a API JGoodies Forms para montar telas eficientes e com poucas linhas de código. 44  Java Magazine • Edição 38  jm38.indb 44 17/7/2006 14:12:18 m Qualidade API JGoodies Forms Saiba como projetar interfaces gráficas eficazes que facilitam a vida dos usuários, e como implementá-las utilizando a API Forms do JGoodies HUGO VIDAL TEIXEIRA Técnicas de projeto visual P or ser um conceito muito abstrato, qualquer julgamento sobre a qualidade de um software é difícil. Embora existam normas e processos de engenharia de software voltados para esse propósito, a tendência de um usuário é determinar a qua lidade de algo que não conhece baseando-se naquilo que vê e sente. Assim, a interface gráfica de um sistema conta muito para uma boa impressão. Vamos começar explorando algumas questões fundamentais que precisam estar claras para qualquer equ ipe envolvida na criação de GUIs. A importância dessas questões está relacionada ao papel do projeto visual no desenvolvimento e o momento em que ele deve ser aplicado. Em primeiro lugar, o projeto visual n ão é uma tarefa que pode ser deixada para depois. Este é um erro comum cometido em muitos projetos e que ainda precisa ser combatido. Para ser eficaz, o projeto visual precisa estar bem integrado ao ciclo de vida de desenvolvimento, permitindo que interfaces gráficas possam ser elaboradas e melhoradas conforme o entendimento do problema avança ao longo do tempo. É comum vermos empresas que deixam o projeto e a implementação de GUIs apenas nas mãos de programadores sem experiência na criação de interfaces, e sem nosso estudo analisando alguns dos principais erro s cometidos no projeto de GUIs. Em seguida veremos técnicas de organização de informações e de redução de poluição gráfica, entre outras. Erros comuns em interfaces gráficas Uma técnica de aprendizado muito eficiente é a analise de erros comuns cometidos no desenvolvimento de interfaces gráficas. Ilustraremos esta técnica com um exemplo – veja a Figura 1 – que resume alguns problemas que precisam ser sempre evitados. Você dificilmente encontrará todos esses problemas juntos na mesma tela de um sistema real, mas a freqüência com que cada um aparece separadamente é bastante alta. Vejamos os erros. Comece observando os componentes  JText Fiel d desalinhados na parte superior esquerda da tela. As suas posições horizontais variam de acordo com o tamanho de cada  JLa bel . Esse problema de alinhar os  JLab el s, mas não os componentes relacionados, torna apoio de designers e outros especial istas em projeto visual. O resultado dessa decisão freqüentemente são sistemas com telas complexas e pouco intuitivas, que às vezes confundem seus usuários por refletirem diretamente as entidades de negócio por trás do sistema (EJBs, tabelas etc.). Além disso, o desconheci mento de princípios de criação de interfaces ou a simples vontade de embelezar muito a tela podem resultar em interfaces pobres e excessivamente poluídas. A segunda questão que precisamos destacar é a suposição incorreta de que o simples uso de componentes e APIs (como os do Swing e do AWT) é suficiente para se alcançar os benefícios de uma boa apresentação. A forma com que essas peças são unidas é tão importante quanto cada peça individual. E é necessário ir além; entender a influência e efeitos que diferentes composições causam numa GUI. Começaremos Figura 1. Tela de exemplo que ilustra um projeto visual com problemas. Edição 38 •  Java Magazine 45  jm38.indb 45 17/7/2006 14:12:20 Interfaces Gráficas com Qualidade a leitura dos valores muito mais difícil do que poderia ser. Agora observe o grupo “Medidas” e repare como os  JTextF iel ds estão colados, enquanto sobra muito espaço ao redor. Observe ainda que a base dos textos dos  JLab el s não está alinhada com a base dos textos dos  JTextF iel ds, o que também atrapalha a leitura dos valores. Descendo mais o olho, percebemos que a parte inferior da tela está dentro de uma borda interna e ainda contém subgrupos com bordas e títulos. A borda interna cria uma dimensão desnecessária que polui mais do que real mente enfatiza aquela área. Já a borda dos subgrupos distrai os olhos e gera uma separação visual pouco eficaz entre os elementos. A presença de bordas aninhadas normalmente revela um projeto visual pobre. Veremos como combater esse problema na seção “Redução de poluição grá fica”, mais adiante. Os problemas ainda não acabaram. Repare a repetição desnecessária da palavra “Controle” tanto no label da  JComb oBox  quanto no título do subgrupo. Além disso, existem duas  JText Area s, uma com borda 3D e outra não. É uma inconsistência comum normalmente causada (por exemplo) pelo fato de desenvolvedores diferentes alterarem a mesma tela, sendo que um adicionou o recurso e o outro, sem notar a presença da borda, deixou de segui r o mesmo estilo. Para terminar nossa análise, note que o subgrupo “Comandos” não está alinhado com o resto dos componentes, e que não ocupa toda a largura disponível na tela, deixando de aproveitar um espaço valioso. Compare ainda Figura 2. Problemas de redimensionamento na tela de exemplo. o tamanho dos botões existentes, e verifique que não exi ste um “Editar” grande demais). Já o subgrupo padrão consistente. “Comandos” permaneceu intacto e poderia ter aproveitado melhor o espaço, Cuidados com redimensionamento por conter um  JTe xt Ar ea . Além disso, Algumas armadilhas ainda aguardam vários espaços vazios surgiram na tela, o desenvolvedor desatento. Um teste reduzindo o relacionamento visual entre que não podemos deixar de fazer no os componentes. desenvolvimento de interfaces é observar como a janela se comporta qua ndo é Técnicas de organização visual redimensionada. Agora que já vimos um pouco sobre o que não   fazer em interfaces gráficas, O teste de redimensionamento é importante podemos discutir alguns princípios geem GUIs criadas com toolki ts como AWT, Swing rais para boa organização e estrutu ração e SWT, porque estes utilizam gerenciadores de visual. As técnicas que abordaremos layout que formatam e posicionam cada comaqui estão divididas em três categorias:  ponen te, segui ndo r egras pr ópria s que não sã o Simetria e Balanceamento, Alinhamento totalmente explicitadas pela GUI. e Relacionamentos Visuais, e Formatação com Espaços Vazios. A idéia, ao fazer o redimensionamenÉ praticamente impossível conseto, é favorecer sempre aqueles compoguir elaborar GUIs eficazes sem o uso nentes que podem crescer sem deixar dessas técnicas. Para nossa sorte, são a tela desproporcional, como  JTab le s, técnicas simples, e o domínio vem com pouco tempo de prática. São princípios  JText Area s,  JTree s,  JLis ts etc. Caso uma janela não possua componentes deste tipo, que fazem parte de disciplinas como podemos sempre pensar em proibir o design gráfico e ergonomia, além de redimensionamento através do método serem apoiados pela área de psicologia cognitiva. Portanto, são muito valiosos setResizable(false)  da classe Frame. para causar uma boa impressão em A F i g u r a 2   mostra qualquer trabalho, mesmo fora da área esse problema com de software. a janela do nosso exemplo. Repare que  Simetria e b alanceamento o subgrupo “ConSimetria é uma propriedade que retrole” foi favorecido sulta da harmonia e equilíbrio de uma sem necessidade (o estrutura. É muito importante por ser que deixou o botão facilmente reconhecida e agradável aos 46  Java Magazine • Edição 38  jm38.indb 46 17/7/2006 14:12:22 nossos olhos. Sempre que uma forma é repetida – seja por translação, rotação ou reflexão – cria-se uma nova imagem simétrica que compartilha características semelhantes. No mundo dos símbolos visuais, as figuras mais memoráveis normalmente são muito simétricas, como a estrela, a seta, a cruz e o yin-yang. A simetria é u m fator importante quando o objetivo do trabalho depende de  balanceame nto, ordem e simpl icidade. Para elaborar um layout simétrico, algumas dicas são importantes: 1. Identificar os eixos pelos quais a simetria será estabelecida. Em interfaces gráficas, a simetria normalmente é vertical e horizontal. A simetria diagonal é mais rara, mas também é valida. Posicionar a informação sobre o eixo de simetria através de um balanceamento cuidadoso de cada lado. A informação não 2. precisa formar um espel ho perfeito, mas tente igualar aspectos como quantidade e espaço ocupado.  Alinhamento e relac ionamentos visuais O alinhamento é o meio mais importante de se estabelecer relacionamentos entre elementos. Objetos alinhados criam uma forte atração entre si, mesmo quando separados por longas distâncias. Isso acontece porque nossos olhos têm preferência natural por estruturas regulares, onde regiões bem definidas podem ser facilmente identificadas. Por outro lado, elementos desalinhados produzem tensão no observador, o que pode causar incômodo ou dúvida quanto às relações entre os elementos. Uma das vantagens em se alinhar elementos é a redução da complexidade d a tela, a qual se torna mais limpa e mais fácil de ser compreendida. Uma interface eficaz precisa estabelecer relacionamen- tos visuais entre suas estrutura s sempre que possível, e o alinhamento é u m passo necessário a uma apresentação coerente. Para estabelecer um bom alinhamento, considere as seguintes dicas: 1. Identifique as principais fronteiras da tela e procure um modo de organizar seus elementos em alinhamento com essas fronteiras. 2. Procure por elementos e margens (internas ou externas) que podem ser alinhados pela alteração de seus tamanhos ou posições. 3. Identifique elementos mais “soltos” na tela e verifique se estão alinhados com alguma outra coisa, seja com uma margem principal, seja com algum outro elemento associado a eles. 4. Se um elemento não está relacionado a nenhum outro na tela, tente posicioná-lo de forma a balancear o espaço já ocupado. Edição 38 •  Java Magazine 47  jm38.indb 47 17/7/2006 14:12:26 Interfaces Gráficas com Qualidade existirem fronteiras  bem definidas). 3. Identifique elementos que precisam de uma ênfase visual adicional (como títulos). Aumente o espaçamento entre esses elementos e outros considerados críticos. Formatação com espaços vazios Quando projetamos telas para sistemas de informação, temos uma tendência natural de tentar incluir o máximo de informações possíveis para o usuário. Essa busca por utilizar cada pixel disponível resulta normalmente em telas saturadas e com muita poluição visual. É daí que vem a importância de se utilizar espaços vazios na organização da informação, direcionando os olhos do usuário para certas regiões da tela e permitindo que cada pedaço de informação seja corretamente destacado. Espaços vazios na tela não significam desperdício, mas sim um elemento poderoso para guiar a atenção do observador. Essa técnica é uma da s melhores soluções para evitar o uso de bordas e linhas que delimitam áreas da tela. As seguintes dicas ajudarão você a encontrar os melhores lugares para aplicar essa técnica: 1. Agrupe as informações em con ju nt os de ta ma n ho s gerenc iáve i s (ex.: no máximo sete elementos) e defina suas prioridades de acordo com a importância da informação para o usuário. 2. Garanta uma separação entre os con juntos de informação através da adição de espaço vazio entre eles (mesmo se já Embora o espaço vazio seja uma variável poderosa em termos de percepção, ele é também o mais custoso, utilizando o pouco espaço que dispomos para mostrar as informações. Assim, a técnica deve ser usada sem exageros. Redução de poluição gráfica Existem algumas técnicas de identificação e remoção de poluição visual que precisam estar na ponta da língua de quem desenvolve interfaces gráficas. Uma delas, e na minha opinião, uma das mais divertidas, é a chamada técnica das unhas na tela. Como todos já percebemos, toolkits Java como Swing e AWT, e os de outras linguagens, desenham seus componentes utilizando cores que simulam um pseudo-3D dando a sensação de profundidade. É exatamente essa sensação de 3D que exploramos nessa técnica. Imagine que você fosse capaz de sentir os relevos 3D e passasse suas unhas sobre a tela em um movimento contínuo, qual grau de vibra- ção você sentiria? Se for “sentida” uma trepidação grande, sua tela provavelmente precisa ser revisada. Agora se forem percebidos apenas a lguns níveis, sua tela provavelmente não e stá poluída. É importante ressaltar que o objetivo dessa técnica é apenas identificar bordas e linhas que o programador adicionou à interface sem necessidade. Como primeiro exemplo, volte à Figura 1 e veja como bordas inúteis se confundem com as bordas dos componentes. Temos outro exemplo ilustrado na Figura 3, onde duas visões de um mesmo painel são apresentadas. Repare que a substituição das bordas com título por  JLab el s reduziu a poluição do painel e resultou em uma tela mais simples e clara para o usuário. Lembre-se que as bordas naturais dos componentes são as poucas que devem predominar na tela, já que trazem informações úteis ao usuário. Portanto, não se incomode com elas. Outra questão são os novos e modernos look-and-feels que simulam interfaces arredondadas e com componentes brilhantes. Visuais como o da Figura 4, por exemplo, produziriam uma sensação de “ondulação” nas unhas que poderia atrapalhar essa técn ica. Nesses casos, não se preocupe com essas ondulações; preste atenção somente nas bordas e linhas que o programador possivelmente colocou em excesso. Isso não consegue passar despercebido mesmo quando usamos um look-and-feel bem projetado, como mostrado na Figura 4 : veja o excesso de  bordas causadas pelo ani nhamento de componentes  JTabbe dPan e. Na próxima seção, mostraremos como implementar interfaces gráficas lançando mão dos princípios e técnicas apresentadas até aqui. Figura 3. Excesso de bordas no painel à esquerda em contraste com a simplicidade do painel à direita. 48  Java Magazine • Edição 38  jm38.indb 48 17/7/2006 14:12:30 Implementação com JGoodies U ma das soluções open source mais interessantes para quem trabalha com Java no desktop é, sem dúvida, o conjunto de APIs do JGoodies. Consulte o quadro “O que é JGoodies?”, ao final desta seção, para conhecer melhor essa iniciativa. Veremos agora como utilizar a API JGoodies Forms para implementar interfaces eficazes em Java. Nosso objetivo principal será reconstruir a tela inicial apresentada nas Figuras 1 e 2 (onde muitos erros foram encontrados) seguindo as técnicas de projeto visual apresentadas. Preparação A obtenção e instalação da API Forms são bastante simples: navegue até o site do JGoodies ( jgoodies.com), vá até a seção Downloads e clique em Libraries. Lá você terá acesso aos arquivos zipados de todas as APIs, os quais contêm exemplos, documentação, código-fonte e o JAR que deve ser incluído no classpath da sua aplicação para executar os exemplos. O FormLayout revela-se como uma solução vantajosa por ser simples e intuitivo, e adequado para a codificação direta sem o uso de editores visuais de interfaces. Você verá a partir de agora que o código exigido para a montagem de uma tela normalmente é  bem curto e de fácil leitura, o que aumenta a produtividade do desenvolvedor. Começando com o FormLayout  A classe central da API Forms é FormLayout , um gerenciador de layout que divide a tela em linhas e colunas flexíveis. Assim como a classe GridBagLayout do Java SE, o FormLayout alinha componentes às células da grade retangular que forma a tela, permitindo que cada componente ocupe uma ou mais células.   Uma das mais importantes vantagens do FormLayout é o uso da grade para dividir o espaço da tela. De fato, essa é a principal técnica utilizada  pelos designers profissionais. Uma grade alinha, Listagem 1. Método para criar o painel do exemplo da Figura 5 com o FormLayout. private static Component montaPainelExemplo() { FormLayout layout = new FormLayout( “right:pref, 3dlu, pref, 3dlu, 15dlu, 10dlu, right:pref, 3dlu, pref”, // colunas “pref, 3dlu, pref, 3dlu, pref”); // linhas layout.setColumnGroups(new int[][] { {1, 7}, {3, 9} }); JPanel panel = new JPanel(layout); CellConstraints cc = new CellConstraints(); panel.add(new JLabel(“Nome:”), cc.xy (1, 1)); panel.add(new JTextField(), cc.xyw(3, 1, 7)); panel.add(new JLabel(“CPF:”), cc.xy (1, 3)); panel.add(new JTextField(10), cc.xy (3, 3)); panel.add(new JLabel(“Categoria:”), cc.xy (1, 5)); panel.add(new JComboBox(), cc.xy (3, 5)); panel.add(new JButton(“...”), cc.xy (5, 5)); panel.add(new JLabel(“Telefone:”), cc.xy (7, 3)); panel.add(new JTextField(), cc.xy(9, 3)); panel.add(new JLabel(“Telefone(Fax):”), cc.xy (7, 5)); panel.add(new JTextField(), cc.xy(9, 5)); return panel; } organiza e oferece uma maneira consistente de trabalhar com diferentes tipos de elementos interrelacionados. Usando o FormLayout  Para a criação de uma instância de FormLayout , passamos no construtor duas strings que definem, respectivamente, as colunas e as linhas que formam a grade da tela sendo projetada. O JGoodies Forms define uma linguagem simples para montar essas strings e especificar cada linha e coluna. Uma vantagem é que toda a estrutura do painel está centralizada nessas duas strings, o que facilita a sua compreensão e rápida modificação. Em outros gerenciadores, a estrutura normalmente fica espalhada, exigi ndo que o desenvolvedor leia partes extensas do código de GUI para entender a estrutura sendo definida. Nosso primeiro exemplo é o painel ilustrado na Figura 5. Para criá-lo utilizando o FormLayout, esboçamos a tela em papel e identificamos as linhas e colunas que formam a sua estrutura. Observe a Figura 6 e veja como o painel foi projetado. Repare que existem nove colunas. As colunas 1, 3, 7 e 9 determinam que a largura seja a largura preferida dos componentes inseridos em seu interior (no caso,  JLabels ou  JTextFields /  JComboBoxes). As colunas 1 e 7 exigem ainda que seus componentes estejam alinhados à direita. Note que a contagem das linhas e colunas começa em 1. As colunas 2, 4 e 8 formam um espaçamento de proporção fixada em 3dlu (dialog units). Essa unidade estabelece um tamanho que é independente de pixels e é calculado levando em conta o taman ho das fontes (definido pelo look-and-feel) e a resolução da tela. Dessa forma, podemos Edição 38 •  Java Magazine 49  jm38.indb 49 17/7/2006 14:12:31 Interfaces Gráficas com Qualidade mudar essas características, e as proporções serão sempre mantidas. Da mesma forma, a coluna 6, que divide a tela ao meio, possui a largura fixada em 10dlu. Poderíamos ter inserido uma l inha para separar os dois grupos inferiores, mas lembre-se que usar espaços vazios é sempre melhor. Por fim, a coluna 5 ficará com a largura fixa de 15dlu para o único  botão nela inserido. As linhas da grade seguem o mesmo estilo das colunas. Assim, as linhas 1, 3 e 5 ficam com a altura preferida dos componentes, enquanto as linhas 2 e 4 são fixadas em 3dlu. Com essas informações, já podemos Tipo de especificação Alinhamento de Colunas instanciar nosso gerenciador de layout: FormLayout layout = new FormLayout( “right: pref, 3dlu, pref, 3dlu, 15dlu, 10dlu, right: pref, 3dlu, pref”, // colunas “pref, 3dlu, pref, 3dlu, pref” ); // linhas Para manter uma boa simetria no painel, podemos utilizar o recurso de agrupamento de linhas e colunas, que garante tamanhos iguais para conjuntos definidos através dos métodos setColumnGroups() e setRowGroups() . No nosso caso, é interessante Exemplos fill ou f : preencher com o conteúdo (default). “fill:30dlu” – coluna de 30dlus de largura, onde os componentes são esticados para ocupar toda a largura. “right:pref ” – coluna onde os componentes ficam alinhados à direita, e sua largura é a largura preferida dos componentes. left ou l : alinhado à esquerda. center ou c : centralizado. center ou c : centralizado (default). top ou t : alinhado ao topo. bottom ou b : alinhado ao chão. fill ou f : preencher com o conteúdo. Inteiro + Unidade Tamanho Constante Onde Unidade pode ser: px ( pixel ), pt ( point ) ou dlu (dialog unit ). (Obs.: 1 pt   = 1/72 polegada) – ou – Double + Unidade Onde Unidade pode ser: in ( polegada ), mm ou cm . Tamanho de Componente min  ou m : tamanho mínimo. pref  ou p : tamanho preferido. default ou d : tamanho default. min(constante ; componente ) : assume o tamanho menor Tamanho Limitado Figura 5. Exemplo simples de um painel para ilustrar o FormLayout . Valores Right ou r : alinhado à direita. Alinhamento de Linhas Figura 4. Bordas aninhadas em um projeto com look-and-feel moderno. entre os valores. max(constante ; componente ) : assume o tamanho maior entre os valores. “top:100px” – linha de 100 pixels de altura, onde todos os componentes estão alinhados na parte de cima (topo). “fill:3cm” – linha de 3 cm de altura, onde os componentes ocupam todo o espaço vertical. “10px ” – linha/coluna com 10 pixels de altura/largura. “36pt” – linha/coluna com 36 pontos de altura/largura (36 pontos = ½ polegada). “0.33cm” – linha/coluna com 0.33 cm de altura/largura. “0.15in” – linha/coluna com 0.15 polegadas de altura/largura. “min ” – linha/coluna com a altura/largura mínima dos componentes. “pref ” – linha/coluna com a altura/largura preferida dos componentes. “min(30dlu;p)” – linha/coluna cuja altura/largura assume o menor  valor entre 30dlu e a altura/largura dos componentes. “max(0.5cm;p)’ – linha/coluna cuja altura/largura assume o maior   valor entre 0.5cm e a altura/largura dos componentes. none : nenhum (default). grow: cresce conforme o painel cresce. grow( double) ou g( double) : cresce seguindo a proporção Redimensionamento passada como parâmetro. Essa definição só faz sentido quando existem mais linhas/colunas que crescem no mesmo painel. Assim, podemos definir aquelas que crescem mais do que as outras. “pref:grow” – linha/coluna que cresce na mesma proporção do crescimento do painel. “p:g(0.5) ” – linha/coluna que cresce com a metade da proporção do crescimento do painel. Tabela 1. Valores para especificação de uma lin ha ou coluna. 50  Java Magazine • Edição 38  jm38.indb 50 17/7/2006 14:12:32 manter as colunas 1 e 7, assim como 3 e 9, com a mesma largura (lembre-se que a simetria é importante). Portanto, podemos definir: layout.setColumnGroups(new int[][] { {1, 7}, {3, 9} }); Agora só falta adicionar os componentes ao painel. Para isso, precisamos utilizar uma classe chamada CellConstraints, para posicionar os componentes na grade. Essa classe possui o método xy(int coluna, int linha)  que posiciona um componente em uma determinada célula. Assim, para adicionar o primeiro  JLabel ao nosso exemplo, fazemos: CellConstraints cc = new CellConstraints(); panel.add(new JLabel(“Nome:”), cc.xy (1, 1)); Além de xy(), existe o método xyw(), usado para posicionar um componente que se estende por várias colunas. Assim, podemos adicionar o primeiro JTextField do exemplo, da seguinte forma: // Adiciona o componente na coluna 3, linha 1, // e ocupa a largura de 7 colunas panel.add(new JTextField(), cc.xyw(3, 1, 7)); O resto do código deste exemplo simples está na Listagem 1. Agora vamos estudar um pouco mais a linguagem de especificação de linhas e colunas do JGoodies, e refazer o exemplo inicial do artigo. Especificando Linhas e Colunas Figura 6. Projeto das linhas e colunas do painel de exemplo. Figura 7. Esboços de layouts para o exemplo. Figura 8. Planilha usada para identificar a nova estrutura do painel. A especificação de uma linha ou coluna do FormLayout sempre segue este formato: Especificação = [Alinhamento :] Tamanho [ : Redimensionamento] Os termos entre colchetes são opcionais, e os valores que podem ser usados para definir a estrutura da tela são detalhados e exemplificados na Tabela 1. Aqui estão mais exemplos de especificações de colunas: • "left:pref:grow” – coluna alinhada à esquerda, cuja largura é a largura preferida dos componentes, e que cresce conforme o crescimento do painel. • "r:min(20dlu;p)” – coluna alinhada à direita, cuja largura é o menor valor entre 20dlu e a largura preferida dos componentes. E aqui estão mais alguns exemplos para linhas: • " b:pref:grow” – linha alinhada à parte de baixo, cuja altura é a altura preferida dos componentes, e que cresce conforme o crescimento do painel. • "c:d:g(0.8) ” – linha centralizada, cuja altura é o tamanho default dos componentes, e que cresce a uma taxa de 80 % do crescimento do painel. • "fill:max(25mm;min)” – linha onde os componentes preenchem todo o espaço vertical, e sua largura vale o maior valor entre 25 mm e a altura mínima dos componentes. Reconstrução do exemplo inicial  Agora que já vimos o básico sobre o FormLayout, vamos reprojetar o exemplo inicial usando esse gerenciador de layout, e também demonstrar outros pequenos detalhes ainda não mencionados sobre a API JGoodies Forms. O primeiro passo na reconstrução de uma interface é identificar como os elementos serão posicionados. Para isso, é recomendado que a equipe se afaste do computador e trabalhe um pouco com papel e caneta. Utilizar o computador para essa tarefa frequentemente atrapalha mais a criatividade do que realmente ajuda a desenvolver um bom projeto visual. O segundo passo é identificar e especificar as linhas e colunas da grade onde serão inseridos os componentes, buscando alinhar e balancear a estrutura. Fazer Edição 38 •  Java Magazine 51  jm38.indb 51 17/7/2006 14:12:36 Interfaces Gráficas com Qualidade isso para telas complexas com lápis e papel tende a ser um pouco trabalhoso, portanto você pode talvez preferir voltar ao computador neste ponto. Uma opção é utilizar uma planilha eletrônica e colorir as células onde ficam os componentes. Essa estratégia tem a vantagem de deixar o arquivo da planilha como documentação para a equipe. A Figura 8 apresenta a planilha criada para o exemplo. A identificação das linhas e colunas  já é suficiente para iniciar a codificação da interface. Construiremos o painel utilizando uma classe utilitária do JGoo- dies Forms chamada DefaultFormBuilder , que apresenta algumas funcionalidades vantajosas como, por exemplo, o suporte a separadores com títulos, depuração e internacionalização. A implementação com essa classe não é muito diferente da vista até aqui: Listagem 2. Classe que recria o painel do exemplo inicial, agora utilizando a API Forms do JGoodies. public class JanelaBomExemplo { public static void main(String[] args) { try {   UIManager.setLookAndFeel(   PlasticXPLookAndFeel.class.getName()); } catch (Exception e) { ... } builder.add(new JComboBox(new String[] {“Automático”}), cc.xyw(2, 11, 3)); builder.add(new JButton(“Editar...”), cc.xy(6, 11)); builder.addSeparator(“Medidas”, cc.xyw(1, 13, 6)); builder.add(new JLabel(“Altura:”), cc.xy(2, 15)); builder.add(new JTextField(6), cc.xy(4, 15)); builder.add(new JLabel(“m”), cc.xy(6, 15)); builder.add(new JLabel(“Comprimento:”), cc.xy(2, 17)); builder.add(new JTextField(6), cc.xy(4, 17)); builder.add(new JLabel(“m”), cc.xy(6, 17)); builder.add(new JLabel(“Largura:”), cc.xy(2, 19)); builder.add(new JTextField(6), cc.xy(4, 19)); builder.add(new JLabel(“m”), cc.xy(6, 19)); builder.add(new JLabel(“Peso:”), cc.xy(2, 21)); builder.add(new JTextField(6), cc.xy(4, 21)); builder.add(new JLabel(“kg”), cc.xy(6, 21)); JFrame frame = new JFrame(“Bom Exemplo”); frame.getContentPane().add(montaPainel()); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLocationRelativeTo(null); frame.pack(); frame.setVisible(true);           } private static Component montaPainel() FormLayout layout = new FormLayout( // colunas “10dlu, right:p, 3dlu, p, 3dlu, min, // linhas “p, 3dlu, p, 3dlu, p, 3dlu, p, 7dlu, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, { 10dlu, p:grow”, builder.addSeparator(“Descrição”, cc.xy(8, 1)); builder.add(new JScrollPane( new JTextArea(2, 21)), cc.xywh(8, 3, 1, 7)); p, 3dlu, p, 7dlu, p, p, 7dlu, p”); builder.addSeparator(“Comandos”, cc.xy(8, 13)); builder.add(new JScrollPane( new JTextArea(2, 21)), cc.xywh(8, 15, 1, 7)); CellConstraints cc = new CellConstraints();   DefaultFormBuilder builder = new DefaultFormBuilder(layout); builder.setDefaultDialogBorder(); builder.add(montaBarraBotao(), cc.xyw(1, 23, 8)); builder.addSeparator(“Valores”, cc.xyw(1, 1, 6)); builder.add(new JLabel(“Primeiro Valor:”), cc.xy(2, 3)); builder.add(new JTextField(15), cc.xyw(4, 3, 3)); builder.add(new JLabel(“Outro Valor:”), cc.xy(2, 5)); builder.add(new JTextField(15), cc.xyw(4, 5, 3)); builder.add(new JLabel(“Label Comprida:”), cc.xy(2, 7)); builder.add(new JTextField(15), cc.xyw(4, 7, 3)); builder.addSeparator(“Controle”, cc.xyw(1, 9, 6)); Figura 9. Tela de exemplo reconstruída com a API Forms. return builder.getPanel(); } private static Component montaBarraBotao() { JButton btnOK = new JButton(“OK”); JButton btnCancelar = new JButton(“Cancelar”); return ButtonBarFactory.buildCenteredBar(btnOK, btnCancelar); } } Figura 10.Tela do exemplo, em modo de depuração, mostrando a definição da grade. 52  Java Magazine • Edição 38  jm38.indb 52 17/7/2006 14:12:36 O que é JGoodies? J Goodies é uma empresa alemã que oferece, dentre outras coisas, um conjunto de APIs open source voltadas para o desenvolvimento de interfaces gráficas desktop de alta qualidade. As APIs do JGoodies são baseadas em Swing e são subdivididas em cinco projetos: • Forms : Suporte para a criação de formulários precisos e elegantes de forma simples, rápida e consistente. • Looks : Uma série de Look-and-Feels permitindo fornecer novos visuais às suas aplicações. • Animation: Classes para criar animações com diferentes recursos e estilos. Essa API utiliza conceitos definidos pela especificação SMIL (Synchronized Multimedia Integration Language) definida DefaultFormBuilder builder = newDefaultFormBuilder(layout); builder.setDefaultDialogBorder(); builder.addSeparator(“Valores”,cc.xyw(1,1, 6)); builder.add(new JLabel(“Primeiro Valor:”), cc.xy(2, 3)); Repare na chamada ao método setDefaultDialogBorder(), que serve para criar uma borda vazia em torno do painel, evitando que este fique colado aos limites da janela. Além disso, o método addSeparator()   cria um separador com um título, ajudando na identificação visual dos grupos, mas sem criar linhas desnecessárias. O código completo desta implementação pode ser visto na Listagem 2. A tela recriada está ilustrada na Figura 9 e utiliza o Look and Feel Plastic XP da API  JGoodies Looks (veja o quadro “O que é  JGoodies?”). Um recurso interessante da classe DefaultFormBuilder é a possibilidade de depurar os painéis criados, como pelo W3C, porém utilizando Java para descrever as animações (ao invés de XML). • Binding : Framework para conectar os componentes de interface com as classes de modelo da aplicação. A idéia é reduzir o código de apresentação e permiti r uma melhor separação de camadas. • Validation : Suporte flexível para validação de campos e formulários, que permite diferentes tipos de técnicas e indicações de erros. Cada API está disponível para download no site do JGoodies na forma de um arquivo zipado que contém o códigofonte, a documentação e arquivos JAR. Inicialmente essas APIs não eram open source, mas agora estão disponíveis sob a licença BSD. mostra a Figura 10. Para ver as linhas e colunas indicadas em vermelho durante a execução do programa, basta passar como segundo parâmetro do seu construtor uma instância da classe FormDebugPanel: DefaultFormBuilder builder = new DefaultFormBuilder(layout, new FormDebugPanel()); Concluindo, observe o método ainda na Listagem 2, que retorna um painel contendo os dois botões, “OK” e “Cancelar”. Ele utiliza o método buildCenteredBar() da classe ButtonBarFactory   que, além de criar os botões com o mesmo tamanho, os centraliza e mantém uma distância padronizada de separação. Por fim, esse painel é adicionado à última linha do nosso layout, ocupando a largura de todas as colunas. montaBarraBotao() , Conclusões Apresentamos nesse primeiro artigo um conjunto básico de técnicas fundamentais para o projeto visual de i nterfaces gráficas, incluindo um exemplo prático com a API Forms do JGoodies. É importante lembrar que bons projetos visuais não vêm naturalmente nem dependem de APIs gráficas, como Swing ou SWT. Existe uma série de princípios que se deve aplicar corretamente para que o resultado seja satisfatório. A estrada que leva à alta qualidade de GUIs é longa, mas com os princípios introduzidos aqui já é possível iniciar essa jornada. Designing Visual Interfaces: CommunicationOriented Techniques Kevin Mullet & Darrell Sano, Prentice Hall PTR, 1994 Um dos livros mais completos sobre projeto de interfaces gráficas que explora diferentes técnicas e examina tipos variados de problemas encontrados em sistemas reais.  jgoodies.com Site do JGoodies com tutoriais, artigos, aplicações e APIs para download. www.sum-it.nl/enguilin.html  Links sobre projeto visual de interfaces gráficas. www.rspa.com/spi/design-interface.html  Site com informações sobre interfaces gráficas mantido por Roger Pressman, famoso especialista em Engenharia de Software.  javamagazine.com.br/downloads/jm38/  jm-guisqualidade-p1.zip Hugo Vidal Teixeira ([email protected] ) é Bacharel em Informática pela UFRJ,mestre em Engenharia de Software pela COPPE/UFRJ e pesquisador da área de componentes e GUI Design.Atualmente trabalha como consultor integrado à Sakonnet Technology, onde trabalha diretamente com Karsten Lentzsch (criador do JGoodies) e empresas especializadas em GUI design, como Ergosign(.de),Centigrade(.de) e OculusInfo(.com). Edição 38 •  Java Magazine 53  jm38.indb 53 17/7/2006 14:12:40 Complete a sua coleção!     0     1    o     ã    ç     i     9    o     ã    ç     i     d     E   A    D    T  A   O    S  G    E     d     E - Java no Governo - Apache FOP - JSTL – Guia Completo - Cocoon Inicial - Pacotes WAR e JAR   A    D    T  A   O    S  G    E     1    o     ã    ç     i     d     E - Ferramentas livres - Introdução ao J2EE 1.4 - Introdução a J2ME - J2EE Fundamental - Dados com JDBC     1     1    o     ã    ç     i     3    o     ã    ç     i     d     E - Multimídia no celular - Automação com Ant - Robocode - Tag Libraries JSP - Processando XML em Java - Dados em J2ME - JavaServer Faces - Jogos wireless - Certificação J2EE - Montando um ambiente Java     3     1    o     ã    ç     i     d     E     2     1    o     ã    ç     i     d     E - Códigos no Eclipse - New I/O Fundamental - Game API - Criando Plug-ins para Eclipse - Preferences API     2    o     ã    ç     i     d     E   A    D    T  A   O    S  G    E     d     E - Tutorial de NetBeans - API New I/O (java.nio) - Cesta de compras com Struts - Testes de carga com JMeter - Concorrência e a JVM - Relatórios Corporativos - Gráficos com Java 2D - Java.net na Prática - Raio-X do Tiger - Paginação na Web - Eclipse para Web - Fome Zero com Java - Tags Customizadas em JSP 2.0 - Tiger: A Evolução do Java - Dicas para Web                                               9     1    o     ã    ç     i        1     2    o     ã     ç     i      0     2    o     ã    ç     i     d     E     d     E     d     E - JSTL aplicado no Tomcat 5 - Modularizando páginas com Tiles - Componentes View do Struts - O rugido do Java livre     9     2    o     ã    ç     i     d     E - Threads no Java 5.0 - Cadastros com Struts - MVC na web - Servlet API Avançada - Padrões de projeto     0     3    o     ã    ç     i     d     E - JavaMail - Por Dentro do Apache Derby - Clusters com Tomcat e Apache - Mais HttpClient - Examinando o Mustang i l i        - Relatórios avançados - Mais design patterns - Gerenciamento com JMX - Java Web Start - Dúvidas de classpath     1     3    o     ã    ç     i     d     E - HSQLDB - Internacionalização de MIDlets - Performance na JVM - Caso de sucesso: Procon - Benchmarks JME www.javamagazine.com.br  jm38.indb i 54        2     2    o     ã    ç     i     3     2    o     ã    ç     i     d     E     d     E - Criptografia aplicada - XML de alto desempenho - Segurança em apllicações web - JSF Passo a Passo - Datas e Horas em Java - O Projeto Eclipse - Segurança no JBoss - JSF Avançado - Começando com Java - Tira-dúvidas     2     3    o     ã    ç     i     d     E - SWT no Eclipse - Eclipse Web Tools Project - Validação avançada com Struts - Fronteiras do Java - CD do NetBeans     3     3    o     ã    ç     i     d     E - NetBeans 5.0 - Aprendendo Groovy - Test-Driven Development - Debate Internacional Sou+Java - Java Business Integration (parte 1) - Hibernate em aplicações web - Java 6 (Mustang) - Programação em par - Processos ágeis - Java Business Integration (parte 2) devmedia.com 17/7/2006 14:12:50     4    o     ã    ç     i     d     E   A    D    T  A   O    S  G    E     5    o     ã    ç     i     d     E - Eclipse inicial - O mercado J2ME - Segurança em aplicações web - Interfaces ricas com Flash - Expressões regulares no J2SE 1.4     4     1    o     ã    ç     i - JBoss Inicial - Introdução ao JMX - Java no Lego Mindstorms - Logging - Memória e desempenho     5     1    o     ã    ç     i     d     E   A    D    T  A   O    S  G    E     d     E - Formulários com Swing - ANT - Automatizando Java - JBoss e Entity Beans - Extreme Programming - Metaprogramação e Reflection                       - Otimização de EJBs no JBoss - Processamento de imagens - Programação com regras - Jakarta Taglibs - Case J2ME     6    o     ã    ç     i     d     E   A    D    T  A   O    S  G    E     7    o     ã    ç     i     d     E     6     1    o     ã    ç     i     d     E     8    o     ã    ç     i     d     E - Bancos de dados livres - Testes unitários com JUnit - JSTL- Guia Completo: tags Core - Java na Droga Raia - Validação na Web - Introdução ao Tomcat - Conectivade com MIDP - Struts, primeiros passos - Automação com XDoclet - Jakarta Velocity     d     E     d     E - SwingWT - Java 2D: Animação e impressão - Anotações no Java 5 - Projeto Looking Glass - Java 2D: Animações e Impressão       •                    • • Gerência deConteúdo Detalhessobrea NovíssimaAPI  JCRea CriaçãodeRepositórios deConteúdona Web          • ConheçaduasAPIsde impressãodo  J2SEeobtenha controlefino sobrelayoute formatação          • Imprimindo com Java     Edição24-AnoIII-R$9,90    - JSP 2 e Servlets no Tomcat 5 - Primeiros passos com wireless - Collections avançado - Conhecendo o JDeveloper 10g - Servlets: do básico ao avançado  Java 5 Impressão  Java Content Repository Caches e JDBC NetBeans  JavaOne                    - JavaOne 2003 - Conhecendo o CVS - JSTL- Guia completo SQL e Format - Tomcat e o Servidor Apache     8     1    o     ã    ç     i     7     1    o     ã    ç     i - Genéricos no Tiger - JBuilder para web - MIDP 2.0 - JavaOne 2004 - Segurança com JAAS   A    D    T  A   O    S  G    E Uma Aplicação Java Completa com NetBeans          Partefinal–AcessoaBanco deDadoseGerênciade PreferênciasdeUsuários Tira-DúvidasEspecial CacheseDAOscom JDBC,Usando  JVMsAlternativas,Relatóriose DriblandoRestrições daMáquina  Java:     4     2    o     ã    ç     i     d     E Futuro                                  5     2    o     ã    ç     i     d     E - Novo NetBeans - Máquinas virtuais alternativas - Gráficos com JFreeChart - SuperWaba Inicial - Tag Files do JSP 2.0     4     3    o     ã    ç     i     d     E - Aplicação Completa - Parte 1 - Desempenho com JDBC e DAOs - Portlets - Fundamentos - JFreeChart Avançado - O Novo Extreme Programming     5     3    o     ã    ç     i     d     E - Para onde vai o Struts - Teste com J2MEUnit - Web Services - Scripting na JVM - Aspectos no Mundo Real .br/anteriores  jm38.indb 55 - Frameworks de Logging - Otimização de Código - Ajuda com JavaHelp - Maven 2 Essencial - Java ME no Eclipse     6     2    o     ã    ç     i     d     E - Aplicação Completa - Parte 2 - Mais Desempenho com JDBC - Portlets - Recursos Avançados - Jakarta Commons Inicial - Números: Conceitos e Formatação     6     3    o     ã    ç     i     d     E - Conhecendo o Ant - Acessando Código Nativo - Qualidade Aplicada - Migrando para o Maven 2 - Logging no Java SE     7     2    o     ã    ç     i     d     E &  JavaOne 2005 Presente Grandesnovidadesem produtoseAPIs,planos e comemoraçõesnoevento mundialda tecnologia Java Migrando para o Java 5 Conheça na prática eem detalhes como,porqueequando fazero upgradepara o J2SE 5.0 - Aplicação Completa - Parte 3 - Migrando para o Java 5 - Impress ão com Java - Gerenciamento de Conteúdo - JavaOne 2005     8     2    o     ã    ç     i     d     E - Hibernate Fundamental - Apache Geronimo na Web - Ajax: Interatividade Turbinada - Tutorial de Genéricos - De Volta aos Patterns Leia uma vez, use em todos os lugares     7     3    o     ã    ç     i     d     E - Criação de Plug-ins - Os 10 Mais do Eclipse 3.2 - JavaOne 2006 - Relatórios Passo a Passo - Testes com mock objects 21 2283 9012 17/7/2006 14:12:52 O Eclipse Callisto A maneira fácil de instalar os principais plug N o final de junho foi finalmente liberado um dos lançamentos mais aguardados do ano, o Eclipse Call isto, que reúne 10 dos projetos mais importantes da Fundação Eclipse: • Business Intelligence and Reporting Tools (BIRT) • C/C++ IDE (CDT) • Data Tools Platform (DTP) • Eclipse Modeling Framework (EMF) • Graphical Editi ng Framework (GEF) e Graphical Modeling Framework (GMF) • Eclipse Project: Eclipse Platform,  Java Development Tools (JDT) e Plug-in Development Environment (PDE) • Eclipse Test and Performance Tools Platform Project (TPTP) • Eclipse Web Tools Platform Project (WTP) • Visual Editor (VE) O projeto Callisto, destacado no artigo sobre o Eclipse 3.2 na edição passada, foi iniciado no começo de 2006 com o ambicioso objetivo de liberar simultaneamente as novas versões de vários dos principais projetos da Fundação Eclipse. Dessa forma, os novos recursos ficam disponíveis para uso imediato pelos interessados, em vez de terem que esperar pela cascata de atualizações gerada por cada projeto individual no passado – por exemplo, hoje sai um novo Eclipse SDK, algumas semanas depois um novo EMF, apenas depois disso um novo WTP, e daí em diante. O propósito do Callisto é facilitar a vida de dois tipos de usuários, ao oferecer uma plataforma unificada com releases simultâneos de componentes-chave dos 10 projetos citados: • Desenvolvedores individuais que usam o Eclipse como ambiente de desenvolvimento de aplicações; • Integradores que constroem produtos baseados nos projetos da Fundação Eclipse Como diz o próprio site do Callisto (eclipse.org/callisto), os projetos não foram 56  Java Magazine • Edição 38  jm38.indb 56 17/7/2006 14:13:07 -ins do Eclipse Aprenda como instalar o Callisto, que fornece um conjunto integrado de plug-ins Eclipse para desenvolvimento Web, Visual, Relatórios e Modelagem FERNANDO LOZANO detalhes de acompanhamento e gerenciamento dos projetos i ndividuais. Figura 1. Como chegar ao site de download do Calli sto. Figura 2. Escolha de um dos espelhos. unificados. Cada um permanece com seus próprios planos de desenvolvimento e cronogramas de releases individuais. O que o Callisto fornece é a possibilidade de se deixar de acompanhar cada projeto individualmente e utilizar apenas as últimas versões disponibilizadas como parte do Callisto. O Callisto garante que cada projeto no seu conjunto de releases funcionará junto com os demais sem problemas, coisa que nem sempre acontece com as versões mais recentes dos projetos individuais; garante também que serão sempre versões estáveis. O projeto ainda traz uniformidade no controle de versões, critérios para qualificação de releases como estável ou em desenvolvimento, e outros pequenos Instalação do Callisto Curiosamente, o Callisto não fornece uma página de downloads e nem um instalador integrado, o que o torna bastante diferente de “distribuições” do Eclipse como o Yoxos ( yoxos.com ). Para se obter o Callisto, é necessário  baixar e instalar manualmente o Eclipse Platform Runtime 3.2 (ou então o Ecl ipse SDK 3.2) para a sua plataforma específica. Depois deve-se abrir o Update Manager da plataforma ( Hel p|Soft war e Upd ate s >Find and Install), conforme mostra a Figura 1. O próximo passo é escolher a opção Search for new features to install, e na página seguinte do assistente selecionar Callisto Discovery Site. Antes de receber a relação de features que podem ser instaladas pelo Callisto, o usuário recebe a opção de selecionar um espelho ( mirror) para o download dos arquivos. Há uma grande quantidade de espelhos ao redor do mundo (veja a Figura 2), mas nenhum ainda no Brasil. O site principal tende a estar saturado, especialmente logo após o anúncio de um novo release de algum componente popular como o JDT, portanto pode ser interessante selecionar uma das demais alternativas. A próxima janela exibe a relação de features disponibilizadas pelo Callisto, organizadas em categorias como “Java Development” e “Charting and Reporting”. A mesma feature pode ser exibida em mais de uma categoria, de modo a facilitar a localização das features desejadas pelos usuários iniciantes em Eclipse. Caso uma feature tenha dependências contidas em outras features, será exibido um marcador de erros semelhante ao Edição 38 •  Java Magazine 57  jm38.indb 57 17/7/2006 14:13:17 O Eclipse Callisto Figura 3. Seleção de features fornecidas pelo Callisto para download e instalação, mostrando que uma dependência ainda não foi satisfeita. usado pelo Eclipse para indicar problemas em código Java ( Figura 3). Apenas depois que todas as dependências sejam satisfeitas será habilitado o  botão Finish. A página seguinte ( Figura 4 ) permite que se verifique a licença de uso de cada feature, mas as opções de “aceito” ou “não aceito” se aplicam a todo o conjunto. Retorne com o botão Back   caso alguma das licenças não lhe agrade. Por enquanto, todos os componentes usam a mesma licença padrão da Fundação Eclipse, mas no futuro poderá haver componentes utilizando outras licenças open source. Antes de iniciar o download e instalação das features selecionadas, o usuário tem a oportunidade de selecionar um local alternativo para a instalação de cada feature. Instalar features em diretórios separados (em especial, diferentes da própria Eclipse Platform) facilita a posterior desinstalação ou desabilitação dessas features. Facilita ainda a sua cópia para a máquina de outro desenvolvedor (que assim não precisa fazer o download direto da internet), ou mesmo o compartilhamento de features entre vários sistemas operacionais para quem tem “dual boot”. Também pode ser um “quebra-galho” interessante em caso de falta de espaço no disco de instalação do Eclipse. Infelizmente o Eclipse não suporta (via Update Manager) o compartilhamento de features entre diversos usuários de um mesmo sistema Linux, Mac OS ou outro sistema Unix-Like. Mas a solução está a caminho, veja o quadro  “Empacotando o Eclipse para Linux”. Finalmente, clicar no botão Finish  faz com que cada feature seja baixada e instalada. Como mostra a Figura 6. Se for necessário, o Eclipse será automa- Empacotando o Eclipse para Linux U suários de Linux poderão achar o Update Manager do Eclipse “primitivo”, por não ser capaz de gerenciar automaticamente dependências e indicar exatamente quais são as features que devem ser acrescentadas para resolvê-las. Afinal, usuários de Debian, Ubuntu e Kurumim fazem isto há anos usando o apt-get , e usuários do Fedora e Yellow Dog contam com o yum ; isto sem falar nas ofertas comerciais da Novell/SuSE e da Red Hat. Muitas distribuições do Linux já empacotam o Eclipse como componentes padrão, às vezes utilizando um Java Livre como o GCJ (caso do Fedora Core Linux, fedora.redhat.com) ou então com o pré-requisito da instalação manual do Java da Sun (como no JPackage,  jpackage.org). A manutenção destes empacotamentos é trabalhosa, pois o Linux espera que cada pacote seja construído a partir dos fontes originais e de forma automatizada (o conceito de “pristine sources” originado pelo RPM). Mas não existe um processo padronizado para a obtenção destes fontes na Fundação Eclipse, nem para a compilação auto- mática dos plug-ins. Só para citar um exemplo, o JDT não é gerado diretamente pelo PDE, mas sim por uma ferramenta conhecida como Releng (procure por org.eclipse.releng.tools-3.2.zip na página de downloads do Eclipse). Os empacotamentos customizados das distribuições resolvem alguns problemas de integração do Eclipse com o ambiente Linux, como a criação de ícones no desktop ou a utilização do IDE por vários usuários da mesma máquina (ex.: com clientes magros), mas nenhum deles hoje consegue permitir a instalação de atualizações ou novas features, pelo Update Manager e mantendo a integração estreita com os gerenciadores de pacotes do Linux. Em resumo, a situação atual exige que o usuário Linux escolha ter uma instalação do Eclipse bem integrada, e faça todas as atualizações e acréscimos por meio do gerenciador de pacotes da distribuição; ou então, que realize a instalação manual em seu diretório pessoal, e f aça todas as atualizações e acréscimos por meio do Update Manager. Dessa forma são geradas várias ins- talações independentes e paralelas do Eclipse, caso haja outros usuários do IDE no mesmo computador. O recém-criado Linux Distributions Project da Fundação Eclipse ( wiki.eclipse.org/index.  php/ Linux_ Distribu tions_ Projec t ) visa resolver estes problemas e além disso fornecer plug-ins específicos para o desenvolvedor Linux / Unix, por exemplo editores de páginas de manual (man  pages), geradores de pacotes RPM e integração com o GNU Autotools (origem do popular script configure usado por quase todos os projetos de software livre escritos em C para Unix).  Usuários de outros sistemas Unix-Like como o Solaris, FreeBSD e o Mac OS têm problemas semelhantes e serão também beneficiados pelo projeto. Os resultados deste projeto serão importantes para todos os usuários do Eclipse, não apenas para os usuários Linux, pois a integração de um melhor gerenciamento de dependências ao Update Manager tornará o Eclipse e seus plug-ins mais fáceis de instalar em qualquer plataforma. 58  Java Magazine • Edição 38  jm38.indb 58 17/7/2006 14:13:21 ticamente reiniciado ao final para ativar os novos recursos. Ao fim do processo, o usuário poderá ver os novos menus, perspectivas e outros recursos acrescentados ao IDE. Figura 4. Aceitação dos termos de licença de todas as features. Figura 5. Seleção do diretório de instalação para cada feature. Figura 6. Baixando e instalando as features selecionadas. Dependências O Callisto ainda não é o “Eclipse para Iniciantes”. Afinal, muitos não saberão distinguir “x86_64 GTK 2” de “x86 /Motif” na página de downloads da Fundação, ou então serão induzidos a baixar o “Eclipse SDK” e gastar dezenas de megabytes de disco (além de muito tempo de conexão internet) com fontes e plug-ins que eles provavelmente não irão utilizar tão cedo. Além disso, algumas dependências do Callisto parecem estar erradas, por exemplo é estranha a exigência de se incluir o PDE (desenvolvimento de plug-ins) para instalar tanto o VE (para desenvolver visualmente aplicações SWT ou Swing) quanto o JST (que permite o desenvolvimento de aplicações Java EE). Em alguns casos, as mensagens de erro do Update Manager não serão úteis, exceto para usuários já familiarizados com os projetos em questão, pois irão relacionar nomes de plug-ins que muitas vezes não fornecem qualquer “dica” de qual projeto ou feature é fornecido, como no exemplo da Figura 7, onde foi selecionado o VE + GMF, que cita o plug-in “org.eclipse. draw2d”; ou a seleção do EMF, que pede o plug-in “org.apache.batik”. Conclusões Embora o Callisto ainda não forneça a maneira “mais fácil” de se instalar o Eclipse, deixando de fora coisas como a criação de um atalho na á rea de trabalho, ele representa um grande avanço em relação à busca e download manual de cada distribuição de cada plug-in fornecido pelos vários projetos da Fundação Eclipse. O objetivo de l iberar simultaneamente novas versões finais de dez projetos complexos foi bastante ambicioso, ainda mais considerando-se a quantidade de pessoas e empresas envolvidas em cada um desses projetos. Apenas um projeto falhou com o ob jetivo, o VE, que foi incluso no Callisto com a versão 1.2RC-2 (segundo Release Candidate), que embora não seja uma versão final (GA, General Availability) é quase isso. Segundo qualquer c ritério de avaliação, entretanto, pode-se considerar o Callisto como um gra nde sucesso. eclipse.org/callisto Página principal do Eclipse Callisto eclipse.org/downloads Página de downloads do Eclipse,para baixar o SDK ou plataforma e iniciar o processo Figura 7. Nem sempre o Update Manager será útil para quem não conhece os projetos que deseja instalar. Por exemplo, nenhuma feature tem um nome parecido com “draw2d”. Edição 38 •  Java Magazine 59  jm38.indb 59 17/7/2006 14:13:23 Google Search Incremente suas aplicações Java com con T odo usuário de internet percebe o papel que o Google representa na vida on-line. Desde o inicialmente modesto site de busca, com uma caixa de texto e dois botões, até o sofisticado Google Earth, poucos são os internautas que não usam um dos produtos Google: Gmail, Calendar, Finance, Pages, Analytics, Maps, Desktop, Talk, SketchUp, Spreadsheets... e a lista não para de crescer. Mas mudar a maneira de como usamos a internet parece não ser suficiente para o Google, que está oferecendo cada vez mais ferramentas e APIs para que desenvolvedores possam explorar os produtos e tecnologias da empresa em suas próprias aplicações. Neste artigo, veremos como usar a Google Search API, para realizar  buscas de vários tipos, obter sugestões de correção ortográfica e ler páginas armazenadas em cache, entre outras operações. Instalação e uso Para usar a Google Sea rch API, basta fazer o download do kit de desenvolvimento, descompactá-lo em algum local do disco e obter uma chave. O site google.com/apis lista os passos necessários. Para obter a chave, clique no link fornecido no segundo passo (“Create a Google Account”). Como se vê, é necessário ter uma conta do Google, que pode ser criada no mesmo site (se você tem uma conta no GMail ou no Orkut, já tem uma conta no Google). Tendo a conta criada, faça o login e uma chave será enviada para seu e-mail no GMail. A chave permite a realização de até mil pesquisas automatizadas por dia. O kit de desenvolvimento contém o  JAR da biblioteca e exemplos de uso em Java, C# e Visu al Basic. Além destas, pode ser usada qualquer outra linguagem que suporte web services: o kit de desenvolvimento inclui o descritor do web service publicado pelo Google (GoogleSearch.wsdl) e exemplos de requisições (no diretório soap-samples ). Em Java, basta adicionar a bi blioteca googleapi.jar ao classpath, instanciar um objeto da classe com.google.soap.search.GoogleSearch e configurar nele a chave usando o método setKey(), como mostrado na Listagem 1. A classe GoogleSearch  contém métodos para busca, sugestão ortográfica e obtenção de páginas em cache, como será mostrado a seguir. Buscas As buscas são feitas definindo uma expressão de consulta, usando o metodo setQueryString()  – semelhante ao que seria feito normalmente no site google.com – e depois invocando o método doSearch(), que retorna um objeto da classe GoogleSearchResult. Este objeto contém os resultados da busca e algumas informações adicionais, como o tempo de busca e o total estimado de resultados. Um exemplo de uso do método doSearch() pode ser visto na Listagem 1. A melhor maneira de se encontrar as informações desejadas usando o Google é construir uma boa consulta. Por exemplo, buscar por Java Magazine (sem aspas) usando a API, dificilmente retornará o site desta revista como o primeiro dos resultados. Uma primeira melhoria seria ao invés de buscar separadamente os termos  Java e  Magazine, buscar o termo composto pelas duas palavras na ordem dada, colocando o conjunto entre aspas. Um detalhe é que, para fazer isso no programa Java, as aspas devem ser “escapadas” com o caractere “ \ ” para que façam parte da string ao invés de delimitá-la, ou seja, a consulta seria “\”Java Magazine\””. Se a consulta fosse feita através de um navegador web, o problema estaria resolvido. Mas o web service utilizado pela API não recebe as informações de localidade submetidas pelo navegador, e sites de peso em língua inglesa como Amazon e JavaWorld tendem a aparecer primeiro nos resultados. Um contorno seria excluí-los manualmente dos resultados com o operador “-“, executando a consulta “\”Java Magazine\” -JavaWorld -Amazon”. Há um mecanismo mais elegante para limitar consultas. O método setRestrict() da classe GoogleSearch  permite que sejam impostas restrições de idioma, de país ou de tópicos. Por exemplo, se antes de  buscar por “Java Magazine” configurarmos 60  Java Magazine • Edição 38  jm38.indb 60 17/7/2006 14:13:27 Use o poder do mecanismo de busca que revolucionou a internet dentro de suas aplicações Java, e conheça técnicas avançadas de pesquisa API sultas ao Google JULIO FAERMAN a restrição “countryBR ”, o site da JM será o primeiro resultado (veja a Listagem 1). O quadro “Restrições” mostra outras restrições suportadas. Além do método setRestrict() , outros limitadores e termos especiais podem ser incluidos na própria expressão de consulta. Por exemplo, a consulta “Faermansite :www.javamagazine.com.br” retorna as paginas do site da JM com artigos deste autor. A lista completa de operadores suportados pela API, com exemplos de uso, pode ser vista no quadro “Operadores”. Conhecer um pouco do funcionamento da internet também ajuda na hora de montar suas consultas. Por exemplo, para buscar documentos sobre (digamos) CMMI em arquivos PDF ou DOC, uma boa consulta Listagem 1.Exemplo de uso da Google Search API package jm; import com.google.soap.search.GoogleSearch; import com.google.soap.search.GoogleSearchResult; import com.google.soap.search.GoogleSearchResultElement;         //Sugestoes Ortograficas sugerirOrtografia(“filosofy”); sugerirOrtografia(“philosophy”); sugerirOrtografia(“filosopia”); sugerirOrtografia(“lumbriga”); public class GoogleSearchDemo { static final GoogleSearch busca = new GoogleSearch();   //Pagina em cache obterPagina(“www.java.com”); } public static void main(String[] args) throws Exception { String clientKey = null; if (args.length == 1) { clientKey = args[0]; } else {   System.err.println( “uso: java -cp ” + “ GoogleSearchDemo ”);   System.exit(-1); }  public static void buscar(String consulta) throws Exception { busca.setQueryString(consulta); GoogleSearchResult result = busca.doSearch(); System.out.printf(“Busca: %s Tempo: %f s Resultados: %d\n”, result.getSearchQuery(), result.getSearchTime(), result.getEstimatedTotalResultsCount()); for (GoogleSearchResultElement element : result.getResultElements()) { System.out.println(“######”); System.out.println(“Titulo: “ + element.getTitle()); System.out.println(“URL:” + element.getURL()); System.out.println(“Trecho: “ + element.getSnippet()); }        //Configuração busca.setKey(clientKey); busca.setMaxResults(5);   //Buscas buscar("Java Magazine"); buscar("\"Java Magazine\" -JavaWorld -Amazon"); busca.setRestrict("countryBR"); buscar(“Java Magazine”); busca.setRestrict(“linux.-lang_en”); buscar(“blackdown”); buscar(“jsf OR struts”); buscar(“Faerman site:www.javamagazine.com.br”); buscar(“jsf inurl:java”); buscar(“hibernate intitle:OnJava”); buscar(“java daterange:2453371-2453736”); buscar(“allintext:Service Oriented Architecture”); buscar(“CMMI filetype:doc OR filetype:pdf”); buscar(“-inurl:htm -inurl:html intitle:\”index of\”” + “+(\”/ebooks\”|\”/book\”)+( chm|pdf|zip) lewis alice wonderland”); buscar(“info:www.javamagazine.com.br”); buscar(“link:www.javamagazine.com.br”); buscar(“related:www.java.com”); }               public static void sugerirOrtografia(String palavra) throws Exception { String sugestao = busca.doSpellingSuggestion(palavra); if (sugestao == null) {   System.out.println( “Sem sugestões para \”” + palavra + “\”.”); } else {   System.out.println( “Voce quis dizer \”” + sugestao + “\”?”); } }  public static void obterPagina( String pagina) throws Exception { System.out.println(new String(   busca.doGetCachedPage(pagina))); } } Edição 38 •  Java Magazine 61  jm38.indb 61 17/7/2006 14:13:31 Usando a Google Search API seria “CMMI filetype:doc OR filetype:pdf”. Entretanto, para buscar um termo comum ou com muitos documentos relacionados, como o livro “Alice no País das Maravilhas” (Alice’s Adventures in Wonderland)1, uma busca por tipo de arquivo dificilmente retornaria o livro. Neste caso, é melhor buscar por páginas de índice de diretórios, cujo título costuma ser “index of”, e num diretório de livros, como “book” ou “ebooks”. Como desejamos o arquivo do livro, também ajuda acrescentar como critério os formatos comuns de livros eletrônicos – zip, chm, txt ou pdf . E como páginas web não interessam, podemos remover endereços com extensões de páginas, como htm e html. Por último, adicionamos os termos da consulta, por exemplo o título do livro e o nome do autor. Sendo assim, uma  busca como a seguinte tem boa chance de ser bem sucedida: intitle:\”index of\” +(\”/ebooks\”|\”/book\”) +( chm|pdf|zip|txt) -inurl:htm -inurl:html lewis alice wonderland. Todas essas buscas são exemplificadas na Listagem 1. Sugestões de ortografia Quando se faz uma consulta no site do Google usando um termo incomum ou com erros de digitação/ortografia, como “javascripiti”, o Google é capaz de verificar em seu índice gigantesco que esta não é a forma mais freqüente da palavra, e educadamente sugerir: “Você quis dizer:  JavaScript?”. A mesma funcionalidade está disponível na API através do método doSpellingSuggestion()  da classe GoogleSearch. Basta passar o termo como parâmetro, que será retornada a sugestão de ortografia, ou null se não houver sugestão. Por exemplo, ao buscar por “Filosofy”, é retornado o termo correto “Philosophy” (veja Listagem 1). Páginas em cache No processo de indexação de uma página, o Google armazena uma cópia em cache. Esta versão arquivada pode ser obtida usando o método doGetCachedPage() , que retorna o código HTML da página. Esse documento pode ser facilmente reexibido por um componente gráfico ou uma taglib, ou, é claro, ser mostrado em um navegador web. Uma maneira simples para obter páginas em cache é mostrada na Listagem 1. Limitações A Google Search API é uma oferta 1  Obra de Lewis Caroll publicada em 1865 e em domínio público desde o início do século passado. Operadores Os termos a seguir possuem interpretação especial e podem ser incluídos na expressão da consulta: Operador Significado Exemplo Intenção + Inclui to be +or not to be “” OR site: Exclui Frase Ou No Site windows -microsoft “Java Magazine”  jsf or struts gosling site:weblogs.java.net daterange: Entre datas  java daterange :2453371-2453736 intitle: allintitle inurl: allinurl: No título Todas no título Na URL Todas na URL hibernate intitle :OnJava allintitle :Java Magazine inurl:google a ll inur l: go og le ske tc hup allintext: No texto allintext:open source java allinlink s: Nos link s allinlinks:google f ilet ype : Tipo de arquivo Subversion book filetype: pdf  -filetype: info: Exceto tipo de arquivo Sobre link: Referenciam Subversion book -filetype:pdf info: www.javamagazine.com.br  link:www.javamagazine.com.br  Livros sobre o software de gerência de configuração Subversion em PDF Livros sobre o Subversion, exceto em formato PDF Informações sobre o site da JM* Páginas com links para o site da JM* Related: Relacionados related:www.javamagazine.com.br  Páginas semelhantes à da JM* cache: Cópia em cache cache:www.java.com Obtém a cópia do cache do Google da página inicial do site comercial de Java da Sun. Incluir o “or” na pesquisa. Normalmente seria ignorado por ser uma palavra muito comum em inglês Páginas com “windows” e sem “microsoft” Busca a frase toda ao invés dos termos separados Páginas com um ou outro termo Posts contendo o nome Gosling nos blogs do site java.net Páginas com o termo “java” publicadas em 2005. Curiosamente, as datas precisam estar no formato Juliano, ou seja, deve ser fornecido o número de dias corridos desde 1 de Janeiro de 4713 a.c. Páginas sobre Hibernate cujo titulo contenha “OnJava” Páginas com os termos Java e Magazine no título Páginas com o termo “google” no endereço Pá gi nas com os te rmos “go og le ” e “ske tc hup ” no e nde re ço Páginas com os termos “open”, “source” e “java” no corpo da página, ignorando título, links e URL. Páginas com o termo “google” nos links, ignorando o texto, o título e a URL. * Deve ser o único termo da consulta 62  Java Magazine • Edição 38  jm38.indb 62 17/7/2006 14:13:34 Restrições R estrições fazem com que a consulta busque apenas em páginas de um determinado país, ou que sejam escrit as em um dado idioma, ou que tratem de alguns tópicos indexados separadamente, etc. Abaixo estão exemplos de restrições que podem ser utilizadas e qual método da classe GoogleSearch  usar para configurá-las: Tópico – setRestrict() unclesam (Governo norte-americano), linux (Siste- maOperacionalLinux), mac ( ComputadoresMacintosh), bsd (Sistema Operacional FreeBSD). Restrições Combinadas – setRestrict() ou setLanguageRestrict() Operador As restrições podem ser combinadas usando os operadores lógicos mostrados na tabela ao lado. Por brevidade, foram apresentadas aqui apenas uma seleção de idiomas, países e tópicos. A lista completa pode ser vista em google. com/apis/reference.html . Significado Exemplo Descrição - Não -lang_pt Exclui resultados em português . E linux.countryBR Resultados apenas do tópico linux de sites no Brasil | Ou lang_br | lang_en Resultados apenas em português ou inglês () Precedência (lin ux).(-(countryUS|countryUK)) Resultados do tópico li nux que não estejam nos EUA ou no Reino Unido Idioma – setLanguageRestrict() lang_pt  (Português), lang_en (Inglês),lang_de (Alemão), lang_fr ( Francês), lang_es (Espanhol). País – setRestrict() countryBR   (Brasil), countryEU   (União Euro- péia), countryUS (Estados Unidos), countryPY (Paraguai), countryPT (Portugal). experimental do Google, limitada a aplicações não-comerciais e a apenas mil consultas por dia. Não há previsão pública de se estender o serviço. Entretanto, para aplicações corporativas, existe uma API semelhante baseada no servidor de busca corporativo do Google, que é um produto à parte (veja links). Outra limitação é que apenas um subconjunto dos operadores de busca do site está disponível para a API. Por exemplo, “stocks:”, “define:”, “movie:”, ou outros serviços, como Images e Froogle, só podem ser usados no site. (Estas e outras opções de busca podem ser conhecidas em  google.com /help/cheatshee t.html ou em  googleguide.com/advance d_ ope rators _refe rence.html.) Por último, a API é muito mais precisa para termos e sites americanos, pelo volume que estes representam no índice total. Por exemplo, a sugestão ortográfica é capaz de corrigir termos mais comuns em português, como “Filosopia”, mas falha em outros pouco publicados, como “Lumbriga”. tões de ortografia. Mas com um pouco de criatividade você poderá usar a API para incrementar praticamente qualquer aplicação, integrando-a ao mais popular mecanismo de busca mundial, e surpreender seus usuários.  Julio Faerman ( [email protected]) é consul- Executando o exemplo Para testar as consultas sugeridas, basta executar a classe  jm.Go ogl eSea rchD emo (Listagem 1), que está também disponível no site da Java Magazine. Deve ser passada como parâmetro a chave de uso (além do classpath, se este não estiver configurado). Por exemplo (em uma linha): tor independente em desenvolvimento de sistemas corporativos e melhoria de processos de software. Certificado SCJP, SCWCD, SCBCD, SCDJWS e SCEA(I), bacharel em Ciência da Computação, MBA em Gerência de Projetos e Mestrando da Universidade Federal de Uberlândia, na área de Inteligência Artificial.  java -cp c:\Java \Goog leAPI\ googlea pi.jar; .  jm.Google SearchDemo  sua_chave  google.com/apis Conclusões A Google API é poderosa e bastante funcional. Mas colocar essa biblioteca de consultas em prática numa aplicação pode não ser tão simples, principalmente pelas limitações da sua versão atual. Algumas destas limitações, no entanto, podem ser dribladas, por exemplo permitindo que cada usuário cadastre sua própria chave de acesso. As aplicações mais beneficiadas diretamente são aquelas que lidam com gerência de conteúdo e sites, podendo mostrar conteúdo semelhante ou suges- Site principal da Google Search API code.google.com Portal para desenvolvedores (geral) code.google.com/enterprise1 Portal para desenvolvedores (clientes corporativos) www.googleguide.com Guia de uso para buscas do Google (criado por terceiros) undergoogle.blogspot.com Blog com dicas e notícias do Google  javamagazine.com.br/downloads/jm38/   jm-googleapi.zip Edição 38 •  Java Magazine 63  jm38.indb 63 17/7/2006 14:13:39 AJAX com Google Escrevendo Aplicações Web Altamen O Google Web Toolkit (GWT) é um framework que define um novo paradigma de desenvolvimento de aplicações AJAX. O seu objetivo é esconder do programador a implementação de código JavaScript, considerando que esta tarefa é repetitiva e propensa a erros, e repleta de tarefas tediosas, como o tratamento de incompatibilidades entre navegadores. O GWT abstrai a linguagem JavaScript a partir de uma biblioteca de classes Java, na qual está disponível uma coleção de componentes visuais AJAX (os widgets),  já conhecidos dos que usam as aplicações AJAX do Google, por exemplo o GMail e o Google Maps. Este tutorial apresenta o GWT e traz um exemplo de implementação utilizando o framework. pilador, distribuído no pacote do próprio framework. O uso de código Java é vantajoso, por exemplo, por permitir que o desenvolvedor utilize a IDE Java de sua preferência, já que o GWT é independente do ambiente de desenvolvimento. Além disso, com o uso de uma IDE, as vantagens da linguagem Java são bem aproveitadas; por exemplo, Vantagens do uso de classes Java A principal novidade apresentada pelo GWT é o uso de classes Java para representar os componentes visuais da aplicação. Estas classes são convertidas em código JavaScript por um com- 64  Java Magazine • Edição 38  jm38.indb 64 17/7/2006 14:13:43 Web Toolkit te Interativas em Java Crie aplicações AJAX a partir de classes  Java, utilizando o novo framework do Google, e deixe que o trabalho pesado seja feito para você DOUGLAS JOSÉ SOARES RODRIGUES a verificação de tipos pelo compilador e a capacidade de completar código ao ser digitado. Arquitetura do Framework Um modelo da arquitetura do GWT é apresentado na Figura 1. A arquitetura é dividida em duas grandes camadas. A camada de bibliotecas contém uma biblioteca de componentes visuais e uma biblioteca de emulação Java, que traz a implementação de algumas classes dos pacotes e  java.util . Estas duas bibliotecas compõem a infra-estrutura básica necessária para representar os componentes AJAX utilizando código Java. A outra camada do GWT é composta por duas ferramentas. A primeira é o compilador de Java para JavaScript, que é responsável por gerar o código JavaScript representando os componentes visuais  java.lang utilizados. A segunda ferramenta é um navegador web local, que evita que o desenvolvedor tenha de converter o seu código Java em JavaScript cada vez que desejar realizar um teste. O navegador local é capaz de exibir os componentes das  bibliotecas sem a necessidade da conversão de código. projeto. Recomenda-se também adicionar o diretório do GWT à variável de ambiente PATH, para facilitar a criação do projeto. A partir do diretório criado para o projeto, execute o comando a seguir: projectCreator –eclipse TutorialGWT Isso cria o projeto. Em seguida, execute este comando (numa mesma linha): Instalação applicationCreator–eclipse TutorialGWT O primeiro passo para utilizar o GWT br.com.javamagazine.client.TutorialGWT é, claro, baixar o pacote a partir da página do framework. O GWT encontra-se Será criada a estrutura básica de um disponível para Windows e Linux. Neste projeto para o Eclipse, com referências às tutorial iremos apresentar as instruções  bibliotecas já configuradas. No Eclipse, de configuração para Windows, lembran-  basta importar o projeto criado (item de do que o procedimento é  bastante semelhante para o Biblioteca de Linux. Foi utilizada a versão Biblioteca de emulação Java Bibliotecas 1.0.21 do GWT; o pacote é componentes visuais (java.lang e java.util) distribuído no formato ZIP e tem 13.9 MB. A instalação é bastante Compilador Java Navegador Ferramentas simples: basta descompara JavaScript Local pactar o arquivo ZIP em um diretório de sua preferência. Neste dire- Figura 1. Arquitetura do Google Web Toolkit. tório estarão as bibliotecas do GWT, e alguns utilitários para a configuração de projetos. O exemplo deste artigo é i mplementado utilizando o Eclipse com o WTP (Web Tools Project). A utilização desse Eclipse se justifica porque o GWT traz ferramentas que automatizam o processo de criação de projetos para esse IDE. Criando um projeto O primeiro passo é a criação de um projeto e uma aplicação. Para isso, serão utilizados dois utilitários fornecidos com o GWT: applicationCreator e  projectCreator. Será necessário criar um diretório para conter os arquivos do Figura 2. Estrutura do projeto de exemplo. Edição 38 •  Java Magazine 65  jm38.indb 65 17/7/2006 14:13:46 AJAX com Google Web Toolkit Listagem 1.TutorialGWT.html Tutorial GWT

Tutorial GWT

       
             
 
                       
Nome: 
Sobrenome: 
E-mail: 
 
 
Listagem 2. TutorialGWT.java package br.com.javamagazine.client; import java.util.*; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.user.client.ui.*; public void onClick(Widget sender) { int i = list.getSelectedIndex(); itens.remove(i); filtrarLista(list, filter.getText()); } });   public class TutorialGWT implements EntryPoint { private List itens = new ArrayList(); //Contatos cadastrados public void onModuleLoad() { final Label label = new Label(“Filtro:”); final ListBox list = new ListBox(); final TextBox filter = new TextBox(); final TextBox firstName = new TextBox(); final TextBox lastName = new TextBox(); final TextBox email = new TextBox(); final Button insertContact = new Button(“Adicionar”); final Button deleteContact = new Button(“Remover”);   list.setVisibleItemCount(5); // Numero de itens exibidos list.setStyleName(“list”);                 RootPanel.get(“label”).add(label); RootPanel.get(“text”).add(filter); RootPanel.get(“list”).add(list); RootPanel.get(“firstName”).add(firstName); RootPanel.get(“lastName”).add(lastName); RootPanel.get(“email”).add(email); RootPanel.get(“insertContact”).add(insertContact); RootPanel.get(“removeContact”).add(deleteContact); } // Listener que trata cada caractere // digitado no campo de filtro filter.addKeyboardListener(new KeyboardListenerAdapter() { public void onKeyUp( Widget sender, char keyCode, int modifiers) { filtrarLista(list, filter.getText()); } });         // Listener que trata o clique no botão ‘Adicionar’ insertContact.addClickListener(new ClickListener() { public void onClick(Widget sender) { inserirContato( list, firstName.getText(), lastName.getText(), email.getText(), filter.getText()); firstName.setText(“”); lastName.setText(“”); email.setText(“”); } }); // Listener que trata o clique no botão ‘Remover’ deleteContact.addClickListener(new ClickListener() { private void inserirContato(ListBox list, String firstName, String lastName, String email, String filter) { String novoContato = lastName + “, “ + firstName + “ (“ + email + “)”;   list.addItem(novoContato);   itens.add(novoContato); filtrarLista(list, filter); } private void filtrarLista(ListBox lista, String filtro) { lista.clear(); for (int i = 0; i < itens.size(); i++) { String item = (String) itens.get(i); if (item.toLowerCase().indexOf( filtro.toLowerCase()) != -1) {   lista.addItem(item); } } } }   66  Java Magazine • Edição 38  jm38.indb 66 17/7/2006 14:13:46 menu File>Import>Existing projects into workspace ), para que as configurações sejam automaticamente aproveitadas. A estrutura do projeto deve ficar como na Figura 2. Implementando o projeto de exemplo Neste tutorial, o problema que iremos resolver é a criação de uma busca incremental, ou seja, uma busca realizada conforme caracteres são digitados. Usuários do navegador Firefox estão acostumados com esta funcionalidade (basta pressionar Ctrl+F para abrir o painel de busca). O exemplo também demonstra como fazer um cadastro simples, mantendo os dados numa coleção em memória. Usaremos uma campo de texto comum para conter o filtro para a busca. Assim que o conteúdo desse campo for alterado, uma Figura 3. Janela de log do navegador local. lista irá exibir apenas os elementos que correspondam ao filtro digitado. Observe que todos os componentes usados (campo de texto, lista) são tipos de campos de formulários HTML comuns, e que não há nenhum tipo de requisição feita ao servidor web (embora isto possa acontecer na solução de outros problemas). Abra o arquivo TutorialGWT.html, gerado pelo toolkit, e o modifique para que corresponda ao conteúdo da Listagem 1. Observe que o arquivo muda pouco, se comparado ao que foi gerado. São definidos oito IDs, que correspondem aos locais onde serão exibidos os componentes definidos na classe Java. E o estilo .list  é definido para posicionar a lista na tela corretamente. O próximo passo é implementar a classe TutorialGWT, que irá descrever o comportamento da busca incremental. No exemplo, foi criado um pequeno catálogo de endereços, onde é possível cadastrar nome, sobrenome e e-mail de um contato, e remover os contatos  já cadastrados. A busca incremental é usada para filtrar os contatos  já cadastrados. Nesta classe são definidos métodos auxiliares para o preenchimento inicial da lista e para realizar a busca na lista por um determinado filtro. O código completo para a classe pode ser conferido na Listagem 2. Executando e compilando Após editar os arquivos HTML e a classe  Java, faça a compilação do projeto com um duplo-clique (dentro do Eclipse) no arquivo gerado TutorialGWT-compile.cmd. Isso gera o código JavaScript e cria o diretório www/br.com.javamagazine.TutorialGWT , com arquivos HTML. Para executar o projeto, dê um duploclique em TutorialGWT-shell.cmd. Serão exibidas duas janelas, uma com o log da execução da aplicação (Figura 3) e outra com o navegador exibindo a aplicação em execução (Figura 4). Conclusões O GWT mostra-se um framework extremamente eficiente e bem escrito. No pacote de download já estão inclusas todas as ferramentas necessárias, e sua integração com a IDE (atualmente, só o Eclipse é suportado) é muito simples. É uma solução robusta para o desenvolvimento AJAX com o suporte de uma empresa renomada. code.google.com/webtoolkit/  Google Web Toolkit eclipse.org/webtools Projeto Eclipse Web Tools  javamagazine.com.br/downloads/jm38/  jm-gwt.zip Douglas José Soares Rodrigues ([email protected] ) é Figura 4. Exemplo de cadastro e busca incremental, exibido no navegador formado em Ciência da Computação pela Unicamp e trabalha como consultor Java há quatro anos. Edição 38 •  Java Magazine 67  jm38.indb 67 17/7/2006 14:13:51 Formatação e Conver Estendendo o framework e aumentando a capa 68  Java Magazine • Edição 38  jm38.indb 68 17/7/2006 14:14:12 são no Struts cidade da sua aplicação web Utilize Converters para resolver problemas de conversão no Struts e deixe seus FormBeans mais completos ARI DIAS NETO O Struts oferece muitas funcionalidades para o tratamento da entrada de dados, mas possui ainda algumas limitações nessa área. Quem utiliza o framework sabe da dificuldade para se tratar, por exemplo, datas e números decimais, e aca ba utilizando strings para representar muitas informações que vêm do usuário. Como sabemos, quando o usuário entra com valores em um formulário e os envia, estes chegam ao servidor em forma de strings. O Struts tenta converter essas strings para os formatos mapeados no FormBean (classe que representa um formulário), e caso não consiga, recebemos erros pouco explicativos ou páginas em  branco; ou pior: os valores podem ser tratados de forma equivocada. Por exemplo, em uma data como 10/03/06, o mês será 10, 03 ou 06? Para nós brasileiros, fica claro que o mês é março – mas e para o sistema? Uma das soluções mais utilizadas é criar métodos no FormBean para tratar os dados enviados. Dessa forma, existiriam no FormBean dois métodos: um para converter para o tipo correto no momento da entrada dos dados, e outro para converter para string no momento da exibição. O problema dessa solução é que ela se repetirá para todos os formulários que precisam da conversão, além de não se aplicar aos DynaActionForms (representações dinâmicas de formulários configuradas no struts-config.xml). Aqui veremos uma solução alternativa, que oferece vantagens. Solução proposta Para demonstrar nossa solução, vamos construir uma aplicação simples, com uma página JSP, um FormBean e uma Action. Usaremos uma classe concreta para representar o formulário, mas poderíamos igualmente utilizar um DynaActionForm. O exemplo completo está disponível no site da Java Magazine. O JSP, como mostra a Listagem 1, constrói um formulário com dois campos de texto; o primeiro para uma data e o segundo para um número decimal. Note que para a construção do formulário utilizamos as tags do Struts  e . O FormBean que representa este formulário terá dois atributos, um do tipo java.util.Date e outro do tipo  java.math.BigDecimal . Veja a Listagem 2; observe que não temos atri-  butos do tipo String. Isso porque faremos o Struts configurar o FormBean com os tipos corretos, ou seja, o próprio framework irá converter os dados enviados pelo usuário para Date e BigDecimal . A Action tem uma implementação simples. Ela faz apenas um forward para o JSP com o formulário (veja a Listagem 3). Nosso objetivo aqui é fazer com que o Struts configure o FormBean com seus devidos atributos. Não nos importa neste ponto o que será feito depois com estes valores. A Listagem 4  mostra o conteúdo do arquivo struts-config.xml. A configuração é simples. Primeiro definimos um formulário dentro do elemento ,com dois atributos: nome e classe. Usamos o nome formBeanTeste e a classe FormBeanTeste. Logo em seguida, temos a configuração da Action dentro do elemento . Configuramos o path, que será a URL chamada pelo formulário no momento da postagem; a classe, através do atributo type; e o mais importante: o nome do FormBean, através do atributo name. O nome deve ser o mesmo dado na configuração do FormBean. Note que, após a execução da Action, iremos retornar para a mesmo formulário (index.jsp) pois também precisamos exibir/formatar os dados corretamente. Esse retorno simula, por exemplo, um formulário de edição que  já possui os dados populados, ou quando há um processo de validação e o usuário é redirecionado ao mesmo formulário seguido dos erros encontrados. Primeira parte da solução Neste estágio, a aplicação ainda não fun- Edição 38 •  Java Magazine 69  jm38.indb 69 17/7/2006 14:14:37 Formatação e Conversão no Struts cionará. Assim que o usuário preencher o formulário e clicar em Enviar, receberá um erro. Isso acontece porque o Struts tenta converter os dados postados para os t ipos correspondentes no FormBean, e não consegue. Por padrão o Struts não vem com os conversores corretos para BigDecimal e Date. É aí que entra a nossa solução. Você já deve ter ouvido falar que o Struts implementa o design pattern Front Controller (veja links). Isso significa que ele possui um controlador que gerencia o tratamento das solicitações, deixando para as Actions a responsabilidade de responder à requisição e de definir o que será retornado para o usuário. O Front Controller do Struts é o servlet org.apache.struts.action.ActionServlet, que está configurado no arquivo web.xml. É justamente neste servlet que podemos interferir Listagem 1. index.jsp: Página com o formulário de exemplo. <%@ taglib uri=”/tags/struts-html” prefix=”html” %> Data:
Valor:
 
Listagem 2. FormBeanTeste.java : Classe que representa o formulário, com dois campos: um Date e outro BigDecimal . package br.com.jm.formbean; import java.math.BigDecimal; import java.util.Date; import org.apache.struts.action.ActionForm; public class FormBeanTeste extends ActionForm { private Date data; private BigDecimal valor; //... Métodos get/set } Listagem 3. PerformPostAction.java: Action que apenas retorna para o formulário com o forward “sucesso”. package br.com.jm.action; // … imports public class PerformPostAction extends Action { public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { /* Neste ponto pode-se obter os valores enviados já com os tipos corretos, / por exemplo: * * FormBeanTeste meuForm = (FormBeanTeste)form; * Date dataEnviada = meuForm.getData(); */ return mapping.findForward(“sucesso”); } } Listagem 4. struts-config.xml : com a configuração de um FormBean e uma Action.           e registrar os nossos converters (classes que executam conversões de tipos, por exemplo, de String   para Date). Para tal, iremos substituir, no arquivo web.xml, o servlet do Struts por um servlet nosso (que estende o do Struts): MeuStrutsServlet. Esse servlet deve fazer tudo que o ActionServlet faz, além de registrar os converters corretos para Date e BigDecimal . A Listagem 5  mostra como fica nosso servlet. Observe que apenas iremos redefinir o método init() e adicionar as linhas que registram os converters corretos, e continuar chamando o método init() da superclasse. A Listagem 6 mostra a configuração do web.xml antes e depois da substituição (apenas a parte alterada). Simplesmente trocamos a classe do servlet, apontando para a nossa. Vamos agora aos converters. Para o converter de data, utilizamos a classe DateLocaleConverter do projeto Jakarta Commons BeanUtils (veja links). Passamos como parâmetros o locale e o formato da data que chegará ao converter. Neste caso, usamos o formato “dd/MM/yyyy”. Infelizmente, para o conversor de BigDecimal não podemos ainda utilizar o BigDecimalLocaleConverter  (também do BeanUtils), pois há atualmente uma incompatilidade entre esse conversor e o Struts. Então, iremos criar a nossa própria classe que implementa a interface org.apache.commons.beanutils.Converter. Vamos chamá-la de BigDecimalConversor (Listagem 7). A classe BigDecimalConversor  terá um método converter() que receberá dois parâmetros: um  java.lang.Objec t e o tipo de classe para qual deverá converter o Object. Como registramos o conversor para apenas o tipo BigDecimal  converteremos sempre para esse tipo. Além disso, a implementação de exemplo já faz o tratamento de exceções. Se houver algum erro, um valor padrão poderá ser retornado. Testando os conversores Agora que já temos os conversores prontos, vamos fazer um teste. Rode a aplicação em qualquer container web, como o Tom- 70  Java Magazine • Edição 38  jm38.indb 70 17/7/2006 14:14:43 cat. A primeira página a ser exi bida será a index.jsp. Preencha o formulário conforme a Figura 1 e envie os dados. Se tudo correr bem, após a requisição nenhum erro ocorrerá; ou seja, o Struts terá utilizado os nossos converters. Mas ainda temos um problema. Note que tanto a data como o número decimal estão com formatações erradas após o retorno (veja a Figura 2). A data não está formatada para o padrão configurado no converter, e o número decimal não está com a notação  brasileira. Isso acontece porque os converters tratam a entrada de dados, mas não a exi bição. Os dados foram convertidos corretamente, porém ao ser reexibido o formulário, não foi feita a formatação correta. A tag não trata os atributos do FormBean levando em conta os padrões locais. Por isso muitos desenvolvedores colocam métodos Listagem 5. MeuStrutsServlet.java: Servlet que registra os converters e substitui o servlet do Struts. package br.com.jm.servlet; import import import import java.math.BigDecimal; java.util.Date; java.util.Locale; javax.servlet.ServletException; import org.apache.commons.beanutils.ConvertUtils; import org.apache.commons.beanutils.locale.converters.DateLocaleConverter; import org.apache.struts.action.ActionServlet; import br.com.jm.converter.BigDecimalConversor; public class MinhaStrutsServlet extends ActionServlet { public void init() throws ServletException {   super.init(); Locale locale = new Locale(“pt”, “BR”); //criação dos conversores DateLocaleConverter dateConverter = new DateLocaleConverter(locale,“dd/MM/yyyy”); BigDecimalConversor bigDecimalConversor = new BigDecimalConversor(locale, new BigDecimal(“0”), true); //registro dos conversores ConvertUtils.register(dateConverter, Date.class); ConvertUtils.register(bigDecimalConversor, BigDecimal.class); } } Edição 38 •  Java Magazine 71  jm38.indb 71 17/7/2006 14:14:52 Formatação e Conversão no Struts no FormBean para formatar estes dados antes da exibição. Essa prática, no entanto, não é recomendada, pois se repetirá para todos os formulários que trabalham com dados diferentes de strings, deixando o desenvolvimento mais lento e diminuindo a reutilização do código.  Segunda parte da solução   formate o conteúdo que irá exibir. Para isso, iremos substituir a classe que implementa a taglib.  Aqui é importante lembrar que as taglibs são configuradas em arquivos chamados tag library descriptors (TLDs), que informam quais atributos a tag pode ter, além de indicar a cl asse que implementa a tag. Chegamos à segunda parte da solução. Precisamos fazer com que a tag Para substituir a tag podemos adotar Listagem 6.Trecho do web.xml , antes e depois da substituição da Action. Antes da substituição action org.apache.struts.action.ActionServlet Depois da substituição action br.com.jm.servlet.MinhaStrutsServlet Listagem 7. BigDecimalConversor.java: Converter personalizado para BigDecimal. package br.com.jm.converter; import import import import java.math.BigDecimal; java.text.DecimalFormat; java.text.ParseException; java.util.Locale; import org.apache.commons.beanutils.ConversionException; import org.apache.commons.beanutils.Converter; public class BigDecimalConversor implements Converter { private Locale locale; private BigDecimal valorPadrao; private boolean useValorPadrao; public BigDecimalConversor(Locale locale, BigDecimal valorPadrao, boolean useValorPadrao) { this.locale = locale; this.valorPadrao = valorPadrao; this.useValorPadrao = useValorPadrao; } public Object convert(Class classe, Object valor) { try { Object resultado = parse(valor); if (resultado == null || resultado instanceof BigDecimal) { return resultado; } return new BigDecimal(resultado.toString()); } catch (Exception ex) { if (useValorPadrao) { return valorPadrao; } else { throw new ConversionException(“Erro ao instanciar BigDecimal”); } } } private Object parse(Object valor) throws ParseException { DecimalFormat formatter = (DecimalFormat) DecimalFormat.getInstance(locale); return formatter.parse((String) valor); } } duas abordagens. A primeira é criar uma nova taglib, ou seja, um novo arquivo .tld e uma nova classe que estende a tag do Struts. Esta abordagem segue as boas práticas de utilização do framework, pois não altera nenhum arquivo original do Struts e deixa o código nas páginas JSP mais légivel, já que utiliza uma taglib própria. É a abordagem indicada para aplicações que estão iniciando o processo de desenvolvimento. A segunda, e a que adotaremos aqui, é apenas editar o arquivo struts-html.tld e substituir o nome da classe que implementa a tag. Esta solução é indicada para aplicações que já estão avançadas no processo de desenvolvimento, e em que um refactoring de todas as JSPs que utilizam esta taglib seria realmente muito custoso. O arquivo struts-html.tld é utilizado para configurar várias taglibs, por isso temos que fazer a alteração apenas na parte referente à tag . A Listagem 8 mostra o trecho relevante do arquivo de configuração antes e depois da mudança. Note que alteramos a linha onde está a definição da classe: o nome da classe muda de org.apache.struts.taglib.html.TextTag para br.com.jm.taglib.Mi nhaTextTag. AListagem9 mostra a classe da nossa taglib, que estende org.apache.struts.taglib.html.TextTag e redefine formatValue(). Este método será chamado antes da exibição do conteúdo e tem implementação simples. Verificamos o objeto que é passado como argumento, Figura 1. Formulário preenchido com valores de teste. Figura 2. Exibição do formulário após seu envio. Data e Valor com formatação. 72  Java Magazine • Edição 38  jm38.indb 72 17/7/2006 14:15:08 Edição 38 •  Java Magazine 73  jm38.indb 73 17/7/2006 14:15:11 Formatação e Conversão no Struts e caso seja uma instância de BigDecimal, fazemos a formatação utilizando a classe  java.text.DecimalFormat . Mais uma vez, o parâmetro Locale(“pt”, “BR”) é utilizado. Já se o objeto passado for do tipo Date, formatamos para o padrão de exibição desejado, nesse caso “dd/MM/yyyy”. Esta segunda abordagem que apenas substitui o nome da classe no arquivo struts-html.tld, pode, em uma fase de manuteção, deixar os desenvolvedores um pouco confusos, já que praticamente escondemos a nova configuração e a criação da nova taglib. Por outro lado, pode ser a salvação para aqueles que já possuem milhares de  JSPs e não querem ter de alterá-los caso seja criada uma nova tag. Analise a melhor solução para a sua aplicação levando em conta a legibilidade do código e a facilidade de manutenção da sua aplicação. Testando a solução Vamos testar a solução completa. Reinicie a aplicação e digite os mesmos dados que usamos na primeira vez, como já mostrado na Figura 1. Após clicar no botão Enviar, o formulário deverá aparecer com os dados formatados corretamente. Note que três coisas aconteceram durante o processamento da requisição: 1.   O Struts converteu os dados e configurou o FormBean; 2.  A Action redirecionou o usuário para o mesmo formulário; Listagem 8. struts-html.tld  , antes e depois da substituição da classe que implementa a tag.  Antes da substituição   text   org.apache.struts.taglib.html.TextTag ... 3. E por último, no momento da exibição, a taglib formatou os dados exatamente como haviam sido digitados. Dessa maneira, seus FormBeans poderão ter atributos mapeados para qualquer classe Java, desde que você registre um conversor responsável para ela e estenda as taglibs. Essa mesma solução se aplica também para formulários dinâmicos (os DynaActionForms). Conclusões Neste artigo, vimos como registrar converters personalizados no Struts e como formatar formulários para exibição ou edição. Uma solução mais rica poderia aceitar a configuração dos converters via XML. Dessa forma, parâmetros do sistema, como o padrão de formatação da data, não estariam diretamente no código, e sim num resource da aplicação. E possivelmente teríamos apenas um objeto  java.util.Loc ale instanciado por sessão do usuário. Depois da substituição   text   br.com.jm.taglib.MinhaTextTag ...  struts.apache.org Framework Apache Struts: downloads e documentação. Listagem 9. MinhaTextTag.java: Classe que substituirá a implementação da taglib Text  do Struts.  jakarta.apache.org/commons package br.com.jm.taglib; Jakarta Commons, componentes reutilizáveis para vários fins. // … imports public class MinhaTextTag extends TextTag{ public MinhaTextTag(){   super(); this.type = “text”; doReadonly = true; } protected String formatValue(Object value) throws JspException { Locale locale = new Locale(“pt”,”BR”); if(value instanceof BigDecimal){   try{ DecimalFormat formatter = (DecimalFormat) DecimalFormat.getInstance(locale); return formatter.format(value); } catch(Exception e){ return super.formatValue(value); } } if(value instanceof Date){   try{ SimpleDateFormat sdf = new SimpleDateFormat(“dd/MM/yyyy”); return sdf.format(value); } catch(Exception e){ return super.formatValue(value); } } return super.formatValue(value); } }  java.sun.com/developer/technicalArticles/  Intl/IntlIntro/  Uma visão geral sobre internacionalização  java.sun.com/blueprints/corej2eepatterns/  Patterns/FrontController.html  Sobre o design pattern Front Controller  javamagazine.com.br/downloads/jm38/   jm-strutsconverters.zip Ari Dias Neto ([email protected]) é con- sultor Java/JEE com experiência de mais de sete anos em tecnogias para web. Atualmente atua em projeto internacional para IBM e tem certificações SCJP, SCWCD, EA(I) e de Borland CaliberRM. 74  Java Magazine • Edição 38  jm38.indb 74 17/7/2006 14:15:21  jm38.indb 75 17/7/2006 14:15:36