java 69 [Introdução Spring Security] [Lido]

76

Transcript of java 69 [Introdução Spring Security] [Lido]

Page 1: java 69 [Introdução Spring Security] [Lido]

java 69.indb 1 26/05/2009 16:36:18

Page 2: java 69 [Introdução Spring Security] [Lido]

java 69.indb 2 26/05/2009 16:36:21

Page 3: java 69 [Introdução Spring Security] [Lido]

Sumário

Easy Java, Core08 – Um pouco de GroovyUma linguagem de scripts simples e 100% compatível com Java[ Marcelo Castellani ]

[Easy Java] Artigos introdutórios sobre a linguagem Java, APIs

ou ferramentas.

[Core] Técnicas Server-side, ferramentas, IDEs, e outros assuntos

que fogem às demais categorias.

[Web] Artigos sobre ou que envolvam técnicas de desenvolvimento

para WEB.

[Tutorial] Artigo no estilo tutorial passo-a-passo.

[Mobile] Artigo sobre as plataformas Java ME, Android, JavaCard,

ou outras móveis/embutidas/wireless.

[Vanguarda] Artigos sobre tecnologias de ponta, que ainda não

fazem parte do dia-a-dia do desenvolvedor mas que prometem ser

a próxima febre.

Olá, eu sou o DevMan! Desta página em diante, eu estarei lhe ajudando a compreender com ainda mais facilidade o conte-údo desta edição. Será um prazer contar com sua companhia! Confira abaixo o que teremos nesta revista:

Você percebeu os ícones ao lado de cada matéria? Eles in-

dicam o que você vai encontrar no artigo – dessa forma,

você também pode ter uma idéia geral do que vai encon-

trar nesta edição como um todo! Os editores trabalham

sempre no sentido de fechar a revista seguindo esta defi-

nição, para oferecer a você o melhor conteúdo didático!

Confira abaixo a lista com a definição dos tipos de artigo encontrados nesta edição:

[Boas práticas] Um dos objetivos da revista é levar para o lei-

tor não somente as melhores técnicas, mas também as melhores

práticas de desenvolvimento, orientadas ao aumento da qualidade

e produtividade.

Vanguarda, Core

52 – Novos tempos: javax.timeA nova API de Data e Hora, que facilita a programação e corrige falhas históricas das suas antecessoras[ Daniel Cicero Amadei e Michael Nascimento Santos ]

60 – Java ME Platform SDK 3As novidades do novo SDK para Java ME, que substitui o antigo Wireless Toolkit[ Ernandes Mourão Júnior ]

Mobile

68 – Estratégias de Integração de Aplicações Java EEMelhores práticas de interoperabilidade Java para o desenvolvimento de aplicações robustas[ Marco Aurélio de Souza Mendes ]

Boas Práticas

Java

Boas

Prá

ticas

Web, Tutorial28 – Spring SecuritySegurança simples, poderosa e portável - à moda do SpringFramework[ Michel Zanini ]

Core, Web, Mobile

40– JavaFX ScriptUma referência didática da linguagem JavaFX Script, uma das principais peças da plataforma JavaFX[ Osvaldo Pinali Doederlein ]

Core, Web16 – JBoss Application Server 5As principais novidades do JBoss AS 5[ Bruno Rossetto Machado e João Paulo Viragine ]

Easy

Java

java 69.indb 3 26/05/2009 16:36:23

Page 4: java 69 [Introdução Spring Security] [Lido]

Acapa desta edição é dedicada ao servidor de aplicações JBoss, o que aconteceu pela última vez há dois anos (Edição 46). Nesse ínterim cobrimos vários softwares da “família JBoss” (Hibernate, Seam,

ESB...), mas o JBoss AS andou longe dos holofotes, que em geral destacam novidades. Como o novo JBoss AS 5, finalmente liberado. Esta nova versão tem grande importância devido ao suporte certificado à plataforma Java EE 5 e também à renovação da arquitetura interna do servidor – como explica nosso artigo, numa cobertura aprofundada que faz jus ao release.

Continuamos também acompanhando o lado Spring da força, dessa vez com foco no Spring Security, que oferece facilidades de controle de acesso e autenticação poderosas e simples de integrar à sua aplicação.

A palavra “integração”, por sinal, provavelmente pode ser encontrada em qualquer edição da Java Magazine. O site eaipatterns.com e o livro que o acompanha são a mais importante linguagem de design patterns disponível para o desenvolvedor da geração SOA. O artigo sobre Integra-ção de Aplicações Java EE apresenta esta linguagem, de forma orientada à plataforma Java.

Dois artigos tratam de linguagens de programação alternativas para a JVM. No primeiro, terminamos a cobertura inicial da plataforma JavaFX com um texto dedicado à linguagem JavaFX Script. No segundo, voltamos à linguagem Groovy – já apresentada anteriormente, mas cujo interesse vem sido renovado recentemente em razão de grande progresso na maturidade da sua implementação e de seus frameworks.

A plataforma Java ME é representada pelo artigo sobre o novo Java ME SDK 3, que nesses tempos de competição acirrada no espaço mobile, é outra renovação crítica do arsenal do Java, aposentando o velho e enferrujado Wireless Toolkit. E na mesma linha de “novos tempos”, cobrimos a nova API javafx.time, que promete corrigir de uma vez por todas uma área de funcionalidade da Java SE que vem sendo criticada desde o JDK 1.0.

Boa leitura,Osvaldo Doederlein

[email protected]

Carta ao LeitorEdiçãoEditores

Osvaldo Doederlein ([email protected])

Eduardo Spínola ([email protected])

ArteDiagramação Romulo Araujo

Capa Antonio Xavier

ProduçãoGerência de Marketing Kaline Dolabella

Coordenação Geral Daniella Costa ([email protected])

DistribuiçãoFernando Chinaglia Distribuidora S.A.

Rua Teodoro da Silva, 907, Grajaú - RJ

CEP 20563-900, (21) 3879-7766 - (21) 2577-6362

Atendimento ao leitorA 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 3382-5025.

Edições anterioresAdquira 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.

[email protected] – 21 3382-5025

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.

Java, o logotipo da xícara de café Java e todas as marcas e logotipos baseados em ou referentes a Java são marcas comerciais ou marcas registradas da Sun Microsystems, Inc. nos Estados Unidos e em outros países.

Fale com o Editor!

É muito importante para a equipe saber o que você está achando da revista: que tipo de artigo você gostaria de ler, que artigo você mais gostou e qual artigo você menos gostou. Fique a vontade para entrar em contato com os editores e dar a sua sugestão!Se você estiver interessado em publicar um

artigo na revista ou no site Java Magazine, entre em contato com os editores, infor-mando o título e mini-resumo do tema que você gostaria de publicar:

Eduardo Spínola - Editor da [email protected]

C

C

S

anjava 69.indb 4 26/05/2009 16:36:31

Page 5: java 69 [Introdução Spring Security] [Lido]

Conheça nossos frameworks open-source

O framework genesis garante uma maior produtividade no desenvolvimento de aplicações desktop, permitindo a utilização de Swing, SWT e Thinlet de forma declarativa e com suporte a anotações como forma de evitar as complexidades e particularidades de cada API gráfica. Seu modelo de integração entre interface e camada de negócios possibilita que aplicações locais, implementadas de forma simples e facilmente testável, possam ser posteriormente dis-ponibilizadas em arquitetura rich-client distribuída, simplesmente reconfigurando-se sua lógica de negócios para execução remota em servidores Java EE. Além de open-source e gratuito, o genesis possui extensa documentação (em inglês e português) e uma ativa comunidade de desenvolvedores.

Uma empresa premiadaEntre os projetos que já contaram com a consul-

toria da Summa Technologies, incluem-se os três únicos sistemas brasileiros premiados com o Duke

Award, conferido anualmente durante o JavaOne Conference: Cartão Nacional de Saúde do Datasus

(2003); IRPF Multiplataforma da Receita Federal e Serpro (2004); e Sistema Integrado de Agenda-

mento de Pacientes da Secretaria de Saúde da Prefeitura de São Paulo (2005).

E m b u s c a d e n o v o s d e s a f i o s e m s u a c a r r e i r a ? E n v i e s e u c u r r í c u l o p a r a : c u r r i c u l o @ s u m m a . c o m . b r

O DevWare é um ambiente virtual completo de desenvolvimento já insta-lado e configurado, composto exclusivamente por produtos open source. Inclui controle de issues e de versão, automação de buid, fórum, wiki corporativa, servidores web, email e ftp, repositório maven2, servidor ldap para controle de usuários, console administrativo, entre outros. Com baixo consumo de re-cursos e baseado em tecnologia de virtualização, o DevWare foi projetado especialmente para facilitar tarefas administrativas como backup e migração entre máquinas. Consulte-nos para saber como o DevWare, combinado com boas práticas de desenvolvimento, pode aumentar a qualidade e produtividade de seus projetos Java.

Os frameworks genesis e DevWare foram criados pela Summa Technologies, disponibilizados de forma livre e gratuita (licença open source LGPL).

Para maiores informações, downloads edocumentações consulte os sites: https://genesis.dev.java.net/https://devware.dev.java.net/

Conheça nosso novo web site.

DevWare

genesis

Consultoria . Arquitetura . Mentoring . Treinamento . Framework . Componentes

Summa Technologies do Brasil . +55.11.3055.2060 . www.summa.com.br

anuncio summa 2008 indd 1 17/12/2008 18:37:23java 69.indb 5 26/05/2009 16:36:32

Page 6: java 69 [Introdução Spring Security] [Lido]

Você pode comprar todas as edições anteriores da Java Magazine através do site DevMedia! Para isso basta acessar https://seguro.devmedia.com.br/edicoes_anteriores.asp

Edições Anteriores da Java Magazine

Brinde na web desta edição

Spring, Hibernate e JSF na prática.

Para visualizar acesse o link:http://www.devmedia.com.br/articles/listcomp.asp?keyword=jm69&codigobanca=jbossas5

5Vídeos

O portal www.devmedia.com.br possui mais de e sobre desenvolvimento de software! Agora você pode comprar as vídeo aulas que preferir e fazer

sua própria combinação de vídeos! Saiba mais em www.devmedia.com.br/creditos

Informativo Java Magazine

Portal Java Magazine www.devmedia.com.br/java

A Java Magazine tem que ser feita ao seu gosto. Para isso, precisamos saber o que você,

leitor, acha da revista!

Dê seu voto sobre esta edição, artigo por artigo, através do link: www.devmedia.com.br/javamagazine/feedback

Para votar, você vai precisar do código de banca desta edição, que é:

Dê seu feedback sobre esta edição!

seu Feedback

sob

reestaedição

java 69.indb 6 26/05/2009 16:36:37

Page 7: java 69 [Introdução Spring Security] [Lido]

Editorial3.indd 7 05/06/2009 16:42:31

Page 8: java 69 [Introdução Spring Security] [Lido]

SEÇÃO EASY JAVA: NESTA SEÇÃO VOCÊ ENCONTRA ARTIGOS PARA INICIANTES EM JAVA

8 Java Magazine Edição 69

De que se trata o artigo:

Apresenta uma introdução a linguagem dinâmica Groovy, que possibilita ter uma produtividade de

linguagens dinâmicas como Python e Ruby dentro da máquina virtual Java, sem emendas.

Para que serve:

Tornar o desenvolvimento em Java mais rápido e produtivo, além de apresentar novos conceitos,

como closures, não disponíveis na linguagem Java, que podem facilitar a vida do desenvolvedor em

tarefas corriqueiras.

Em que situação o tema é útil:

Para agilizar o desenvolvimento de aplicações Java, otimizando situações onde a mesma é muito verbosa,

como manipulação de XML por exemplo. Groovy possibilita, através de mecanismos como closures, uma

sintaxe mais limpa e produtividade em alto nível.

Um pouco de Groovy:

É possível programar para a plataforma Java sem usar a linguagem Java, e ainda por cima ser extrema-

mente produtivo. Groovy é uma linguagem dinâmica, flexível e que se integra com Java sem emendas,

além de fornecer recursos como closures e atribute accessors, não disponíveis na linguagem padrão da

JVM. Groovy, ao contrario de outras linguagens dinâmicas, possibilita gerar bytecodes Java e possibilita o

uso de toda a infra-estrutura já desenvolvida para suas aplicações.

Linguagens dinâmicas estão na moda já há algum tempo. Desde o advento de frameworks de alta

produtividade como o Ruby on Rails e o Django, linguagens como Ruby e Python saíram de seus nichos e passaram a fazer parte das rodinhas de conversa de desen-volvedores Java, outrora um tanto quanto seletivos. Esses, então, descobriram um admirável novo mundo, com closures, ti-pos de dados complexos e facilidades que não existem na sua linguagem preferida. Foi mais ou menos nesse meio que surgiu o embrião do que viria a ser o Groovy.

Como tudo começouNo dia 29 de agosto de 2003 James Stra-

chan publicou em seu blog o primeiro ar-tigo sobre aquilo que viria a ser o Groovy (veja em Links o endereço do post). Ele deixava bem claro as suas intenções na época: “minha idéia inicial é fazer uma pequena linguagem dinâmica, que seja compilada diretamente em classes Java e que tenha toda a produtividade elegante encontrada em Ruby e Python, mas que permita reusar, estender, implementar e testar código Java já existente”.

James procurava uma linguagem di-nâmica para desenvolver em plataforma Java, e em seu post ele deixava claro que as opções da época não eram interessan-tes. Ele não queria apenas uma linguagem dinâmica, mas sim algo que pudesse ser integrado ao que ele já tinha pronto em Java, algo que acelerasse seu desenvolvi-mento e que não o obrigasse a jogar tudo o que tinha de código Java já pronto e testado (e em produção) no lixo. Enfim, ele queria algo que não existia na época.

Mas como querer é poder, James uniu-se a Bob McWhirter e juntos fundaram o projeto Groovy em 2003. Logo, com um grupo de pessoas que compartilhavam da

mesma idéia, iniciaram o desenvolvimento da linguagem. Foi em 2004, com a funda-ção do GroovyOne e a entrada de outros desenvolvedores (entre eles Guillaume Laforge – hoje o mantenedor do projeto) que a coisa decolou. Foi criada a Groovy Language Specification (GLS) e o kit para testes de compatibilidade (o TCK), além do parser básico da linguagem. O embrião do projeto estava pronto e a partir daí não teria mais como voltar atrás.

Groovy evoluiu desconhecido por algum tempo, e até dezembro de 2007 várias versões foram lançadas sob o número 1.1.x. Em 7 de dezembro de 2007 a versão final da família 1.1 foi lançada, e então nomeada Groovy 1.5 devido às diversas modificações reali-zadas na mesma. Hoje a linguagem é uma especificação do JCP (JSR 241) e é

considerada a segunda linguagem oficial da plataforma.

Ao contrario do que alguns pensam, Groovy não é um concorrente do Java, mas uma ferramenta de apoio, de produ-tividade, como veremos neste artigo.

O que é e pra que serve o Groovy?O web site oficial da linguagem possui

uma das melhores definições sobre a linguagem, a qual reproduzo a seguir: “Groovy é uma linguagem ágil e dinâmica para a Plataforma Java com recursos que são inspirados em linguagens como Python, Ruby e Smalltalk, tornando-os disponíveis aos programadores Java, usando uma sintaxe mais próxima do Java”. Ou seja, Groovy possui uma sintaxe semelhante ao Java, mas com o poder de linguagens dinami-camente tipadas.

java 69.indb 8 26/05/2009 16:36:43

Page 9: java 69 [Introdução Spring Security] [Lido]

MARCELO CASTELLANI

Edição 69 Java Magazine 9

Mas Groovy não é apenas uma lin-guagem de script. Groovy pode ser compilada, gerando bytecodes Java, ou seja, um arquivo de código fonte Groo-vy pode virar um arquivo .class (e esse recurso você não encontra por exemplo no JRuby). Isso garante que a única coisa que você precisa para rodar seus códi-gos Groovy no ambiente de produção é a máquina virtual Java (ou seja, nada mais do que usualmente já precisaria) e o jar com o runtime e API`s do Groovy. É comum dizer que Groovy roda inte-grado com o Java sem emendas, o que não acontece com seus “concorrentes”, por assim dizer.

Mais do que isso, o Groovy é totalmente integrado ao Java no mais baixo nível. Por exemplo, se você instanciar um obje-to do tipo Date em Groovy esse nada mais é do que uma instância de java.util.Date. E tudo funciona de maneira transparente por que, por debaixo dos panos, tudo é bytecode Java.

Aí você me pergunta “ok, então pra que eu preciso disso?”, e a resposta é simples: para facilitar sua vida. Groovy possui uma sintaxe mais simples e enxuta do que o Java, apesar de ainda parecer Java, e possui recursos poderosos que não são encontrados na linguagem Java, como clo-sures. E Groovy possui um grande aliado, o Grails, um framework de produtividade baseado em Spring e Hibernate que per-mite o desenvolvimento de aplicações Java EE com a mesma agilidade do pes-soal do Ruby on Rails (e sem configurar centenas de arquivos XML!).

Outro ponto importante é que ambos, Groovy e Grails, são hoje propriedades da SpringSource, empresa que mantém o framework Spring. A empresa adquiriu a G2One, que cuidava de ambos, em 11 de novembro de 2008 e em seu site (nova-

mente na seção Links) é possível ver uma nota interessante sobre o assunto.

O que preciso para desenvolver em Groovy?

Como qualquer outra linguagem, para desenvolver em Groovy você precisa de um editor de textos, de um interpretador/com-pilador e outras ferramentas. Felizmente o NetBeans nos fornece tudo o que precisa-mos (e até mais) num único pacote.

O NetBeans é uma excelente IDE man-tida pela Sun e desenvolvida por uma grande comunidade ao redor do mundo. Ela possui suporte nativo a Java, C/C++, PHP, JavaScript, Ruby e Groovy. Para este artigo vou usar a versão 6.5 da IDE rodan-do no Mac OS X versão 10.5.6. Você pode baixar gratuitamente o NetBeans de seu site (veja o endereço no quadro Links).

Caso deseje usar o Eclipse (que também suporta Groovy via plugins) ou outra IDE para testar os códigos deste artigo, ou mesmo um editor de textos simples como o GEdit do Gnome ou o Notepad do Windows, você deverá configurar o am-biente. Para isso recomendo que acesse a página do projeto na internet. Porém, caso ainda não use o NetBeans, dê uma chance a ele. Essa é a oportunidade de conhecer duas ferramentas novas e de alta qualidade ao mesmo tempo.

Alô mundo Vamos começar nossa viagem pelo

admirável mundo novo do Groovy com um exemplo extremamente simples. Sou fã do tradicional Alô mundo, apesar de ser um exemplo simples para iniciar numa linguagem. No nosso caso ele será

Figura 1. Criação de um novo projeto Java.

java 69.indb 9 26/05/2009 16:36:43

Page 10: java 69 [Introdução Spring Security] [Lido]

10 Java Magazine Edição 69

suficiente para apresentar muitos recur-sos, como attribute accessors, como usar Groovy dentro do Java e muito mais.

Abra o NetBeans (ou o ambiente de sua escolha) e crie uma nova aplicação Java. Você verá uma categoria Groovy na jane-la de Novo Projeto, mas ela tem apenas um template para a criação de um projeto Grails. Como este não é o escopo deste artigo vamos ignorar essa categoria de projetos. Para isso use a categoria Java, como na Figura 1.

Clique no botão Próximo e então infor-me um nome para seu aplicativo (eu usei o singelo nome “AloMundoGroovy”) e selecione onde o deseja salvar. Clique em Finalizar e seu aplicativo será criado. Até agora não colocamos nem um pouco de Groovy no projeto, ele é um tradicional e simples projeto de aplicação Java que você já conhece.

Vamos adicionar então o Groovy ao projeto. Para isso clique com o botão de atalho do mouse sobre o projeto e selecione o menu Propriedades. Na janela que será aberta selecione o item Groovy na lista de categorias e marque a opção Ativar Groovy, como na Figura 2.

Agora nosso projeto já possui Groovy em sua estrutura. Perceba, na Figura 3,que, no grupo Categorias, no navegador do projeto, foi adicionado o groovy-all.jar,que é quem faz a “mágica” para nós.

Por padrão o NetBeans criará um arqui-vo .java no nosso projeto. Remova-o pois não o usaremos, e então crie um pacote chamado org.groovy.maonamassa para adicionarmos os códigos-fonte de nosso projeto. Dentro desse pacote adicione um novo JFrame e, na janela de design do NetBeans, adicione uma caixa de texto ao JFrame, como na Figura 4.

Agora vamos adicionar um arquivo .groo-vy em nosso projeto. Para isso clique sobre o pacote criado e clique com o botão de atalho do mouse. Selecione então a opção Novo>Outro, e na janela que será aberta, na categoria Groovy, selecione Classe do Groovy. Nomeie-a como considerar mais interessante, sem a necessidade de ser o nome da classe principal, pois Groovy não faz essa diferenciação como o Java.

Vamos adicionar o código à nossa clas-

Figura 2. Adicionando Groovy ao projeto.

Figura 3.

Figura 4. Um JFrame com uma caixa de texto dentro.se Groovy. Para isso, digite o código da Listagem 1.

Perceba que não usamos ponto-e-vírgula no final de nossa declaração, e que usamos a palavra reservada def na criação de nos-so objeto (sim, objeto, da classe Object). O restante deve ser conhecido para progra-madores Java. Nossa classe Groovy está pronta para uso. Basta editarmos o código de nosso JFrame para colocar tudo em fun-cionamento. O código do JFrame deverá ficar como apresentado na Listagem 2.

Repare na linha em negrito, é nela que chamamos o método getSaudacao() de nossa classe Groovy. Se você olhou o código da Listagem 1 e não achou esse método não se preocupe, ele é criado através de um recurso comum no Groovy e no Ruby, que é chamado attribute accessor. Esse recurso cria os getters e setters para propriedades de uma maneira simples e eficaz, sem excesso de código. Isso acontecerá sempre que você definir um membro de sua classe sem especificar a visibilidade (protected,public ou private): o Groovy o considera como uma propriedade e define automaticamen-te os getters e setters.

A mesma classe da Listagem 1, escrita em Java, teria o dobro do tamanho. Veja na Listagem 3.

Note que parte de nosso projeto foi feito em Java (para tirar proveito do editor visual do IDE), mas uma parte foi feita em Groovy (e isso deixou as coisas mais simples – uma linha ao invés de sete), e ambos funcionam bem juntos, como é possível ver na Figura 5.

O leitor mais atento deve ter reparado no .toString() junto ao nosso método get-Saudacao(), mostrado na Listagem 2, o que mostra que tanto o getter como o setter de saudacao trabalham com um Object. Isso se deve ao fato de que não definimos o tipo de nosso objeto no momento da sua criação com o def. Para corrigir, modifi-que o código Groovy para ficar como o da Listagem 4 e remova o .toString() da Listagem 2. Verifique que agora ambos os métodos getter e setter trabalham com String e não com Object. É possível ser menos verboso ainda e deixar de utilizar o def, pois ele pode ser omitido quando especificamos o tipo do objeto.

GDKAssim como o Java possui a JDK, o

Groovy possui a GDK. É fácil confundir-

java 69.indb 10 26/05/2009 16:36:44

Page 11: java 69 [Introdução Spring Security] [Lido]

Edição 69 Java Magazine 11

se quando pensamos nisso pois todo objeto Java pode ser usado dentro do Groovy, mas o contrario não é verdade. A GDK estende a JDK adicionando mé-todos que não existem originalmente nos objetos Java.

Um exemplo seria como obter o tama-nho de uma determinada instancia de uma classe. Em Java isso é bem confuso pois existem objetos que usam o método length() (como os que são instancias de arrays e Strings), outros usam o método size() (como os que são instancias de Col-lections e Maps). Temos até um getLength()(para java.lang.reflect.Array) e o método groupCount(), para instancias da classe Matcher.

Groovy, através de um dispositivo chamado MetaClass, possibilita que todos esses objetos utilizem um mesmo método para obter o tamanho de um objeto: o size(). Isso possibilita termos o código da Listagem 5, onde temos tanto um ArrayList quanto uma String usando o mesmo método, o size().

Outra vantagem do GDK sobre a bi-blioteca padrão do Java é que Groovy não diferencia entre tipos primitivos e objetos. Em Groovy a expressão valor01 + valor02, considerando valor01 e valor02 do tipo java.lang.Integer, retorna a soma dos dois inteiros. Mas o Groovy vai além, definindo uma equivalência entre ope-radores e métodos: no caso, a expressão acima será interpretada como valor01.plus(valor02). Se você quiser criar novas classes com suporte a operadores, basta definir nela o método que será chamado para cada operação (para + o método é o plus(), para – o método é o minus(), para ++é next() e por aí vai – consulte a documen-tação do Groovy para a lista de métodos e operações correspondentes).

Pense na utilidade prática disso. Quan-tas vezes você já não teve uma classe em que seria conveniente usar o operador +

Listagem 1.

package org.groovy.maonamassa

class AloMundoGroovy { def saudacao = “Alô mundo, em Groovy !!!”}

Listagem 2. O código de nosso JFrame

package org.groovy.maonamassa;

public class MostrarJFrame extends javax.swing.JFrame { AloMundoGroovy meuAloMundo = new AloMundoGroovy();

/** Creates new form MostrarJFrame */ public MostrarJFrame() { initComponents(); String aloMundo = meuAloMundo.getSaudacao().toString(); jTextField1.setText(aloMundo); }

/** This method is called from within the constructor to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ @SuppressWarnings(“unchecked”) // <editor-fold defaultstate=”collapsed” desc=”Generated Code”> private void initComponents() {

jTextField1 = new javax.swing.JTextField();

setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); getContentPane().add(jTextField1, java.awt.BorderLayout.CENTER);

pack(); }// </editor-fold>

/** * @param args the command line arguments */ public static void main(String args[]) { java.awt.EventQueue.invokeLater(new Runnable() { public void run() { new MostrarJFrame().setVisible(true); } }); }

// Variables declaration - do not modify private javax.swing.JTextField jTextField1; // End of variables declaration

}

Listagem 3.

package org.groovy.maonamassa;

public class AloMundoJava {

String saudacao = new String();

public String getSaudacao() { return saudacao; }

public void setSaudacao(String saudacao) { this.saudacao = saudacao; }}

Figura 5.

para somar uma instância com outra e teve que apelar para métodos mirabo-lantes como somaClasse() ou append()? Em

java 69.indb 11 26/05/2009 16:36:44

Page 12: java 69 [Introdução Spring Security] [Lido]

12 Java Magazine Edição 69

Listagem 4.

package org.groovy.maonamassa

class AloMundoGroovy { // aqui você pode omitir o def def String saudacao = “Alô mundo, em Groovy !!!!”}

Listagem 5. O poder de fogo do GDK

class TestaSize { public def imprime() { String teste = “isso é um teste” ArrayList meuArray = new ArrayList() meuArray.add(teste)

println teste.size() println meuArray.size() }}

Listagem 6. Usando o plus para aumentar o poder do +

package org.groovy.maonamassa

class SomaODobro {

def Integer valorInicial

public def plus(SomaODobro outro) { return (valorInicial + outro.valorInicial) * 2 }

}

class AloMundoGroovy {

public def testa() { SomaODobro valor01 = new SomaODobro() SomaODobro valor02 = new SomaODobro()

valor01.valorInicial = 10 valor02.valorInicial = 20

println valor01 + valor02 }}

Groovy basta definir o método correto e, ao avaliar a operação, o Groovy procura o método correspondente.

Isso só é possível por que o Groovy usa o conceito de MetaClass apresentado acima. Quando o compilador encontra uma expressão como valor01 + valor02 num código Groovy, ele gera um bytecode diferente do que gera quando encontra essa mesma expressão num arquivo de código Java, pois chamadas de métodos são redirecionadas pelo MetaClass do objeto, o que possibilita ao Groovy inter-ceptar, adicionar, redirecionar e remover código em tempo de execução. É esse truque que possibilita valor01 + valor02tornar-se valor01.plus(valor02) em tempo de execução.

Claro que todo esse poder tem um preço:

um código Groovy é ligeiramente mais lento do que um código Java durante a execução, mas nada que torne proibitivo seu uso. Fazendo uma analogia, num comparativo com o desenvolvimento para sistemas operacionais, a JVM seria nosso sistema operacional, e ao desenvolver optaríamos por Java quando precisamos de velocidade, e por Groovy quando pre-cisamos de facilidades e performance não é um dos requisitos principais. Pode parecer, com todo esse parágrafo, que Groovy é um elefante pesado e lento, mas Groovy é apenas um pouco mais lento que Java.

Na Listagem 6 é possível encontrar um exemplo de como sobrescrever o operador + através do uso do método plus(). Criei uma classe chamada SomaO-Dobro que, quando tem duas instâncias

somadas, realiza a adição e depois a multiplicação para retornar o resultado. Veja o código.

É importante ressaltar que sim, é pos-sível, em Groovy, ter mais de uma classe dentro de um arquivo de código fonte como visto acima. As classes podem, inclusive, ser públicas, ao contrário do Java, onde podemos ter apenas uma classe pública por arquivo. Veja nas Lis-tagens 7 e 8 um exemplo simples.

ClosuresUm dos recursos mais úteis e apaixo-

nantes de linguagens dinâmicas são os closures, ou fechamentos, ou blocos, que dão um poder de fogo enorme no desen-volvimento. Closures nada mais são do que pedaços de código tratados como obje-tos, e como tal podem receber parâmetros e retornar valores. E como a JVM não sabe se o código que está rodando é Groovy ou Java, é perfeitamente possível dizer que um closure é apenas mais objeto para a JVM, tal qual uma String ou um Integer.

Uma aplicação robusta e poderosa de closure é na classe File da GDK. O Groo-vy estende o objeto File padrão do Java e adiciona um método eachLine(), que recebe como parâmetro um closure:

new File(“arquivo.txt”).eachLine { println it }

O closure nada mais é do que o bloco {println linha }, que será executado para cada iteração de eachLine(), ou seja, essa única linha abrirá um arquivo de texto chamado arquivo.txt, lerá linha por linha até o final e passará cada linha ao closure, que imprimirá o que recebeu na saída padrão usando o println() (o it representa a linha recebida). Tudo isso em apenas uma linha de código.

Outro exemplo bem interessante é apre-sentado a seguir, onde temos um tipo de dado do Groovy (o Range, que é um intervalo representado com dois núme-ros separados por dois pontos simples, como em 1..100, que inclui os números de 1 a 100); e o método each(), que varre cada membro do Range, e depois executa a closure que o imprime.

(1..10).each { println it }

java 69.indb 12 26/05/2009 16:36:44

Page 13: java 69 [Introdução Spring Security] [Lido]

Edição 69 Java Magazine 13

Ok, mas o que é esse tal de it no meu código? Ele é uma variável conhecida como “Magic variable”, ou “ variável mágica”, algo que não precisa ser decla-rado pra existir. it pode ser visto como um membro da classe que define os closures do Groovy, é ele quem recebe o parâmetro padrão quando esse não é declarado. Veja como fica a opção de uso de uma variável explícita no lugar da variável mágica.

(1..10).each { valorAtual -> println valorAtual }

É o sinal de -> que separa a declaração de variáveis do corpo do closure. Mas closures não são úteis apenas para imprimir um valor na saída padrão, eles podem ser usados para operações complexas, sua imaginação é o limite.

O poder dos closuresVamos criar um exemplo pra demons-

trar um pouco do poder e da elegância do uso de closures. Crie um novo pro-jeto Java e adicione Groovy a ele como visto anteriormente. Adicione uma nova classe Groovy chamada Aluno e então insira o código da Listagem 9.

Nessa classe temos duas proprieda-des, o nome do aluno e o número de sua matrícula. O nome deverá ser informa-do no momento da criação do objeto, através de nosso construtor e o número da matrícula é sugerido através do uso de um membro estático que é incre-mentado a cada nova instancia criada (perceba que esse recurso não deve ser usado em situações reais, mas encaixa como uma luva nesse exemplo).

Redefinimos também o método toString(),para possibilitar uma impressão simpli-ficada de nossos valores, quando neces-sário. Perceba que faço uso dos getters e setters sem os declarar pois, como foi visto antes, eles são criados automaticamente quando definimos membros de classe sem especificar sua visibilidade.

Na Listagem 10 instanciamos, em um arquivo main.java três objetos de nossa classe e imprimimos seus dados, usando o toString().

O resultado será algo como:

Listagem 7. Um arquivo Groovy com duas classes públicas

package groovytest

public class Carro { public def imprime() { println “Sou um carro” }

}

public class Moto { public def imprime() { println “Sou uma moto” }}

Listagem 8. Instanciando as classes Groovy

package groovytest;

public class Main {

public static void main(String[] args) { Carro meuCarro = new Carro(); Moto minhaMoto = new Moto();

meuCarro.imprime(); minhaMoto.imprime(); }

}

Listagem 9. A classe Aluno.groovy

package groovy2

class Aluno { // definimos as propriedades String nomeAluno Integer matriculaAluno

// variavel para a matriculo static int matricula = 0

// Construtor Aluno(String nome) { matricula = matricula + 1 this.setNomeAluno(nome) this.setMatriculaAluno(matricula) }

public String toString() { return “Matricula: “ + this.getMatriculaAluno().toString() + “ Nome: “ + this.getNomeAluno() }}

Listagem 10. A classe Main.java, instanciando três objetos aluno

package groovy2;

public class Main {

public static void main(String[] args) { Aluno aluno01 = new Aluno(“Marcelo”); Aluno aluno02 = new Aluno(“Giuliana”); Aluno aluno03 = new Aluno(“Ana Beatriz”);

System.out.println(aluno01.toString()); System.out.println(aluno02.toString()); System.out.println(aluno03.toString()); }

}

Matricula: 1 Nome: MarceloMatricula: 2 Nome: GiulianaMatricula: 3 Nome: Ana Beatriz

Vamos agora criar, na Listagem 11,uma nova classe Groovy chamada Aula.Vamos utilizá-la para agrupar nossos alunos em aulas.

java 69.indb 13 26/05/2009 16:36:44

Page 14: java 69 [Introdução Spring Security] [Lido]

14 Java Magazine Edição 69

Modifique o arquivo Main.java para que fique como na Listagem 12.

Ao chamarmos o método imprimeListaAlu-nos() faremos uso de um closure para percor-rer todos os membros do ArrayList da classe Aula (através do each()). Agora faça um teste e escreva as classes Aluno e Aula em Java e veja quantas linha a mais de código seriam necessárias para o mesmo resultado.

A maior parte das linguagens e recursos que se propõe a enxugar o código o faz às custas de clareza. Isso não acontece em Groovy: o código continua perfeitamente legível, mesmo com linhas a menos. Em alguns casos, como no exemplo acima, é até mais fácil ler um código Groovy do que um código Java.

Para onde ir agora?Groovy é extremamente poderosa e

pode lhe ajudar muito em seus projetos Java. Ela é particularmente útil para pro-cessamento de texto graças a um podero-so suporte a expressões regulares, para processamento de listas e de arquivos

Listagem 11. A classe Aula.groovy

package groovy2

class Aula { ArrayList alunos = new ArrayList()

def adicionaAluno(Aluno nomeAluno) { alunos.add(nomeAluno) }

def removeAluno(Aluno nomeAluno) { alunos.remove(nomeAluno) }

def imprimeListaAlunos() { alunos.each() { alunoAtual -> println alunoAtual.toString() } }}

Listagem 12. A classe Main.java, modificada

package groovy2;

public class Main {

public static void main(String[] args) { Aluno aluno01 = new Aluno(“Marcelo”); Aluno aluno02 = new Aluno(“Giuliana”); Aluno aluno03 = new Aluno(“Ana Beatriz”);

Aula historia = new Aula(); historia.adicionaAluno(aluno01); historia.adicionaAluno(aluno02); historia.adicionaAluno(aluno03);

historia.imprimeListaAlunos(); }}

graças ao uso de closures e principalmen-te para o processamento de XML, onde o Java é deveras confuso e prolixo.

Além disso Groovy é a base do Grails, framework de produtividade para o desenvolvimento de aplicações web que une a poderosa infra-estrutura do Spring e Hibernate à simplicidade das idéias do Ruby on Rails. Grails possibilita o desen-volvimento de aplicações complexas de maneira rápida e indolor, gerando uma aplicação web totalmente compatível com Java EE em um arquivo .war.

Para aprender mais sobre Groovy dê uma olhada na página do projeto na web. Existem dúzias de exemplos e informação relevante para que você torne-se produtivo rapidamente. Além disso, é interessante dar uma olhada no livro Groovy em ação, escrito por Dierk König junto a Andrew Glover, Paul King, Guillaume Laforge (o mantenedor do projeto) e Jon Skeet, publicado pela edi-tora AltaBooks. (O original, Groovy in action, é publicado pela Manning, caso

http://radio.weblogs.com/0112098/2003/08/29.htmlPost de James Strachan, onde surgiu a idéia sobre o Groovy

http://www.springsource.com/node/836Página da SpringSource comentando a compra da G2One

http://www.netbeans.orgSite do NetBeans, a única IDE que você precisa

http://grails.codehaus.orgSite do Grails, framework para aplicações web que usa o Groovy como base

http://groovy.codehaus.orgSite do Groovy

Marcelo Castellani [email protected]É diretor de novas tecnologias na

mindaslab.com. Desenvolvedor

experiente e fã incondicional de

linguagens dinâmicas, atua há mais de quatorze anos

em projetos de software, seja sistemas embarcados,

web ou desktop. É um dos fundadores do grupo de

usuários de Ruby do estado de São Paulo e ministra

periodicamente treinamentos sobre Groovy, Ruby e

Rails pela Tempo Real Eventos.

Dê seu feedback sobre esta edição!

A Java Magazine tem que ser feita aoseu gosto. Para isso, precisamos sabero que você, leitor, acha da revista!

Dê seu voto sobre este artigo, através do link:

www.devmedia.com.br/javamagazine/feedback

seu Feedback

sob

reeeestaedição

inglês não seja um problema). Groovy é simples e poderoso e merece sua aten-ção. O tempo que irá ganhar quando começar a usá-lo compensará e muito seu aprendizado.

java 69.indb 14 26/05/2009 16:36:46

Page 15: java 69 [Introdução Spring Security] [Lido]

Edição 69 Java Magazine 15

java 69.indb 15 26/05/2009 16:36:49

Page 16: java 69 [Introdução Spring Security] [Lido]

16 Java Magazine Edição 69

SEÇÃO JAVA: NESTA SEÇÃO VOCÊ ENCONTRA ARTIGOS INTERMEDIÁRIOS E AVANÇADOS SOBRE JAVA

De que se trata o artigo:

Após três anos de desenvolvimento, o JBoss Application Server 5 está pronto e traz uma arquitetura

totalmente redesenhada. Este artigo introduzirá a nova arquitetura baseada no JBoss Microcontainer,

suas vantagens e principais diferenças em relação à sua antecessora baseada no JBoss Microkernel.

Além disso, detalhará as principais novidades em mensageria, clustering, balanceamento de carga,

cache, transações e monitoração.

Para que serve:

O JBoss Application Server 5 serve para disponibilizar os recursos necessários à execução de apli-

cações Java EE 5. Sua arquitetura flexível permite total controle, customização e tuning, conforme as

necessidades do desenvolvedor. Além disso, sua instalação é simples e rápida.

Em que situação o tema é útil:

O artigo atualiza o leitor em relação às mudanças mais expressivas da nova versão do JBoss Application

Server, o servidor de aplicações mais utilizado do mundo.

JBoss Application Server 5:

O JBoss Application Server 5 é resultado de três anos de pesquisas e desenvolvimento, que culminou

em um total redesenho da arquitetura interna do servidor de aplicações.

Além da compatibilidade total à especificação Java EE 5 e do suporte ao JDK 6, a principal carac-

terística dessa nova versão é a substituição do JBoss Microkernel pelo JBoss Microcontainer. Com o

JBoss Microcontainer, é possível desenvolver serviços baseados em POJOs, não sendo mais necessário

implementar MBeans. Com isso, a integração de novos módulos torna-se ainda mais dinâmica e rápida,

o que facilita customizar, excluir ou acoplar novos serviços. É possível também integrar componentes

baseados nos antigos MBeans, módulos OSGi, entre outros.

Houve também mudanças significativas no mecanismo de classloader para a utilização do Virtual

Deployment Framework (VDF), o qual garante que toda dependência do deploy seja satisfeita antes

da disponibilização do serviço. Os principais módulos também sofreram evoluções, como: clustering,

mensageria, cache, binding de portas, etc.

A interface gráfica do novo JBossAS também foi atualizada, e foi criado o projeto Jopr – uma

interface web para monitoração e controle de toda a infraestrutura JBoss, o que possibilita, entre

outras coisas: a criação de novos datasources, deploy de pacotes, monitoração de pools de conexão,

mantendo um histórico de ações e gráficos para futuras consultas. Dessa forma, ficou muito mais

fácil cuidar dos seus JBosses.

O lançamento do JBoss AS 5 é apenas o começo de uma nova era para os projetos JBoss, uma vez

que outras soluções, como a Plataforma SOA, Portais, etc., poderão usufruir desse robusto e perfor-

mático servidor de aplicações.

Aversão 5 do JBoss Application Ser-ver, que a partir desse momento chamaremos simplesmente AS5,

foi resultado de uma maratona de três anos de pesquisas e desenvolvimento que culminou em um total redesenho da arqui-tetura interna do servidor de aplicações.

Essa versão marca o início de uma nova era para o servidor de aplicações mais popular, querido e utilizado do mundo. Não se trata apenas de uma nova versão do servidor de aplicações, mas de todo um ambiente em estado da arte para execução da próxima geração de projetos desenvol-vidos pela JBoss.

Sobre a JBossJBoss, apesar de ser sinônimo de servi-

dor de aplicações, não está restrito apenas a isso. A comunidade JBoss (www.jboss.org) possui hoje mais de 35 projetos. Entre eles, podemos destacar:

Hibernate – o framework de persistência ORM (Object Relational Mapping) mais utilizado do mundo e que muito influen-ciou a especificação de EJB 3.0.

JBoss Seam – o framework que combina o que há de melhor em desenvolvimento Web 2.0 com o novo modelo de compo-nentes de negócio EJB 3.0, aumentando a produtividade e disponibilizando inúme-ros componentes para facilitar e acelerar o desenvolvimento de aplicações corporati-vas em Java. O reconhecimento do poder do JBoss Seam por parte da comunidade deu origem à JSR 299 – Web Beans. Ver Edição 58.

Além de influenciar o futuro da plataforma Java EE, seja com participações nas JSR’s, seja com a implementação de referência de JSR’s, a JBoss conta hoje com a participação de brasileiros, funcionários da Red Hat Brasil, como principais desenvolvedores em diversos projetos da comunidade JBoss,

java 69.indb 16 26/05/2009 16:36:49

Page 17: java 69 [Introdução Spring Security] [Lido]

BRUNO ROSSETTO MACHADO E JOÃO PAULO VIRAGINE

Edição 69 Java Magazine 17

dedicando-se em tempo integral a atividades de desenvolvimento e suporte a clientes. Dentre esses projetos, podemos destacar: o próprio JBoss AS, o JBoss Rules – motor de regras e BRMS (business rule management system), JBoss AOP – framework para AOP (programação orientada a aspectos), JBossSX (framework de segurança da JBoss), JBoss Profiler (ferramenta de profiling baseada em log), JBoss Messaging (JMS provider), JBoss ESB (para integração SOA, ver Edição 59) e JBoss Portal (solução para portais corporativos).

Mais detalhes sobre esses e outros projetos JBoss (como o JBoss jBPM, JBoss Tools, Teiid) podem ser encontrados no site: www.jboss.org.

Apesar de os projetos JBoss serem conduzidos, em sua maior parte, por fun-cionários da Red Hat/JBoss, é inegável a contribuição da comunidade durante todos esses anos de existência da jboss.org. Essa contribuição é de extrema im-portância para a sobrevivência e qualidade dos projetos.

A contribuição não é feita apenas com desenvolvimento de código fonte, mas também com participação em fóruns de discussão, relato de bugs, pedido de novas funcionalidades, elaboração/tradução de documentação, blogs pessoais, eventos organizados pela comunidade, etc.

Veja os links de referência para saber mais

informaçõ es so bre como co ntr ibuir com a

comunidade JBoss

NovidadesUma das novidades da versão 5 do JBoss

AS é a compatibilidade total à especifi-cação Java EE 5. Apesar de a versão 4.x já suportar grande parte da especificação Java EE 5 (EJB 3.0, JPA, JAX-WS, etc.) e ser um dos primeiros servidores de aplicações

a suportar a especificação de EJB 3.0, o suporte à Java EE 5 não era completo nem certificado. A certificação era uma carac-terística bastante requisitada por clientes corporativos da Red Hat, principalmente em relação à garantia de compatibilidade das aplicações desenvolvidas.

O suporte ao JDK 6 é também uma novidade dessa versão. Apesar de su-portar o Java 6 desde a versão 4.2, é na versão 5 que esse suporte foi aprimorado e tornou-se padrão para execução do servidor de aplicações.

Além da certificação Java EE 5 e do supor-te ao Java 6, o destaque dessa versão, sem dúvida nenhuma, fica a cargo do JBoss Microcontainer. O AS5 faz parte de uma nova geração do servidor de aplicações, construído com base no novo JBoss Mi-crocontainer.

O JBoss Microcontainer é resultado de uma completa reescrita do JBoss JMX

Microkernel (utilizado nas versões das séries 3.x e 4.x do JBoss AS) e o substitui completamente para suportar a utiliza-ção direta de POJOs e o uso como um projeto independente do servidor de aplicações JBoss, seguindo a tendência e evolução do desenvolvimento Java EE com a utilização de novos paradigmas como AOP, injeção de dependência e inversão de controle, e o foco na utiliza-ção de POJOs (como EJB 3.0, JPA, Spring, Guice, entre outros).

O servidor de aplicação JBoss 3/4 era basicamente uma série de MBeans agru-pados, controlados e disponibilizados pelo Microkernel, o qual já possibilitava grande flexibilidade para retirar e adicio-nar novos MBeans.

Já com o JBoss Microcontainer é possível desenvolver serviços do servidor de apli-cações baseados em POJOs. Não é mais necessário desenvolver MBeans.

java 69.indb 17 26/05/2009 16:36:49

Page 18: java 69 [Introdução Spring Security] [Lido]

18 Java Magazine Edição 69

O AS5 utiliza o JBoss Microcontainer para fazer a integração dos serviços dis-ponibilizados pelo servidor de aplicações, entre eles: container Servlet/JSP; container EJB; gerenciador de deploy, entre outros, disponibilizando, assim, um ambiente Java EE padrão. O JBoss AS não é um servidor de aplicações monolítico – com um único kernel fornecendo os serviços requeridos pela especificação Java EE – mas sim, uma coleção de componentes independentes e interconectados, cada um deles com foco em uma funcionalidade específica requerida pela especificação Java EE. Essa arquitetura flexível possibilita que novos serviços possam ser facilmente adiciona-dos e os serviços desnecessários possam ser removidos. Se houver necessidade de um serviço adicional, simplesmente fazemos o deploy do serviço desejado. De maneira análoga, se não precisamos de um serviço, podemos simplesmente removê-lo. A Figura 1 mostra uma visão geral de como os serviços são associados e disponibilizados pelo Microcontainer.

Como resultado, temos um servidor de aplicações totalmente customizado às nossas necessidades, com o uso eficaz de recursos do servidor físico (CPU, memória, disco).

A f lexibilidade é tamanha, que os serviços construídos com base no JBoss Microcontainer podem ser utilizados de maneira independente em outros ambien-tes/servidores de aplicações não JBoss, como o GlassFish, ou até mesmo o Tomcat. Como exemplo, podemos citar o suporte total ao EJB 3.0 no Tomcat (bastando para isso, fazermos o deploy do JBoss EJB 3.0 container no Tomcat).

Como o JBoss Microcontainer é extre-mamente leve, pode ser utilizado para disponibilizar serviços até mesmo em um ambiente Java ME. Desse modo, abre-se um novo horizonte de possibilidades para aplicações móveis que passam a usufruir dos serviços “enterprise”, sem a necessida-de de utilização de um ambiente/servidor Java EE completo.

O JBoss Microcontainer utiliza o conceito de injeção de dependências (IoD) para in-terconectar e disponibilizar os serviços do servidor de aplicações. Além disso, pode ser utilizado como container de injeção de

Figura 1. Uma visão geral da arquitetura de serviços que são disponibilizados pelo Microcontainer

dependências de propósito geral ao estilo Pico Container e Spring.

Como amplamente consolidada no Java 5, toda configuração do JBoss Microcontainer pode ser realizada através de anotações ou XML, dependendo do local onde a informa-ção de configuração está localizada (classes Java ou arquivos de configuração).

Além de tudo isso, o JBoss Microcontai-ner possui classes de testes utilitárias que estendem o JUnit e tornam a configuração e a execução de testes unitários uma tarefa extremamente simples, permitindo que o desenvolvedor acesse POJOs e serviços nas classes de testes com apenas algumas linhas de código.

Todo o mecanismo de classloader do JBoss AS também foi modificado para utilizar o avançado conceito do Virtual Deployment Framework (VDF). O VDF foi desenvolvido para abstrair, simplificar e unificar a manipulação de arquivos pelo servidor de aplicações.

Denominado Virtual File System (VFS)Class Loader, esse novo mecanismo de classloader, além do uso do VDF para localizar bibliotecas e classes, faz uso extensivo de AOP para “aspectizar” o deploy de aplicações/serviços no servidor de aplicações.

O VFS faz a análise dos deploys produ-zindo meta-informações que serão utili-zadas pelo JBoss Microcontainer para ins-tanciar, interconectar e controlar o ciclo de vida e dependência dos deploys. O JBoss Microcontainer utiliza uma máquina de estados para garantir que toda e qualquer dependência do deploy seja satisfeita antes de disponibilizar o serviço.

Modularização dos serviços – Maior possibilidade

de escolha e flexibilidade

Um grande avanço do AS5 foi a modulari-zação dos serviços internos do servidor de aplicações em projetos independentes.

Essa modularização não traz impactos

diretos para o usuário final, mas faz parte de uma importante estratégia da JBoss em disponibilizar os vários serviços Java EE como projetos independentes. Assim, esses serviços podem ser consumidos ala carte em diferentes ambientes, e não apenas no próprio servidor de aplicações, o que permite grande flexibilidade e liber-dade de escolha. Remover serviços é tão simples quanto adicionar novos.

Muitas das principais funcionalidades do AS5 são providas da integração de vários outros projetos JBoss, entre eles:

JBoss EJB 3.0 – Implementação da úl-tima versão da especificação EJB 3.0 – A especificação de EJB 3.0 faz parte de uma total reestruturação da especificação EJB. E tem por objetivo a simplificação do desenvolvimento;

JBoss Messaging – Reescrita completa do antigo JBossMQ (que é o provedor JMS padrão no JBoss AS das séries 4.x). É uma implementação de JMS de alta per-formance compatível com a JSR-914, com suporte out-of-the-box a cluster de filas e tópicos, com tolerância a falhas transpa-rente e um sistema de redistribuição de mensagens inteligente. É hoje o provedor de mensageria padrão do AS5, além de ser parte integrante da infraestrutura do JBoss ESB;

JBoss Cache – É a implementação de cache utilizada no AS5. É utilizado principalmen-te em conjunto com o JGroups para fornecer uma solução completa de cluster. Entre as diversas características está o buddy repli-cation: permite que o cache seja replicado apenas para um “buddy” (companheiro) no cluster, evita a sobrecarga de outros nós no cluster sem necessidade, realiza uma espécie de backup do estado do nó;

JBoss WS – Implementação da pilha de web services compatível com a especifica-ção JAX-WS 2.0/JAX-RPC. Além de implementar toda a especificação de Web Services, foi criada uma camada de

java 69.indb 18 26/05/2009 16:36:50

Page 19: java 69 [Introdução Spring Security] [Lido]

Edição 69 Java Magazine 19

abstração que possibilita que se pluguem outras implementações. Por exemplo: podemos utilizar a implementação nativa do JBoss WS, o Metro (implementação de web services da Sun), ou ainda o CXF (implementação da Apache), sem qualquer tipo de impacto sobre o JBoss AS. Assim, o usuário tem total liberdade para escolher a implementação que melhor se adapta às suas necessidades.No final do mês de março, foi anunciado que os esforços serão focados em uma úni-ca implementação: JBossWS-CXF, ou seja, as próximas versões do JBoss AS virão com o CXF nativo. Aqueles que usam o JBoss WS nativo não precisam se preocupar, pois a transição será realizada gradativamente e trará grandes benefícios, principalmente no que diz respeito a soluções SOA;

JBoss Transactions – é o gerenciador de transações padrão no AS5. O JBoss Tran-sactions foi adquirido em 2005 da Arjuna/Hewlett-Packard – um gerenciador de transações extremamente rápido e robusto. Resultado de mais de 18 anos de experiên-cia dos seus criadores em gerenciamento de transações, foi a primeira implementa-ção de JTA e JTS do mercado;

JBoss Web – É o container Web/Servlet do AS5, comumente conhecido como “Tomcat on stereoids”. Tem sua implementação base-ada no Apache Tomcat 6.0 e inclui suporte a conectores baseados no Apache Porta-ble Runtime (APR) para alcançar maior performance e escalabilidade, podendo, em alguns casos, equiparar-se ao Apache HTTP Server ou até superá-lo;

JBoss Security – Além do suporte a JAAS, foi atualizado para suportar meca-nismos de autorização plugáveis: SAML, XACML e SSO.

A Tabela 1 compara os principais ser-viços utilizados no AS5 e no seu sucessor (JBossAS 4.2.3), para facilitar a visualiza-ção da evolução de versões entre os dois.

O AS5 suporta nativamente POJOs, MBeans e OSGi bundles (com ajuda do Apache Felix). Suportar um novo modelo de componentes é tão simples quanto implementar uma nova fachada para o JBoss Microcontainer. Isso permite que o JBoss AS suporte qualquer outro modelo

JBoss AS 4.2.3.GA JBoss AS 5.0.1.GA

1.5.6.GA 2.0.1.GA

4.2.3.SP7 4.4.0.GA

2.0.1.GA v2.1.2.GA

3.0.1-native-2.0.4.GA 3.0.5.GA

JBoss MQ com suporte a JMS 1.1 JBoss Messaging 1.4.1.GA

2.4.1.SP4 2.6.7.GA

1.4.1.SP7 3.0.2.GA

Tabela 1. Matriz de comparação de versão entre o JBossAS 4.2.3 e o JBossAS 5

de componentes existente ou que ainda está por vir; já está preparado, portanto, para o sistema de módulos que será im-plementado no Java 7.

Novidades em Cluster Uma das melhorias no AS5 foi a criação

de um novo mecanismo de integração en-tre o JBoss Cache e o Hibernate/JPA para a utilização de Second Cache Level (ou cache L2, introduzido no Hibernate 3.3). Existem basicamente quatro tipos de objetos que po-dem participar de um Second Cache Level: entidades, collections, resultados de query e timestamps. Nas versões 4.x, apenas um único cache podia ser utilizado para arma-zenar todos os tipos de objetos, causando dificuldades na consulta. Com o AS5 existe um cache diferenciado para cada tipo de objeto, evitando assim sobrecarga e lentidão na busca de objetos na árvore de cache.

Essa versão também permite buddy re-plication de Stateful Session Beans. Com buddy replication, é possível diminuir a carga de memória e o tráfego na rede. A Figura 2 mostra uma arquitetura com seis nós, onde cada nó possui os seus dados e um cache do nó anterior. Quando ocorre queda de um dos nós, automaticamente o nó que possuía o cache do nó em queda

assume o comando, guardando também o cache do nó anterior, fechando o círculo. A Figura 3 mostra a queda do servidor nó 1 e o servidor nó 2 assumindo o cache do nó 1 (em queda) e 6.

Nas versões 4.2.x, buddy replication era configurada no arquivo $JBOSS_HOME/server/all/deploy/jboss-web-cluster.sar/META-INF/jboss-service.xml (apenas camada web). Já o AS5 centraliza toda a configuração de cache no serviço chamado Cache Manager, que está localizado em $JBOSS_HOME/server/all/deploy/cluster/jboss-cache-manager.sar.

Com a utilização do JBoss Messaging em vez do JBossMQ, a clusterização do provider de mensageria também mudou. O antigo JBossMQ era executado em modo HA-Singleton, ou seja, apenas uma instância de JBoss executava o provider de mensageria por vez. Com o JBoss Mes-saging, é possível ter todos os nós ativos para o serviço de mensageria, proporcio-nando um balanceamento de carga entre os diversos nós, caso ocorra uma sobre-carga no servidor. Para que as filas sejam consideradas “clusterizadas”, é necessário adicionar o atributo Clustered com valor True na declaração da Queue ou Topic, conforme mostra a Listagem 1.

Figura 2. Arquitetura com buddy replicationFigura 2 Arquitetura com buddy replication Figura 3. Arquitetura com buddy replication e queda do nó 1Figura 3 Arquitetura com buddy replication e queda do nó 1

java 69.indb 19 26/05/2009 16:36:50

Page 20: java 69 [Introdução Spring Security] [Lido]

20 Java Magazine Edição 69

A configuração do serviço de portas também mudou. Com a utilização de POJOs e AOP no Microcontainer, as portas agora são injetadas conforme a necessidade da configuração.

O serviço ServiceBindingManager é o responsável por fazer a associação entre as portas e cada um dos serviços, por exemplo, HTTP na porta 8080, AJP na porta 8009, etc. Na versão 5.0, ocorre uma chamada ao arquivo bootstrap.xml(Listagem 2), que é o responsável por carregar algumas configurações em

Listagem 1. $JBOSS_HOME/server/all/deploy/cluster/jboss-cache-manager.sar

<mbean code=”org.jboss.jms.server.destination.QueueService” name=”jboss.messaging.destination:service=Queue,name=testDistributedQueue” xmbean-dd=”xmdesc/Queue-xmbean.xml”> <depends optional-attribute-name=”ServerPeer”>jboss. messaging:service=ServerPeer</depends> <depends>jboss.messaging:service=PostOffice</depends> <attribute name=”Clustered”>true</attribute> </mbean>

Listagem 2. $JBOSS_HOME/server/$PROFILE/conf/bootstrap.xml

<bootstrap xmlns=”urn:jboss:bootstrap:1.0”> <url>bootstrap/vfs.xml</url> <url>bootstrap/classloader.xml</url> <url>bootstrap/aop.xml</url> <url>bootstrap/jmx.xml</url> <url>bootstrap/deployers.xml</url> <url>bootstrap/bindings.xml</url> <url>bootstrap/profile-repository.xml</url></bootstrap>

Listagem 3. Trecho do arquivo bindings.xml – definição de alias

<bean name=”ServiceBindingStore” class=”org.jboss.services.binding.impl.Pojo ServiceBindingStore”>

<!-- Base bindings that are used to create bindings for each set --> <property name=”standardBindings”><inject bean=”StandardBindings”/></property>

<!-- The sets of bindings --> <property name=”serviceBindingSets”> <set> <inject bean=”PortsDefaultBindings”/> <inject bean=”Ports01Bindings”/> <inject bean=”Ports02Bindings”/> <inject bean=”Ports03Bindings”/> </set> </property></bean>

Listagem 4. Trecho do arquivo bindings.xml – definição de PortsDefaultBindings

<bean name=”PortsDefaultBindings” class=”org.jboss.services.binding.impl. ServiceBindingSet”> <constructor> <!-- The name of the set --> <parameter>ports-default</parameter> <!-- Default host name --> <parameter>${jboss.bind.address}</parameter> <!-- The port offset --> <parameter>0</parameter> <!-- Set of bindings to which the “offset by X” approach can’t be applied --> <parameter><null/></parameter> </constructor></bean>

tempo de inicialização. O bootstrap.xmlestá configurado para utilizar o arquivo de configuração de portas bindings.xml,o qual já possui algumas configurações pré-definidas que podem ser utilizadas e customizadas conforme a necessidade do usuário. A Listagem 3 mostra a injeção das configurações de portas disponí-veis. No caso, estão sendo injetadas as configurações de PortsDefaultBindin-gs, Ports01Bindings, Ports02Bindings e Ports03Bindings. A definição das configurações PortsDefaultBindings e

Ports01Bindings é realizada com a inje-ção de beans do tipo ServiceBindingSet (Listagens 4 e 5). O trecho referente a port offset atua diretamente na configuração de StandardBindings (Listagem 6), rea-lizando uma somatória no valor de cada porta. No caso, o PortsDefaultBindings irá manter as configurações conforme estão no arquivo, pois seu port offsetestá definido com valor 0, porém a con-figuração Ports01Bindings irá somar 100 em cada uma das portas. Portanto, para o Ports01Bindings, a porta 1099 será 1199, a porta 1098 será1198, a porta 8080 será 8180, e assim por diante.

$JBOSS_HOME é o diretório de instalação

do JBoss AS5.

$PROFILE é o diretório referente ao profile/

configuração, por exemplo : default, all,

web, etc.

As portas padrão do JBoss Application Server são definidas no bean Standard-Bindings, o qual realiza a associação de cada porta a cada serviço específico. A Listagem 6 mostra um trecho da declara-ção do StandardBindings, em que o ser-viço Naming (JNDI) está sendo associado à porta 1099 e à porta RMI 1098.

Com a utilização do ServiceBindingMa-nager, torna-se mais fácil a utilização de várias instâncias de JBoss AS no mesmo servidor físico. Desse modo, a configu-ração de portas é mantida em um único lugar, o que facilita a manutenção.

Injeção de POJOs utilizando o Microcontainer

Os arquivos que terminam com jboss-beans.xml são utilizados pelo Microcon-tainer para realizar a injeção de POJOs. São semelhantes aos -service.xml que eram utilizados nas versões 4.x. A maio-ria dos serviços do AS5 já foi convertida para POJOs. Porém, ainda restam alguns MBeans das versões antigas que utilizam os -service.xml, os quais serão substituí-dos em versões futuras.

Para facilitar o entendimento da injeção de POJOs realizada pelo Microcontai-ner, criamos a classe PojoServiceExample

java 69.indb 20 26/05/2009 16:36:50

Page 21: java 69 [Introdução Spring Security] [Lido]

Edição 69 Java Magazine 21

Listagem 5. Trecho do arquivo bindings.xml – definição de Ports01Bindings

<bean name=”Ports01Bindings” class=”org.jboss.services.binding.impl.Service BindingSet”> <constructor> <!-- The name of the set --> <parameter>ports-01</parameter> <!-- Default host name --> <parameter>${jboss.bind.address}</parameter> <!-- The port offset --> <parameter>100</parameter> <!-- Set of bindings to which the “offset by X” approach can’t be applied --> <parameter><null/></parameter> </constructor></bean>

Listagem 6. Trecho do arquivo bindings.xml – definição de StandardBindings – portas padrão

<bean name=”StandardBindings” class=”java.util.HashSet” elementClass=”org.jboss.services.binding.ServiceBindingMetadata”> <constructor> <parameter> <set> <!-- ********************* conf/jboss-service.xml ****************** --> <!-- Naming Service --> <bean class=”org.jboss.services.binding.ServiceBindingMetadata”> <property name=”serviceName”>jboss:service=Naming</property> <property name=”bindingName”>Port</property> <property name=”port”>1099</property> </bean>

<bean class=”org.jboss.services.binding.ServiceBindingMetadata”> <property name=”serviceName”>jboss:service=Naming</property> <property name=”bindingName”>RmiPort</property> <property name=”port”>1098</property> </bean> . . . </set> </parameter> </constructor> </bean>

Listagem 7. Classe PojoServiceExample

package jm.exemplos.pojo;

public class PojoServiceExample {

public PojoServiceExample() { System.out.println(“Construtor de PojoServiceExample()”); }}

Listagem 8. Arquivo jboss-beans.xml

<?xml version=”1.0” encoding=”UTF-8”?><deployment xmlns=”urn:jboss:bean-deployer:2.0”> <bean name=”PojoServiceExample” class=”jm.exemplos.pojo.PojoServiceExample”/></deployment>

Listagem 9. $JBOSS_HOME/server/$PROFILE/log/server.log

2009-03-04 17:10:16,060 DEBUG [org.jboss.deployers.structure.spi.helpers.AbstractDeploymentContext] (main) Added component PojoServiceExample to vfszip:/opt/downloads/jboss-5.0.1.GA/server/default/deploy/jboss5-servico-exemplo. beans 2009-03-04 17:10:16,063 INFO [STDOUT] (main) Construtor de PojoServiceExample()

(Listagem 7). É uma classe muito sim-ples, com apenas um método construtor que imprime uma mensagem na tela. A Listagem 8 mostra o arquivo jboss-beans.xml, o qual possui a declaração do POJO com o nome PojoServiceExample. Ao realizar o deploy, deverá ser exi-bida a mensagem conforme mostra a Listagem 9.

Esse exemplo mostra a forma mais sim-ples de disponibilizar um POJO utilizan-do o Microcontainer. Basicamente todos os serviços, módulos e suas dependên-cias são injetados como POJOs e mani-pulados dessa forma, sem a necessidade de ter de implementar uma interface ou estender uma classe abstrata.

Instalação Para a instalação, utilizaremos a versão

binária da distribuição do JBoss AS. Para fazer o download do AS5, basta acessar a página de download (ver Links) e selecionar o arquivo jboss-5.0.1.GA.zip.O site JBoss.org disponibiliza também versões anteriores e um Release Notes de cada uma das versões.

Recomendamos a utilização da versão GA (General Availability), que é a versão estável da distribuição.

O único pré-requisito para execução do JBoss AS é uma máquina virtual Java (JRE) 1.5 ou superior instalada. Na versão 5, não há mais a necessidade de instalação do JDK, pois o AS5 já vem com o ECJ (compilador do Eclipse JDT), necessário para compilar JSPs.

O AS5 pode ser instalado e executado utilizando uma máquina virtual Java 5 ou 6 em qualquer Sistema Operacional. Os binários compilados com as duas JDKs estão disponíveis no site www.jboss.org. Apesar de o número de downloads do binário compilado com Java 6 ser superior e ser considerado uma versão experimental, a versão com Java 5 é a chamada versão primária e é recomenda-da para utilização em produção.

Caso queira rodar o AS5 compilado com JDK 5 utilizando JRE 6, quatro bibliotecas devem ser copiadas do diretório /client para o diretório /lib/endorsed. São elas:

jbossws-native-saaj.jar;jbossws-native-jaxrpc.jar;jbossws-native-jaxws.jar;jbossws-native-jaxws-ext.jar.

Porém, utilizando o binário compilado com JDK 6 em uma JRE 6, nenhuma alteração é necessária.O que muda em geral é o script de inicialização de cada ambiente. Por exemplo:

java 69.indb 21 26/05/2009 16:36:50

Page 22: java 69 [Introdução Spring Security] [Lido]

22 Java Magazine Edição 69

no Windows utilizamos run.bat, no Unix/Linux, run.sh (para simplificar, omitiremos a extensão a partir deste ponto). O processo de instalação básica do JBoss AS é extrema-mente simples: basta descompactá-lo em algum diretório de sua escolha.

Todo o JBoss AS e sua configuração es-tão contidos em uma única estrutura de diretório. Então para desinstalar o JBoss AS basta removermos todo o diretório.

Inicializando o servidor

Após a descompactação do arquivo, iremos iniciar o Application Server. Os scripts de inicialização estão localiza-dos no diretório /bin; execute o script run. Caso esteja utilizando o Windows, execute o arquivo run.bat. O prompt de comando deverá exibir algo semelhante à Figura 4. Com isso, seu AS5 está pronto para ser utilizado.

Os arquivos de inicialização utiliza-rão por padrão o profile default. Veja o quadro “Explorando a nova estrutura de diretórios” para entender melhor os profiles existentes no AS5. Com o parâ-metro -c, é possível inicializar diferentes profiles:

# ./run -c all

Por questões de segurança, o JBoss AS, quando executado, atende às requisições apenas na interface local (127.0.0.1). Esse comportamento faz com que o servidor não seja acessível remotamente. Para habilitar o acesso remoto ao servidor de aplicações, basta utilizarmos a opção -b <interface> no script de inicialização do servidor. O comando abaixo fará o JBoss AS executar os serviços em todas as interfaces de rede do servidor onde está sendo executado.

# run.sh -b 0.0.0.0

De qualquer maneira, esteja ciente da necessidade da correta configuração de segurança do servidor conforme a polí-tica de segurança local.

JBoss AS de cara nova O design do JMX Console e Web Con-

sole também foi atualizado para facilitar a busca de serviços. Agora, há um menu

Figura 4. Prompt de inicialização do AS5

lateral esquerdo com filtro para facilitar a identificação dos serviços. Ao clicar no link, apenas os serviços relacionados serão exibidos (Figura 5). O Web Console também foi modificado, incorporando o design do JMX Console (Figura 6).

MitosAcabando com o mito: O JBoss AS não

tem um console unificado de administra-

Figura 5.

ção, monitoração e controle, tudo tem de ser feito “à mão”.

Não basta ser um servidor moderno, robusto e performático se a adminis-tração não for algo simples e intuitivo. Pensando nisso, foi criado o projeto Jopr (Figura 7). O nome Jopr (pronuncia-se jopper) foi escolhido baseado no filme Jogos de Guerra (WarGames), em que havia um super computador chamado

java 69.indb 22 26/05/2009 16:36:51

Page 23: java 69 [Introdução Spring Security] [Lido]

Edição 69 Java Magazine 23

WOPR (Whopper) – War Operat ion Plan Response – o qual era responsável por responder a todo e qualquer ataque nuclear inimigo.

O propósito desse projeto é disponi-bilizar ao administrador uma interface Web integrada e intuitiva para a admi-nistração, monitoração, configuração e controle da Plataforma JBoss.

Através do Jopr é possível, entre várias outras coisas:

Saber o consumo de CPU, memória, disco e rede do servidor;

Saber o consumo de memória da JVM utilizada pelo servidor de aplicações;

Visualizar e monitorar métricas do servidor de aplicações e das aplicações. (Ex: saber quantas sessões estão abertas em uma determinada aplicação);

Realizar start/stop/restart do servidor de aplicações;

Monitorar métricas e criar/deletar/configurar datasources, connection fac-tories, JMS topics;

Gerar alertas através de e-mail e/ou traps SNMP quando da ocorrência de uma condição pré-configurada (Ex: utili-zação de CPU ultrapassar 80%; memória da JVM ultrapassar 90%).

Além do Jopr Server – com foco em várias instâncias de JBoss AS, existe também uma versão com foco em apenas uma instância de JBoss AS chamado Em-bedded Jopr, o qual é disponibilizado no próprio servidor. Com o Embedded Jopr (Figura 8), é possível realizar deploys de EARs e WARs, criar novos Datasources,

Figura 6.

Figura 7. Jopr

criar novas filas JMS, monitorar o pool de conexões, executar scripts, etc. Tudo isso utilizando uma interface Web intuitiva.

ConclusãoApós três anos de pesquisas e desenvol-

vimento, o JBoss Application Server 5 está pronto para sua grande estréia.

Com um novo kernel construído a

partir do zero, substitui a utilização de MBeans por POJOs, utiliza exten-samente AOP, unifica a manipulação de metadados, altera o mecanismo de classloading, “aspectiza” os deployers, tudo isso mantendo a compatibilidade com a maioria dos serviços existentes. Essas são algumas das novidades dessa nova versão.

Figura 8. Embedded Jopr

java 69.indb 23 26/05/2009 16:36:52

Page 24: java 69 [Introdução Spring Security] [Lido]

24 Java Magazine Edição 69

A estrutura de diretórios do AS5 é muito se-

melhante à dos seus antecessores ( ).

Iremos detalhar as principais diferenças entre a

estrutura de diretórios de uma versão da série 4.x

para a versão 5.

Ao instalar o AS5, percebe-se o novo diretório

common na raiz da instalação. Nas versões ante-

riores, o diretório lib de cada profile (configura-

ção) possuía praticamente as mesmas bibliotecas.

Em um ambiente com diversos profiles sendo

executados em paralelo, o tamanho em disco

do JBoss AS aumenta consideravelmente. No

AS5 as bibliotecas que são obrigatórias para o

funcionamento de todos os profiles foram mo-

vidas para o diretório $JBOSS_HOME/common/

lib. Esse diretório funciona como uma extensão

do diretório $JBOSS_HOME/server/$PROFILE/lib,

deixando-o mais limpo e de fácil manutenção,

especialmente para gerenciar seus drivers jdbc

ou bibliotecas específicas das aplicações.

Os outros diretórios da raiz da instalação per-

manecem com as mesmas funções:

bin – possui todos os scripts e arquivos binários

necessários para iniciar e parar o AS;

– contém bibliotecas necessárias à

comunicação de uma aplicação cliente com o

JBoss AS. Essas bibliotecas não são carregadas

pelo JBoss AS diretamente, mas por aplicações

clientes rodando em JVMs diferentes;

– diretório com exemplos de configura-

ção de Datasources, DTDs e XML schemas, licenças

de bibliotecas e resultados de testes unitários. Para

documentação completa do JBoss AS, acesse o site

da comunidade JBoss www.jboss.org;

– possui as bibliotecas necessárias para exe-

cutar o “core” do AS;

– é um dos diretórios mais importantes e

contém os profiles e as configurações para a exe-

cução de aplicações Java EE.

Além dos profiles clássicos das versões anteriores

(minimum, default, all), dois novos profiles foram

adicionados ao diretório server: web e standard. O

profile web foi criado com o objetivo de executar

apenas aplicações web, ou seja, JSPs e Servlets (sem

a utilização de EJBs). Além disso, também estão dis-

poníveis JTA, JCA e JPA; porém a maioria dos outros

serviços não está disponível, como os serviços de

e-mail, mensageria, Quartz, gerador de chaves, etc.

Esses serviços só estão disponíveis a partir do profiler

default. O profile standard foi criado para a execução

dos testes de compatibilidade com Java EE 5. O profile

default é um “superset” do standard e possui algumas

poucas configurações e aplicações adicionais.

Muitos usuários se perguntam qual profile devem

utilizar para executar suas aplicações. A

mostra as principais diferenças entre os cinco

profiles.

Os profiles mais utilizados nas versões anteriores

eram o default e o all. No AS5, além destes, o pro-

minimal web standard default all

x x x

ejb2 x x x

ejb3 x x x

x x x x

x x x x

x x x x

x x x

x x x

x x x

x x x

x x x

x x x

x

Tabela Q1. Serviços disponíveis em cada profile.

file web deverá ser utilizado em grande escala,

substituindo a utilização do Tomcat e jboss-web

stand-alone. Se a aplicação necessita de alta-dispo-

nibilidade (HA), utiliza-se o profile all. A maioria dos

outros casos será atendida com o profile default.

Cada profile possui um diretório conf. Assim

como nas versões anteriores do JBoss AS, possui

as configurações gerais do servidor de aplicação,

como controle transacional, log4j, diretórios de

deploy, etc.

O diretório deploy é o local utilizado para

publicar aplicações e disponibilizar serviços no

JBoss AS.

No AS5, houve a separação dos serviços “de-

ployáveis” com a criação do diretório deployers

( ). Assim, não ficam mais misturados no

diretório deploy, sendo armazenados no diretório

deployers(a exemplo do jbossweb.deployer).

O diretório lib contém bibliotecas que serão

compartilhadas por todos os serviços e aplicações

disponíveis para o profile. Caso queira compar-

tilhar um driver JDBC entre várias aplicações no

mesmo profile, adicione a biblioteca do drive no

diretório lib.

Para o profile all, foi criado o diretório cluster, o

qual armazena uma total reestruturação dos arqui-

vos de configuração de cluster. O arquivo cluster-

service.xml não existe mais, e seu equivalente é o

$PROFILE/deploy/cluster/jgroups-channelfactory.

sar/META-INF/jgroups-channelfactory-stacks.xml.

java 69.indb 24 26/05/2009 16:36:52

Page 25: java 69 [Introdução Spring Security] [Lido]

Edição 69 Java Magazine 25

Figura Q1. Estrutura de diretórios da raiz do AS5

Figura Q2.

Bruno Rossetto Machado [email protected]É bacharel em Sistemas de

Informação pela Universidade

Presbiteriana Mackenzie e atua com

desenvolvimento de software com a

plataforma Java desde 2003. Possui experiência em

projetos Java EE nas áreas automotivas, e-commerce,

financeira, telecom, e outros projetos de missão crítica.

Participou do projeto ganhador do Duke Choice’s Awards

de 2005 - SIGA Saúde. Atualmente é Consultor da JBoss,

a division of Red Hat no Brasil com foco em customiza-

ção, performance e tuning do JBoss Application Server e

desenvolvimento de portais com JBoss Portal.

João Paulo Viragine [email protected]É bacharel em Ciência da

Computação pela Unesp. Trabalha

como Arquiteto de Soluções na JBoss, a

division of Red Hat, onde uma de suas

atribuições é ser o evangelista oficial de Seam no Brasil.

Acumula cerca de 7 anos de experiência na tecnologia

Java, tendo atuado em projetos da área de Governo e

Finanças. Possui as certificações: SCJP e SCWCD.

www.jboss.orgPágina principal da JBoss

http://www.jboss.org/community/docs/DOC-9938Como contribuir com a comunidade JBoss

http://java.sun.com/javaee/overview/compatibility.jspListagem de Servidores de Aplicação compatíveis com Java EE 5.0

http://jcp.org/en/jsr/detail?id=244Página da especificação Java EE 5.0

http://www.jboss.com/products/platforms/application/standardsPágina de padrões suportados pelo JBoss AS

http://www.jboss.org/jbossas/downloads/Página de download do JBoss AS

http://www.jboss.org/jopr/Página principal do Jopr

http://felix.apache.orgPágina principal do Apache Felix

http://magazine.redhat.com/2008/10/31/interview-chris-morgan-on-jopr/Entrevista com Chris Morgan sobre Jopr

Dê seu feedback sobre esta edição!

A Java Magazine tem que ser feita aoseu gosto. Para isso, precisamos sabero que você, leitor, acha da revista!

Dê seu voto sobre este artigo, através do link:

www.devmedia.com.br/javamagazine/feedback

seu Feedback

sob

reeeestaedição

Nova versão do livro JBoss in Action a qual

foca nas principais configurações do JBoss

Application Server 5

O lançamento do AS5 é apenas o começo de uma nova era para os projetos JBoss.

A flexibilidade proporcionada pelo Mi-crocontainer permitirá à Red Hat/JBoss, além de inovar, estar up-to-date com as especificações do JCP.

O objetivo da Red Hat/ JBoss é ter o mais inovador, robusto e performático servidor de aplicações do mercado.

As possibilidades são infinitas e a Red Hat/JBoss precisa da participação da comu-nidade para ajudar na definição do futuro e no desenvolvimento do JBoss AS e de todos os outros projetos. Essa contribuição é es-sencial para manter os projetos JBoss como os mais populares, queridos e utilizados do planeta. A comunidade é o poder do open source. Não seja apenas usuário: participe, teste, reclame, sugira, contribua.

java 69.indb 25 26/05/2009 16:36:53

Page 26: java 69 [Introdução Spring Security] [Lido]

java 69.indb 26 26/05/2009 16:36:54

Page 27: java 69 [Introdução Spring Security] [Lido]

java 69.indb 27 26/05/2009 16:36:54

Page 28: java 69 [Introdução Spring Security] [Lido]

28 Java Magazine Edição 69

SEÇÃO JAVA: NESTA SEÇÃO VOCÊ ENCONTRA ARTIGOS INTERMEDIÁRIOS E AVANÇADOS SOBRE JAVA

De que se trata o artigo:

O artigo apresenta o projeto Spring Security como uma alternativa na área de segurança à tradicional

especificação Java EE, através de um exemplo prático e realista.

Para que serve:

Com o Spring Security é possível criar um mecanismo de autenticação e autorização para sua apli-

cação web em questão de minutos. O framework foca em facilitar a implementação dos casos de uso

mais freqüentes, porém oferece valiosos pontos de extensão para requisitos mais complexos. Por fim,

disponibiliza suporte a inúmeros diferentes tipos de autenticação e integração com as mais usadas

tecnologias na área de segurança.

Em que situação o tema é útil:

Para qualquer aplicação web que necessite restringir seus recursos para diferentes tipos de usuário, bem

como assegurar que se autentiquem de forma prática e segura.

Spring Security:

O Spring Security surgiu da necessidade de melhorar o suporte à segurança oferecido pela especificação

Java EE. O framework centraliza a configuração em um único XML, dispensando configurações do container

e tornando a aplicação web um arquivo WAR auto contido.

Para começar a utilizá-lo basta adicionar seus JARs ao classpath, configurar um filtro e um listener no

web.xml e criar um application context (XML de configuração). O XML centraliza todas as configurações

de autenticação e autorização. As tags <intercept-url> definem quais roles podem acessar cada grupo de

URLs. A tag <authentication-provider> define a fonte de dados para as informações de usuários (banco

de dados, arquivo de propriedades, LDAP, etc.).

Quando necessário, é possível utilizar os eventos publicados pelo framework a cada sucesso ou falha na

autenticação ou autorização. Ouvir os eventos permite criar complexos casos de gerenciamento de usuá-

rios. O Spring Security ainda oferece integrações com a API de Servlets, taglibs para facilitar a codificação

de JSPs, suporte à HTTPS, segurança em métodos com uso de anotações e suporte a autenticação com

LDAP ou certificados X509.

Segurança é um requisito importante presente na grande maioria dos sis-temas desenvolvidos. Na plataforma

Java EE temos uma solução oferecida pela especificação que determina como uma aplicação pode definir regras de controle de acesso e autenticação. Entretanto, ainda é comum nos depararmos com soluções “caseiras” para cumprir tal requisito. Em parte, tais soluções são criadas pela falta de experiência dos desenvolvedores, ou por ou-tro lado, porque a especificação não é flexível o suficiente para comportar os requisitos.

Com o objetivo de preencher a lacuna deixada pela especificação, em 2003 sur-giu o Acegi Security System for Spring. O Acegi Security é conhecido por ser extremamente configurável e poderoso, porém difícil de utilizar devido à enor-me quantidade de configuração XML necessária. Em 2007 o projeto Acegi foi incorporado dentro do guarda-chuva de projetos do Spring Framework Por-tifolio, e então, renomeado como Spring Security. Em abril de 2008 a versão 2.0.0 do Spring Security foi lançada tomando como proveito a configuração baseada em namespaces do Spring 2.0. Hoje, o Spring Security é extremamente fácil de configurar, sem perder a flexibilidade e o poder do antigo Acegi.

O Spring Security depende de alguns JARs do

Spring Framework “core”. Entretanto, não é necessá-

rio que sua aplicação seja construída com o modelo

de programação do Spring Framework. Ou seja, uma

aplicação pré-existente que não usa Spring pode pas-

sar a utilizar o Spring Security sem grandes modifica-

ções. Para aprender mais sobre o Spring Framework

consulte o artigo de capa da Edição 65.

Assim como o Java EE o Spring Security possui uma abordagem declarativa para segurança, baseada em roles (papéis).

java 69.indb 28 26/05/2009 16:36:55

Page 29: java 69 [Introdução Spring Security] [Lido]

MICHEL ZANINI

Edição 69 Java Magazine 29

A abordagem é declarativa, pois a aplica-ção não precisa chamar nenhum método para realizar autenticação ou autorização, tudo é feito através de configuração XML.

Para configurar o Spring Security de forma declarativa, assim como no Java EE, é necessário declarar quais serão os roles envolvidos, quais os recursos que serão protegidos, e quais roles podem acessar cada recurso. Além disso, declara-se como a autenticação será feita (basic, digest, form login, LDAP, etc.).

Este artigo apresenta as características do Spring Security, mostrando alguns recursos importantes não presentes na especificação Java EE. Exemplos práticos serão construídos, abordando cenários frequentes que são requisitos de grande parte das aplicações web.

Os conceitos básicos sobre segurança não são

abordados no artigo. Entretanto, o artigo de capa da

Edição 22 descreve tais conceitos e demonstra exem-

plos práticos utilizando a especificação Java EE.

Primeiro exemploComo primeiro exemplo vamos criar

uma aplicação web simples com duas áreas de acesso restrito: uma permitida para qualquer usuário autenticado (/usuarios/index.jsp) e outra apenas para usuários administradores (/admin/index.jsp). As páginas restritas apenas exibem uma mensagem e possuem um link de retorno à página principal. Espera-se que um login seja solicitado ao acessar qual-quer uma destas áreas. A página inicial da aplicação (/index.jsp), ilustrada na Figura 1, tem acesso livre e possui links para as duas áreas restritas.

O código fonte dos três JSPs são HTML simples e

portanto não serão exibidos nas listagens (estão dis-

poníveis para download no site da Java Magazine).

Figura 1. Página inicial da aplicação.

Listagem 1. web.xml – Configuração do Spring Security no web.xml

<web-app>

<filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy </filter-class> </filter>

<filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>

<listener> <listener-class>org.springframework.web.context.ContextLoaderListener </listener-class> </listener>

<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-security-config.xml</param-value> </context-param>

</web-app>

Configurando o web.xml

O Spring Security utiliza-se de um filtro HTTP, declarado no web.xml (Listagem 1), para interceptar todas as URLs acessadas e conferir suas permissões de acesso. Por isso, o filtro é aplicado com o url-pattern “barra asterisco”. No Java EE tal filtro não é necessário, pois o controle de acesso é realizado pelo próprio container.

É importante notar que o nome do filtro é ‘sprin-

gSecurityFilterChain’ e não deve ser alterado, pois o

Spring Security já espera que o filtro esteja com este

nome, por convenção.

No Java EE as configurações de auten-ticação e autorização são feitas no web.xml. No Spring Security são feitas em um application context padrão do Spring Framework. Dessa forma, precisamos do listener ContextLoaderListener declarado no web.xml para carregar o application con-text na inicialização da aplicação web. O atributo contextConfigLocation do liste-ner indica a localização do application context, neste caso, na raiz do classpath com o nome spring-security-config.xml.O web.xml da Listagem 1 aplica essas configurações.

java 69.indb 29 26/05/2009 16:36:56

Page 30: java 69 [Introdução Spring Security] [Lido]

30 Java Magazine Edição 69

Application context é o nome dado aos XMLs de

configuração do Spring Framework. Esses arquivos

são genéricos o suficiente para configurar qualquer

tipo de aplicação. Em casos específicos, como do

Spring Security, namespaces são utilizados para

reduzir a quantidade de XML necessária.

Controle de acesso e autenticação no spring-

security-config.xml

Agora é necessário criarmos o arquivo spring-security-config.xml, conforme a Listagem 2. Este arquivo, carregado pelo listener do web.xml, utiliza o namespace do Spring Security (http://www.springfra-mework.org/schema/security) para declarar regras de autenticação e autorização. Declaramos este namespace como default para o XML (sem prefixo) e o prefixo “be-ans” para o namespace normal do Spring Framework.

Se o leitor utiliza a IDE Eclipse, aconselhamos a

instalação do plugin Spring IDE (veja seção de links)

para facilidades na edição de application contexts.

Outras IDEs como NetBeans e IntelliJ IDEA também

possuem excelentes plugins de integração com o

Spring, vale à pena conferir.

O controle de acesso é definido pela tag <intercept-url> interna à tag <http>. No atri-buto pattern definimos uma expressão que atenderá as URLs acessadas e no atributo access definimos os roles de usuários que poderão acessar as URLs, separados por vírgulas. Definimos que todas as URLs com prefixo /usuarios serão acessadas por usuários normais e administradores e URLs com prefixo /admin apenas por administradores.

Por default a sintaxe das expressões utilizadas no

atributo pattern é a mesma utilizada no Ant. Porém,

se desejado, pode-se alterá-la para seguir a sintaxe

de expressões regulares. Para tal, basta adicionar o

atributo path-type=”regex” na tag <http>. Dessa

forma é possível criar expressões tão complexas

quanto necessário para atender às URLs, de acordo

com os requisitos do desenvolvedor.

As tags <intercept-url> serão interpreta-das em ordem de definição e a primeira a atender será usada. Dessa forma, os patterns mais específicos devem vir pri-

meiro. Por exemplo, a expressão ‘/usua-rios/vip/**’ deve ser declarada acima da expressão ‘/usuarios/**’, caso contrário a expressão ‘vip’ nunca será avaliada, pois a expressão ‘/usuarios/**’ também atende a URLs do tipo ‘/usuarios/vip/**’.

O atributo da tag <http>configura automaticamente a aplicação para utilizar login baseado em formulário. O JSP do formulário nem mesmo precisa ser codificado, o Spring Security irá gerá-lo dinamicamente conforme a Figura 2.Para mais informações sobre o auto-

veja o quadro “Entendendo o auto-config”.

Desta forma, a última coisa que nos resta é definir os usuários possíveis e seus pa-péis. No primeiro exemplo, para facilitar,

Listagem 2. spring-security-config.xml – Arquivo de configuração do Spring Security

<beans:beans xmlns=”http://www.springframework.org/schema/security” xmlns:beans=”http://www.springframework.org/schema/beans” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:schemaLocation=” http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.2.xsd”>

<http auto-config=”true”> <intercept-url pattern=”/usuarios/**” access=”ROLE_USUARIO,ROLE_ADMIN” /> <intercept-url pattern=”/admin/**” access=”ROLE_ADMIN” /> </http>

<authentication-provider> <user-service> <user name=”joao” password=”123” authorities=”ROLE_USUARIO” /> <user name=”admin” password=”123” authorities=”ROLE_ADMIN” /> </user-service> </authentication-provider>

</beans:beans>

iremos utilizar a tag <user-service> que permite definir usuários, senhas e roles no próprio arquivo XML (também é pos-sível referenciar um arquivo de proprie-dades). Normalmente, em uma aplicação real, não é viável definir os usuários em arquivo. Nos próximos exemplos iremos apresentar alternativas.

O atributo auto-config da tag <http> na confi-

guração do Spring Security ativa as opções mais

usadas do framework, ajudando a diminuir a

quantidade de XML necessário. Quando setamos

seu valor para “true” o Spring Security considera

o XML como a seguir:

<http> <form-login /> <anonymous /> <http-basic /> <logout /> <remember-me /></http>

Isso configura o framework para utilizar auten-

ticação por formulário e http-basic, bem como

tratamento de usuários anônimos e previamente

autenticados (remember-me).

Cada uma das tags possui atributos. Para

modificá-los é necessário apenas escrever a

tag específica, e o auto-config=true substituirá

esta parte da configuração. As tags omitidas

continuam sendo consideradas. Por exemplo,

o código abaixo muda o JSP do formulário de

login e o restante das configurações automáticas

continuam aplicadas.

<http auto-config=’true’> <form-login login-page=’/login.jsp’/></http>

Figura 2. Login gerado automaticamente pelo Spring Security.

java 69.indb 30 26/05/2009 16:36:56

cristianogarcia
Highlight
Page 31: java 69 [Introdução Spring Security] [Lido]

Edição 69 Java Magazine 31

Últimos passos

O esqueleto do projeto, juntamente com os JARs necessários para rodar os exemplos, podem ser vistos da Figura 3.Para ajudar na depuração da aplicação, através de log, criamos o arquivo log4j.properties e adicionamos o log4j.jar ao classpath. O JAR do banco de dados HSQL-DB está presente pois será utili-zado em breve, nos próximos exemplos. O resto das bibliotecas são dependências do Spring Security. Os JARs estão dispo-níveis no download dessa edição no site da Java Magazine.

Com os três JSPs, o web.xml, o spring-security-config.xml e os JARs necessários, podemos executar a aplicação. O deploy pode ser realizado em qualquer servidor da preferência do leitor, pois o Spring Security não requer configurações adi-cionais dependentes de container.

Executando o exemplo

Ao acessar o index da aplicação (Fi-gura 1) dois links serão apresentados. Ao clicar em algum deles, por exemplo /usuarios/index.jsp, o filtro do Spring Security irá detectar como uma página protegida e irá gerar automaticamente o HTML para o login (Figura 2). Um usuário normal, ao logar-se, terá acesso à página de usuários, mas não à de ad-ministradores. Já o administrador tem acesso a ambas as páginas. Note que o serviço de “remeber-me” para o login já está funcionando. O exemplo é bastante simples, mas já cobre alguns dos princi-pais conceitos e casos de uso.

Utilizando algoritmos de hashpara senhas

No primeiro exemplo as senhas dos usuários estão visíveis aos administrado-res da aplicação. Isto apresenta um risco de segurança. Um algoritmo de hash é normalmente usado em uma aplicação real, impossibilitando o acesso à senha original. Para tal, o Spring Security oferece a tag <password-encoder>. São oferecidos os principais algoritmos de hash e também é possível criar uma implementação custo-mizada. A Listagem 3 aplica o algoritmo “md5” como password-encoder. Figura 3. Arquivos do primeiro exemplo.

Listagem 3. spring-security-config.xml – Utilizando um password-encoder

<beans:beans (...) > (...)

<authentication-provider> <password-encoder hash=”md5” />

<user-service> <user name=”joao” password=”202cb962ac59075b964b07152d234b70” authorities=”ROLE_USUARIO” /> <user name=”admin” password=”202cb962ac59075b964b07152d234b70” authorities=”ROLE_ADMIN” /> </user-service> </authentication-provider>

(...)</beans:beans>

Listagem 4. login.jsp – Página de login

<html> <head> <title>Spring Security</title> </head> <body> <h1>Spring Security</h1><hr/> <p> <% if (request.getParameter(“login_error”) != null) { %> <font color=”red”> Não foi possível se autenticar.<br/> Motivo: ${SPRING_SECURITY_LAST_EXCEPTION.message}. </font> <% } %> </p> <form action=”j_spring_security_check” method=”POST”> Login: <input type=’text’ name=’j_username’ value=”${not empty login_error ? SPRING_SECURITY_LAST_USERNAME : ‘’}” /> Senha: <input type=’password’ name=’j_password’> <input type=”checkbox” name=”_spring_security_remember_me” /> Salvar as minhas informações neste computador? <input name=”submit” type=”submit” value=”Login” /> <input name=”reset” type=”reset” value=”Limpar” /> </form> <a href=”index.jsp”>Voltar...</a><br> </body></html>

Para gerar rapidamente um hash md5 para utilizar

nos exemplos o leitor pode implementar uma classe

Java simples de utilidade ou acessar um gerador

online (veja Links).

Formulário personalizadoA geração automática de formulário é

útil apenas para testes. Uma aplicação real necessita de uma página de formu-lário customizada. Iremos criar um JSP (/login.jsp) com um formulário para o nosso exemplo. Para isso acrescentamos este trecho dentro da tag <http> no spring-security-config.xml:

<form-login login-page=”/login.jsp” authentication-failure-url=”/login.jsp?login_error=true” />

O atributo authentication-failure-url con-figura o JSP que será apresentado caso o login falhe. Neste caso configuramos o

java 69.indb 31 26/05/2009 16:36:56

Page 32: java 69 [Introdução Spring Security] [Lido]

32 Java Magazine Edição 69

mesmo JSP do formulário de login com um parâmetro login_error=true. Esse pa-râmetro é utilizado pelo JSP de login da Listagem 4.

Os exemplos demonstrados utilizam Scriplets

(código Java no JSP) apenas por questões didá-

ticas. Uma aplicação real estaria utilizando a

taglib JSTL.

No topo do JSP, abaixo do título, testa-mos se o parâmetro login_error é igual a true. Caso verdade (o login falhou) então mostramos uma mensagem de erro. A expressão ${SPRING_SECURITY_LAST_EXCEPTION.message} recupera a última mensagem de erro gerada pelo framework. Essa mensagem por default está em inglês, mas pode ser internacionalizada.

Em seguida codificamos o formulário. Por default a action do formulário de login deve ser j_spring_security_check eo “name” dos inputs de usuário e senha j_username e j_password, respectivamen-te. No nosso exemplo, para habilitar o remember-me, adicionamos um checkbox com o “name” _spring_security_remember_me. Esse JSP gera a imagem da Figura 4.

Logout

O atributo auto-config=true da tag <http> já configura uma URL default para realizar o logout, /j_spring_security_logout. Ao clicar em um link apontando para esta URL o logout é realizado. Caso necessário, é possível modificar a URL acrescentado a tag <logout> dentro da tag <http>:

<logout logout-url=”/logout” />

Página de erro

Quando um usuário normal acessa a página protegida dos administradores

Figura 4. Página de login customizada.

o container apresenta uma mensagem padrão para o erro 403 (access denied). Essa página pode ser personalizada pelo Spring Security acrescentando o atributo access-denied-page à tag <http>:

<http access-denied-page=”/accessDenied.jsp” (...) >

E então, criamos o accessDenied.jsp con-forme a Listagem 5.

Formulário de login embutido em outras páginas

Quem tem experiência com a segurança tradicional Java EE sabe que não é pos-sível acessar o JSP de login diretamente pela aplicação. O container deve apresen-tar este JSP quando uma página protegida é acessada. Essa limitação cria outros problemas, por exemplo, quando um portal deseja que o formulário de login esteja contido em todas as áreas do site. Nesse caso, os desenvolvedores se obri-gam a criar algum mecanismo utilizando JavaScript para contornar a situação.

No Spring Security tais limitações simples-mente não existem. Quando o usuário acessa diretamente o JSP de login, ou quando um formulário de login embutido é utilizado, o Spring Security utiliza uma URL default para redirecionar o usuário. A tag <form-login> possui um atributo default-target-urlque indica esta URL (se não informada o default é a raiz da aplicação). Por exemplo, se o formulário for configurado desta forma:

<form-login default-target-url=”/index.jsp” (...) />

Sempre que o formulário de login for acessado diretamente, após logar-se, o /index.jsp será carregado. Caso o usuário acessar uma página protegida, após logar-se, esta será a página exibida e não o /index.jsp. Se o atributo always-use-default-target for true o usuário sempre será redirecio-nado para o /index.jsp.

Autenticação utilizando banco de dadosA última modificação necessária para

tornar o exemplo realístico é adicionar um banco de dados, substituindo a configu-ração dos usuários e roles do XML. Um modelo de dados típico para uma aplica-ção web, de maneira simplificada, é algo parecido com as tabelas da Figura 5.

Apesar de não ser necessário no nosso exemplo, criamos uma tabela de junção entre as tabelas de usuário e perfil para termos uma relação NxN. Este cenário é muito comum em aplicações enterprise.

O campo chamado ativo na tabela de usuários serve para impedir que usuários bloqueados autentiquem-se. Caso este campo for false o usuário está com o acesso bloqueado. O campo tenta-tivas_login armazena o número de vezes que o usuário errou a senha consecutiva-mente. Esse campo será utilizado apenas em exemplos posteriores.

Listagem 5. accessDenied.jsp – Página de erro

<html> <body> <h1>Spring Security</h1><hr/> <p><font color=”red”>Acesso negado. O usuário não tem permissão para acessar essa página.</font><p> <p>Remote user....: <%= request.getRemoteUser() %></p> <p>User principal....: <%= request.getUserPrincipal() %></p> <a href=”../”>Voltar...</a><br> <a href=”../j_spring_security_logout”>Logout</a><br> </body></html>

Figura 5. Modelo de dados para armazenar os usuários, senhas e perfis.

java 69.indb 32 26/05/2009 16:36:57

Page 33: java 69 [Introdução Spring Security] [Lido]

Edição 69 Java Magazine 33

O download do artigo traz dois scripts para serem executados no banco de dados HSQL. Um script cria as tabelas e outro cria alguns usuários para tes-te. Para rodar o HSQL basta executar este comando no prompt do sistema operacional (considerando que o jar do HSQL está no diretório corrente):

java -cp hsqldb-1.8.0.7.jar org.hsqldb.Server

Logo após, abra outro prompt e execute o comando para abrir o console SQL com interface gráfica:

java -cp hsqldb-1.8.0.7.jar org.hsqldb.util.DatabaseManagerSwing

Selecione a opção “HSQL Database En-gine Server” e pressione OK. Ao abrir o console execute os dois scripts para criar e popular as tabelas. Feche o console, mas mantenha sempre o prompt do servidor HSQL rodando.

Alterar a configuração do Spring Securi-ty para considerar as tabelas é algo muito simples, pressupondo que o banco de da-dos está corretamente configurado. Duas modificações são necessárias: substituir a tag <user-service> por uma tag <jdbc-user-service> e acrescentar um spring bean para a configuração do banco de dados (data-source). A Listagem 6 demonstra o novo spring-security-config.xml.

Precisamos de três atributos para configurar a tag <jdbc-user-service>. O primeiro atributo é uma referência para a configuração do banco de dados que será utilizado (data-source-ref). O segundo é a query que será utilizada para buscar os usuários dado um username (users-by-username-query). Essa query necessita retornar três colunas esperadas pelo Spring Security: username, password e enabled. Mapeamos as colunas do nosso modelo para as esperadas pela query. Por último, uma query para buscar os roles (authorities) do usuário, dado um userna-me (authorities-by-username-query). Essa query retorna um username e a authority (role). Isso permite ao framework realizar as queries no banco e utilizar as informa-ções retornadas para autenticação.

No final do arquivo de configuração adicionamos um bean “dataSource” e o configuramos para acesso ao banco de

Listagem 6. spring-security-config.xml – Adicionando autenticação com banco de dados

<beans:beans (...)> <http auto-config=”true” access-denied-page=”/accessDenied.jsp”> <intercept-url pattern=”/usuarios/**” access=”ROLE_USUARIO,ROLE_ADMIN” /> <intercept-url pattern=”/admin/**” access=”ROLE_ADMIN” /> <form-login login-page=”/login.jsp” authentication-failure-url=”/login.jsp?login_error=true” default-target-url=”/index.jsp” /> </http> <authentication-provider> <password-encoder hash=”md5” /> <jdbc-user-service data-source-ref=”dataSource” users-by-username-query=”select login as username, senha as password, ativo as enabled from usuario where login = ?” authorities-by-username-query=”select u.login as username, p.descricao as authority from usuario u join usuario_perfil up on u.login = up.login join perfil p on up.id_perfil = p.id_perfil where u.login = ?” /> </authentication-provider> <beans:bean id=”dataSource” class=”org.springframework.jdbc.datasource. DriverManagerDataSource”> <beans:property name=”url” value=”jdbc:hsqldb:hsql://localhost” /> <beans:property name=”driverClassName” value=”org.hsqldb.jdbcDriver” /> <beans:property name=”username” value=”sa” /> <beans:property name=”password” value=”” /> </beans:bean></beans:beans>

Figura 6. Eventos de autenticação e autorização publicados pelo Spring Security.

java 69.indb 33 26/05/2009 16:36:58

Page 34: java 69 [Introdução Spring Security] [Lido]

34 Java Magazine Edição 69

Listagem 7. TestEventListener.java – Ouve eventos de autenticação publicados pelo Spring Security

public class TestEventListener implements ApplicationListener {

public void onApplicationEvent(ApplicationEvent event) { if (event instanceof AuthenticationSuccessEvent) { System.out.println(“Usuário autenticado com sucesso”); } if (event instanceof AbstractAuthenticationFailureEvent) { System.out.println(“Usuário não autenticado”); } }

}

Listagem 8. IncorrectPasswordEventListener.java – Listener que atualiza a coluna tentativas_login de acordo com o resultado da autenticação

public class IncorrectPasswordEventListener extends JdbcDaoSupport implements ApplicationListener {

public void onApplicationEvent(ApplicationEvent event) { if (event instanceof AuthenticationFailureBadCredentialsEvent) { AuthenticationFailureBadCredentialsEvent badCredentialsEvent = (AuthenticationFailureBadCredentialsEvent) event; String sql = “update Usuario set tentativas_login = tentativas_login + 1 where login = ?”; this.executeSql(badCredentialsEvent, sql); } if (event instanceof AuthenticationSuccessEvent) { AuthenticationSuccessEvent successEvent = (AuthenticationSuccessEvent) event; String sql = “update Usuario set tentativas_login = 0 where login = ?”; this.executeSql(successEvent, sql); } }

private void executeSql(AbstractAuthenticationEvent event, String sql) { getJdbcTemplate().update(sql, new Object[]{event.getAuthentication(). get Name()}); }}

Listagem 9. Interface UserDetailsService e o método loadUserByUsername() a ser implementado

public class CustomUserDetailsService implements UserDetailsService { public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { //retorna um objeto representado o usuário a ser autenticado return null; }}

dados HSQL. Repare que utilizamos a classe DriverManagerDataSource que serve apenas para propósitos de teste. Em uma aplicação real configuraríamos um pool de conexões como data-source, normal-mente oferecido pelo container através de um nome JNDI.

Eventos de autenticação e autorizaçãoO Spring Security uti l iza a infra-

estrutura do application context do Spring para publicar eventos referentes a momentos importantes em seu fluxo de execução. Existem duas categorias de eventos: eventos de autenticação e eventos de autorização. Para cada situ-ação existe um evento correspondente.

Por exemplo, quando uma autenticação ocorre com sucesso, um evento Authen-ticationSuccessEvent é publicado; quando a autenticação falha porque a senha está errada, um evento AuthenticationFai-lureBadCredentialsEvent é publicado; se a autenticação falha porque o usuário está inativo, um evento AuthenticationFailure-DisabledEvent ocorre; e assim por diante. Quando uma URL é acessada e o filtro do Spring Security verifica se o usuário tem autorização para acessar a URL, eventos de sucesso ou falha também são publicados. Veja na Figura 6 uma hierarquia de eventos de autenticação e autorização. Consulte o Javadoc de cada classe para entender o momento em que cada evento é publicado.

Para “ouvirmos” aos eventos acima é necessário implementar a interface Appli-cationListener e registrar a classe no applica-tion context. A Listagem 7 demonstra um exemplo simples de como ouvir a eventos de sucesso ou falha na autenticação.

Lembre-se de adicionar o novo bean no application context:

<beans:bean class=”br.com.jm.security.TestEventListener” />

Essa funcionalidade permite imple-mentar complexos casos de uso, com baixo acoplamento entre a aplicação e o Spring Security, como veremos em um exemplo adiante. Para facilitar o apren-dizado de quando os eventos ocorrem, registre dois listeners que vêm juntos com a distribuição do Spring Security, como a seguir:

<beans:bean class=”org.springframework.security.event.authorization.LoggerListener” /><beans:bean class=”org.springframework.security.event.authentication.LoggerListener” />

Estes listeners efetuam log de todos os eventos que ocorrem, de autenticação e autorização. Uma ótima forma de aprender o funcionamento do framework é a análise do log gerado por estes listeners.

Explorando os pontos de extensãoEscolhemos um caso de uso para demons-

trar como os eventos de autenticação são úteis e como é fácil customizar o framework.

java 69.indb 34 26/05/2009 16:36:59

Page 35: java 69 [Introdução Spring Security] [Lido]

Edição 69 Java Magazine 35

Cada vez que um usuário errar a senha por três vezes consecutivas, a sua conta será bloqueada. Essa funcionalidade é muito comum em sites que exigem altos padrões de segurança, como bancos por exemplo. A cada erro de autenticação por informar a senha incorreta (evento AuthenticationFailu-reBadCredentialsEvent) a coluna tentativas_loginserá incrementada. A cada autenticação com sucesso (evento AuthenticationSuccessEvent)a coluna tentativas_login será zerada. A cada tentativa de login, caso a coluna tentativas_lo-gin for igual ou maior que três, a autenticação será bloqueada. Veja na Listagem 8 o listener que atualiza a coluna tentativas_login.

Para completar o exemplo ainda é neces-sário bloquear o login caso a coluna seja maior ou igual a três. Para isso iremos ex-plorar um ponto de extensão comumente utilizado no Spring Security, a interface UserDetailsService. Essa interface possui o método loadUserByUsername() que recupera os dados de um usuário dado seu username. Veja a Listagem 9.

Uma implementação dessa interface substitui as tags <user-service> (usuários em XML ou arquivo de propriedades) ou <jdbc-user-service> (usuários em banco de dados) que vimos até agora. Sendo assim, através dessa implementação, o usuário do framework tem liberdade para buscar as informações de onde necessitar e da forma que quiser. Entretanto, o motivo mais comum para implementar a interface não é a escolha de uma nova fonte de dados e sim, a personalização do objeto UserDetailsde retorno.

A interface UserDetails é implementada por objetos que representam o usuário no seu modelo de domínio. Ela possui métodos para retornar o username, o password, as authorities e quatro booleans represen-tando diferentes motivos para bloqueio do login: enabled, accountNonLocked, accountNo-nExpired e credentialsNonExpired. Sendo assim, criamos uma classe Usuario para implemen-tar a interface, veja a Listagem 10.

Caso qualquer um dos métodos que retornam boolean retornar false o login será bloqueado e uma mensagem adequada será apresentada. Nesse caso não iremos utilizar as propriedades de conta ou senha expirada, então retornarmos sem-

pre true nos métodos isAccountNonExpired()e isCredentialsNonExpired(). Para o método isEnable() utilizamos o valor da coluna ativo no banco de dados e para o método isAccountNonLocked() utilizamos nossa regra de negócios: bloquear o login caso três ou mais tentativas de login tenham sido feitas com a senha incorreta.

Para conectar as implementações pre-cisamos de uma classe que implemente a interface UserDetailsService. Entretanto,

Listagem 10. Usuario.java – Objeto do modelo de domínio que implementa a interface UserDetails

public class Usuario implements UserDetails { private String login; private String senha; private String email; private boolean ativo; private Integer tentativasLogin; private GrantedAuthority[] authorities;

public String getUsername() { return this.login; } public String getPassword() { return this.senha; } public GrantedAuthority[] getAuthorities() { return this.authorities; } public boolean isEnabled() { return this.ativo; } public boolean isAccountNonLocked() { return this.tentativasLogin < 3; } public boolean isAccountNonExpired() { return true; } public boolean isCredentialsNonExpired() { return true; } // --- restante dos getters and setters omitidos ---}

Listagem 11. CustomUserDetailsService.java – Estende a classe JdbcDaoImpl para modificar o UserDetails de retorno

public class CustomUserDetailsService extends JdbcDaoImpl { protected UserDetails createUserDetails(String username, UserDetails userFromUserQuery, GrantedAuthority[] combinedAuthorities) { Usuario usuario = new Usuario(); usuario.setLogin(userFromUserQuery.getUsername()); usuario.setSenha(userFromUserQuery.getPassword()); usuario.setAtivo(userFromUserQuery.isEnabled()); usuario.setAuthorities(combinedAuthorities); this.carregarInformacoesAdicionais(usuario); return usuario; }

private void carregarInformacoesAdicionais(final Usuario usuario) { String sql = “select email, tentativas_login from Usuario where login = ?”; getJdbcTemplate().query(sql, new Object[]{usuario.getUsername()}, new Row Mapper() { public Object mapRow(ResultSet rs, int rowNum) throws SQLException { usuario.setEmail(rs.getString(“email”)); usuario.setTentativasLogin(rs.getInt(“tentativas_login”)); return null; } }); }}

queremos continuar utilizando um banco de dados para armazenar os usuários e apenas retornar um objeto Usuario com informações adicionais, as colunas email e tentativas_login. Para não duplicarmos códi-go sem necessidade, iremos estender uma classe do Spring Security que já nos oferece um ponto de extensão justamente para es-tes casos. A classe JdbcDaoImpl é a classe por trás da tag <jdbc-user-service>. Essa classe já implementa o método loadUserByUsername() e

java 69.indb 35 26/05/2009 16:36:59

Page 36: java 69 [Introdução Spring Security] [Lido]

36 Java Magazine Edição 69

Listagem 12. spring-security-config.xml – Versão final do XML de configuração refletindo o exemplo de bloqueio de login

<beans:beans (...) > <http auto-config=”true” access-denied-page=”/accessDenied.jsp”> <intercept-url pattern=”/usuarios/**” access=”ROLE_USUARIO,ROLE_ADMIN” /> <intercept-url pattern=”/admin/**” access=”ROLE_ADMIN” /> <form-login login-page=”/login.jsp” authentication-failure-url=”/login. jsp?login_error=true” default-target-url=”/index.jsp” /> </http> <authentication-provider user-service-ref=”customUserService”> <password-encoder hash=”md5” /> </authentication-provider> <beans:bean id=”customUserService” class=”br.com.jm.security. CustomUserDetailsService”> <beans:property name=”dataSource” ref=”dataSource” /> <beans:property name=”usersByUsernameQuery” value=”select login as username, senha as password, ativo as enabled from usuario where login = ?” /> <beans:property name=”authoritiesByUsernameQuery” value=”select u.login as username, p.descricao as authority from usuario u join usuario_perfil up on u.login = up.login join perfil p on up.id_perfil = p.id_perfil where u.login = ?” /> </beans:bean> <beans:bean id=”dataSource” class=”org.springframework.jdbc.datasource. DriverManagerDataSource”> <beans:property name=”url” value=”jdbc:hsqldb:hsql://localhost” /> <beans:property name=”driverClassName” value=”org.hsqldb.jdbcDriver” /> <beans:property name=”username” value=”sa” /> <beans:property name=”password” value=”” /> </beans:bean> <beans:bean class=”br.com.jm.security.IncorrectPasswordEventListener”> <beans:property name=”dataSource” ref=”dataSource” /> </beans:bean> <beans:bean class=”org.springframework.security.event.authorization.Logger Listener” /> <beans:bean class=”org.springframework.security.event.authentication.Logger Listener” /></beans:beans>

nos deixa uma extensão valiosa, o método createUserDetails(). Esse método é um gancho para retornar um UserDetails customizado. Veja a Listagem 11.

O método createUserDetails() apenas copia propriedades que já estão disponíveis

e chama o método carregarInformacoesAdicionais() que faz uma query para pre-encher as propriedades restantes: email e tentativas_login.

A implementação do caso de uso está completa. A classe CustomUserDetailsService

é utilizada para buscar as informações de um usuário e retornar um UserDetailsdo nosso domínio. Após a execução do método lo adUs e rByUs e r name ( ) as propriedades booleanas do Usuariosão testadas. Nesse caso, o getter da propriedade accountNonLocked testa se a coluna tentativas_login é igual ou maior que três. Por fim, para controlar o incremento da coluna, os eventos de sucesso e falha na autenticação são tra-tados pela classe IncorrectPasswordEven-tListener. O novo spring-security-config.xml é demonstrado na Listagem 12.

A principal diferença do novo XML é a tag <authentication-provider>. Re-t iramos o <jdbc-user-service> e f i-zemos uma referência para o bean “customUserService”. Como a classe CustomUserServiceDetails estende JdbcDa-oImpl as propriedades das queries continuam existindo. Sendo assim, copiamos as propriedades da antiga <jdbc-user-service> para o novo bean. Outra diferença importante é a adição do IncorrectPasswordEventListener no final do arquivo.

Integração com a API de servletsO filtro do Spring Security substitui

a implementação original da interface ServletRequest por um wrapper (extensão da classe ServletRequestWrapper). Este wra-pper implementa os métodos relaciona-dos a segurança na interface ServletRequest:getRemoteUser(), isUserInRole() e getUserPrinci-pal(). Dessa forma, é possível utilizar os métodos tradicionais do Java EE como de costume, sem diferenças. Por exem-plo, veja o trecho de código a seguir:

Autenticação single sign on significa logar-se em uma aplicação e permanecer logado ao acessar outra aplicação do mesmo grupo. Essa funcionalidade é comumente oferecida por containers para as aplicações as quais ele gerencia. O Spring Security oferece suporte a single sign on para aplicações intranet através do Central Authentication Service (CAS) e aplicações internet através do OpenID.O CAS é uma aplicação web (arquivo WAR) que é responsável por apresentar as telas de login das aplicações do mesmo grupo. Basicamente, todas as aplicações do grupo irão redirecionar o browser para a aplicação central na hora da autenticação, e após o login, o CAS irá retornar a URL para a aplicação que solicitou o login. Dessa forma, as configurações de autenticação ficam no

WAR do CAS e nos demais WARs o Spring Security é usado para realizar a integração. Uma vantagem do CAS é o fato de existirem clientes para diversas linguagens como Java, .Net, PHP, Perl, etc. permitindo integração entre aplicações heterogêneas.O OpenID, por sua vez, elimina a necessidade de ter vários logins em diferentes sites na internet. Ao criar um login em um dos providers de OpenID (veja Links) é possível utilizar o username e senha para acessar todos os sites que o suportam, sem necessitar logar-se múltiplas vezes. Grandes empresas já suportam o padrão como Sun, Google, IBM, Microsoft, etc. O Spring Security facilita o processo de habilitar sua aplicação para suportar logins provenientes de providers OpenID.

N o t a d o D e v M a nWrapper: Um objeto wrapper é uma implementação do padrão de projeto Decorator. O objetivo deste desing pattern é adicionar ou substituir o comportamento de classes existentes de forma dinâmica. Isto é feito criando uma classe base, normalmente com o sufixo Wrapper ou Decorator, que implementa a interface a ser decorada e também recebe como parâmetro no construtor um objeto da mesma interface. Em seguida, todos os métodos da classe são implementados delegando para o objeto recebido no construtor. Por fim, quando se deseja adicionar ou mudar o comportamento da interface, basta estender o Wrapper e sobre-escrever os métodos desejados.

java 69.indb 36 26/05/2009 16:36:59

Page 37: java 69 [Introdução Spring Security] [Lido]

Edição 69 Java Magazine 37

String role = request.getRemoteUser();System.out.println(“Role: “ + role);

System.out.println(request.isUserInRole(“ROLE_USUARIO”));System.out.println(request.isUserInRole(“ROLE_ADMIN”));

Este código funciona perfeitamente com o Spring Security. Se o usuário “admin” (com perfil de administrador) estiver lo-gado, então a seqüência a ser impressa no console será:

Role: adminfalsetrue

O método getUserPrincipal() retorna um objeto que implementa a interface org.springframework.security.Authentication. Através desse objeto é possível retornar o usuário logado, como a seguir:

public Usuario getUsuarioLogado(HttpServletRequest request) { Authentication authentication = (Authentication) request. getUserPrincipal(); if (authentication == null) return null; return (Usuario) authentication.getPrincipal();}

Outra forma de se obter o usuário logado, porém sem necessitar do Http-ServletRequest, é através da classe Secu-rityContextHolder. Essa classe mantém o objeto Authentication em uma variável thread-local. O método a seguir pode ser implementado em uma classe de uti-lidade e pode ser chamado em qualquer ponto da aplicação:

public static Usuario getUsuarioLogado() { Authentication authentication = (Authentication) SecurityContextHolder.getContext().getAuthentication(); if (authentication instanceof Usuario) { return (Usuario) authentication.getPrincipal(); } return null;}

Utilizando as taglibsO Spring Security fornece duas tags

úteis para codificação de JSPs: <authorize> e<authentication>. Ambas podem ser impor-tadas com a declaração a seguir:

<%@ taglib prefix=”sec” uri=”http://www.springframework.org/security/tags” %>

A tag <authorize> é utilizada para mos-trar/esconder informações de acordo com as permissões (roles) do usuário. Veja o código a seguir:

<sec:authorize ifAllGranted=”ROLE_ADMIN”> <p>Você é um administrador e também pode acessar esta <a href=”../admin/index.jsp”>página</a>.<p></sec:authorize>

A tag possui três atributos exclusivos: ifAllGranted, ifAnyGranted e ifNotGranted.Todos os atributos suportam um ou mais roles separados por vírgula. O atributo ifAllGranted informa que o usuário tem que possuir todos os roles declarados para retornar true. O atributo ifAnyGranted necessita de apenas um dos roles para retornar true e o atributo ifNotGranted será true apenas se o usuário não possuir nenhum dos roles.

A tag <authentication> permite acessar as propriedades do objeto Authentication do usuário logado no JSP. Por exemplo, o trecho de código a seguir, codificado no index.jsp, irá exibir as informações do usuário utilizando a tag <authentication>:

<sec:authorize ifAnyGranted=”ROLE_ADMIN,ROLE_USUARIO”> <b>Informações do usuário logado:</b><br> Login: <sec:authentication property=”principal.login” /> <br> Senha: <sec:authentication property=”principal.senha” /> <br> E-mail: <sec:authentication property=”principal.email” /> <br> <a href=”j_spring_security_logout”>Logout</a><br></sec:authorize>

ConclusõesCom os exemplos demonstrados podemos

ver alguns dos principais casos de uso de segurança em uma aplicação web. O Spring Security centraliza as configurações em apenas um arquivo que será empacotado juntamente com o war da aplicação, dispen-sando configurações externas do container. A aplicação não fica apenas mais enxuta, como também mais extensível, como vi-mos através da interface UserDetailsService e

java 69.indb 37 26/05/2009 16:37:00

Page 38: java 69 [Introdução Spring Security] [Lido]

Michel Zanini [email protected]É formado em Ciências da

Computação pela Universidade Federal

de Santa Catarina (UFSC) e possui as

certificações SCJP, SCWCD, SCBCD e SCDJWS.

Dê seu feedback sobre esta edição!

A Java Magazine tem que ser feita aoseu gosto. Para isso, precisamos sabero que você, leitor, acha da revista!

Dê seu voto sobre este artigo, através do link:

www.devmedia.com.br/javamagazine/feedback

seu Feedback

sob

reeeestaedição

dos eventos de autenticação e autorização. Dessa forma é possível implementar casos complexos de gerenciamento de usuários, de forma desacoplada do domínio de negó-cios da aplicação.

Alguns assuntos não foram abordados no artigo por motivo de espaço, porém o leitor pode consultar a documentação no site do framework. Algumas funcionalidades oferecidas pelo Spring Security e não apre-sentadas são: segurança a nível de métodos (utilizando anotações e AOP), suporte a HTTPS, controle de sessões concorrentes e diferentes formas de autenticação, como certificados X509, LDAP, etc. Para mais infor-mações sobre single sign on consulte o quadro“Single sign on com CAS e OpenID”.

www.springsource.org

Portal do Spring Framework e sub-projetos

static.springframework.org/spring-security/

site/index.html

Acesso direto à home page do Spring Security

springide.org/blog

Download do Spring IDE (plugin para o Eclipse)

www.jasig.org/cas

Homepage do projeto CAS

openid.net

Homepage do OpenID

www.myopenid.com

Provider de logins OpenID

md5-hash-online.waraxe.us

Gerador online de hash md5

java 69.indb 38 26/05/2009 16:37:07

Page 39: java 69 [Introdução Spring Security] [Lido]

Edição 69 • Java Magazine 39

03_Michel_Spring.indd 39 05/06/2009 16:41:35

Page 40: java 69 [Introdução Spring Security] [Lido]

SEÇÃO JAVA: NESTA SEÇÃO VOCÊ ENCONTRA ARTIGOS INTERMEDIÁRIOS E AVANÇADOS SOBRE JAVA

40 Java Magazine Edição 69

De que se trata o artigo:

Apresentamos uma referência da linguagem JavaFX Script, que faz parte da plataforma JavaFX.

Para que serve:

JavaFX é a nova plataforma RIA da Sun, compatível com Java SE e Java ME, já apresentadas em artigos

anteriores desta série. Alguns leitores podem encarar a exigência de aprender uma nova linguagem

de programação como um obstáculo, mas este aprendizado é facilitado pela semelhança entre JavaFX

Script e Java – tiramos proveito desta semelhança para explicar a nova linguagem de forma concisa.

Mesmo para quem já aprendeu JavaFX Script, o artigo serve como uma referência bem organizada e

pragmática (ao contrário da referência oficial, que tem uma estrutura mais formal, certamente mais

detalhada, mas não adequada à facilidade de consulta e sem pretensões didáticas).

Em que situação o tema é útil:

A linguagem JavaFX Script é um pré-requisito para desenvolver para a plataforma JavaFX, a qual pro-

mete grande produtividade, mas (com qualquer plataforma) somente após vencer uma curva inicial de

aprendizado.

Mesmo para quem não tiver grande interesse na JavaFX, o artigo apresenta muitas inovações da JavaFX

Script que são um aprendizado valioso para qualquer interessado em linguagens de programação.

Na Edição 67 apresentamos a plata-forma JavaFX, introduzindo-a de forma conceitual e dando alguns

“aperitivos” das suas funcionalidades e programação. Na Edição anterior (68), seguimos com um primeiro tutorial de programação JavaFX, ensinando o básico da linguagem e framework de uma forma prática, mas bastante informal.

Agora, encerrando esta cobertura inicial da JavaFX, vamos nos focar apenas na lin-guagem JavaFX Script, cobrindo-a de uma forma mais formal e abrangente. (Para o leitor ainda pouco motivado a aprender JavaFX Script, seria boa idéia começar pelo quadro “Por que uma nova linguagem?”.)

Não é meu objetivo repetir o documento de Referência da Linguagem de Progra-mação JavaFX Script que está disponível em openjfx.dev.java.net/langref. Ao invés disso, a idéia é explicar a linguagem de uma forma concisa e pragmática, tendo como alvo não alguém que vai escrever um compilador ou outra ferramenta que exige conhecimento formal da linguagem, mas um desenvolvedor que deseja vencer a curva de aprendizado da sua sintaxe ou então ter uma referência de fácil consul-ta. Ainda mais especificamente, escrevo pensando no programador que já conhece bem a linguagem Java, o que permitirá resumir ou omitir explicações dos pontos onde ambas as linguagens forem iguais ou muito parecidas (e são muitos pontos). Assim, podemos concentrar nosso tempo e neurônios nas partes que são diferentes.

O artigo é organizado como uma refe-rência da linguagem, agrupando suas funcionalidades em seções como Valores, Operadores, Classes etc., de forma similar a uma referência formal. No entanto, fiz este agrupamento de uma forma “relaxada” segundo critérios conceituais e não de gra-mática formal. Por exemplo, a seção de Ope-

radores não possui todos os operadores, pois alguns deles são cobertos em outras seções (ex.: os diversos operadores específi-cos para sequences são mostrados na seção Sequences). Também não me preocupei em documentar minimamente alguns aspectos mais elementares da linguagem que são exatamente idênticos a Java, por exemplo a sintaxe para números literais. A intenção é ter um texto o mais compacto e didático possível, mas ainda assim, suficientemente organizado e formal para servir como refe-rência da linguagem.

No decorrer do artigo, uso o termo “JavaFX” no

lugar de “JavaFX Script”, por simplicidade.

Tipos e ValoresO sistema de tipos da JavaFX é inspirado

no Java, mas com melhorias importantes. Na Tabela 1, classifiquei os tipos da Java-FX em cinco categorias e comparei-os aos

tipos equivalentes em Java. Vamos comen-tar apenas as novidades desta tabela.

Valores

A maior novidade é que o typesystem de JavaFX é OO-puro: não existem tipos primitivos. Por outro lado, existem “tipos de valor”, que são aqueles cuja igualdade de referência é equivalente à igualdade de valor (em outras palavras: x == y se e somente se x.equals(y)). Os tipos primitivos do Java, como int, são tipos de valor, por isso não há dois valores 17 distintos, por exemplo. O mesmo vale para o Integer da JavaFX. Além disso, os valores são imutáveis, e não admitem null.

A diferença entre esses tipos da JavaFX e os tipos primitivos do Java é que os tipos de valor são objetos. Em JavaFX, todos os tipos, sem exceção, são derivados de Object.

Em termos de implementação, os valores de JavaFX são equivalentes aos primitivos de Java, evitando o custo de desempenho

java 69.indb 40 26/05/2009 16:37:14

Page 41: java 69 [Introdução Spring Security] [Lido]

OSVALDO PINALI DOEDERLEIN

Edição 69 Java Magazine 41

de usar objetos. Por exemplo, se você olhar o arquivo .class gerado pelo javafxc para uma função que recebe um parâmetro Integer,verá que o bytecode compilado irá conter um método que recebe um int primitivo. Somente quando um valor é utilizado em alguma operação que exige sua faceta OO, a JavaFX faz uma conversão automática para um objeto. Você pode considerar isso uma versão melhorada do autoboxing de Java 5. As melhorias incluem a simplificação (não há tipos paralelos como int/Integer) e desem-penho (o compilador, runtime e frameworks usam várias técnicas para representar valo-res na forma primitiva, e reduzir ao mínimo as conversões de/para a forma OO).

Strings

Menção honrosa vai para o tipo String da JavaFX Script, que ao contrário de Java, é definido como um value type. Além disso, carrega um lote de funcionalidades extra:

O valor default de uma String não inicia-lizada é “” (string vazia). É impossível ter uma string null; se você fizer esta atribui-ção, fica com “”. Nunca acontecerá uma NullPointerException envolvendo strings (ou qualquer value type);

O operador == equivale a equals(), não há distinção entre igualdade e identidade (novamente, como todos value types);

Pode-se mesclar strings com expressões, por exemplo: “Alô, {nome}!” será expandido conforme o valor dinâmico da variável nome. Ou então, “Temperatura: {%2.2f temp}”,a variável temp será formatada no estilo de System.printf() (ex.: %2.2f 32.257 32,25);

Pode ser delimitada por aspas simples ou duplas, ex.: ‘String com “aspas duplas” dentro’;

Internacionalização é simples: def msg = ##”ERRO” irá atribuir a msg o valor da string associada à chave ERRO no resource bundleda aplicação; se não existir este resour-ce, o valor da string será “ERRO” mesmo.

VALORES (value types)

Comentários JavaFX Java

true ou false Boolean booleanInteiro, 8 bits sem sinal Byte byteInteiro, 16 bits com sinal Short shortInteiro, 32 bits com sinal Integer intIEEE754, 32 bits Number, Float floatIEEE754, 64 bits Double doubleString String (Em Java, é tipo de referência)

Duração temporal Duration N/A; costuma-se usar long

VOID

Comentários JavaFX JavaNenhum valor Void void

REFERÊNCIA

Comentários JavaFX JavaClasse class class, interfaceFunção function (parâmetros) : retorno N/D

Seqüência/Array TipoElemento [] TipoElemento []

Tabela 1. Classificações de tipos da JavaFX, comparativamente com Java.

Para separar a chave do valor default, use ##[ERRO]”Deu zebra!”;

É o único tipo de JavaFX Script para manipular caracteres. Não existe um tipo específico para um caractere único, como o char do Java. Conversões automáticas são feitas ao invocar classes/APIs de Java que utilizam char; ex.: “Osvaldo”.charAt(0) = “O”.

Duration

O tipo de valor Duration representa uma quantidade de tempo. Exemplos de literais: 15ms (15 milissegundos), 2.3s (2.3 segundos), 55m (55 minutos), 10h (10 horas), 10h + 5m (10 horas e 5 minutos). Este tipo não passa de

um açúcar sintático para um long contendo o tempo normalizado para milissegundos, mas ao usar o framework de animação da JavaFX, você verá que é muito conveniente ter uma sintaxe especial para isso.

Void

O Void do Java FX significa o mesmo que o do Java, mas é mais útil, ver seção Controle.

Referência

Os reference types da JavaFX também são familiares. Ver seções sobre funções e sequences.

java 69.indb 41 26/05/2009 16:37:15

Page 42: java 69 [Introdução Spring Security] [Lido]

42 Java Magazine Edição 69

Funções

JavaFX Script possui funções de primeira ordem. Exemplo:

var validador: function (o:Object): Boolean

O tipo da variável validador é uma função que possui um parâmetro do tipo Objecte retorna um Boolean. Portanto, funções podem ser atribuídas a variáveis, passa-das como parâmetro, etc. como quaisquer outros tipos. A linguagem Java possui uma aproximação desta facilidade, com-binando interfaces com inner classes – mas o resultado é uma sintaxe confusa. Com a versão muito melhorada de JavaFX, pode-mos escrever por exemplo um tratador de eventos assim:

Stage { onClose: function() { FX.exit() }

}

Funções suportam os seguintes modifi-cadores (antes do function):

Visibilidade (public, protected, package, e por default script-private);

abstract, igual a Java;override, igual ao @Override do Java 5 (mas

é mandatório);bound, que examinaremos em Binding;Não há nada equivalente ao final dos

métodos Java.

Sequences

As sequences da JavaFX Script possuem sintaxe similar, mas significado e capaci-dades diferentes dos arrays do Java. Em comum com os arrays, as sequences são coleções de objetos de um tipo homo-gêneo e com tamanho fixo, indexadas a partir da base 0.

As diferenças começam com algumas sintaxes facilitadas (syntax sugar), mas vão além. A Tabela 2 exemplifica todas as capacidades e sintaxes específicas para sequences. Algumas coisas são simples – por exemplo, o operador sizeof equivale ao pseudo-atributo length dos arrays do Java; e com o ‘..’ você pode especificar ranges (intervalos), que podem ser usados tanto para determinar quais elementos da se-quence serão manipulados (como em delete dias[1 .. 2]), quanto para criar uma sequence contendo todos os números inteiros do range (como em [1 .. 100]).

SEQUENCES

Expressão Resultadodef dias : String[] = [ “Dom”, “Seg”, “Ter” ]def dias = [ “Dom”, “Seg”, “Ter” ]

[ “Dom”, “Seg”, “Ter” ]

sizeof dias 3dias[1] “Seg”dias[1 .. 2]dias[1 .. <3]

[“Ter”, “Qua”]

dias[d | d.startsWith(“T”)] [“Ter”]dias[0] = “DOM” [“DOM”, “Seg”, “Ter”]insert “Qua” into diasinsert “Qua” before dias[3]insert “Qua” after dias[2]

[“Dom”, “Seg”, “Ter”, “Qua”]

insert [“Qua”, “Qui”] into dias[ dias, [“Qua”, “Qui”] ]

[“Dom”, “Seg”, “Ter”, “Qua”, “Qui” ]

delete dias[1]delete “Dom” from dias

[“Seg”, “Ter”]

delete dias[1 .. 2] [“Seg”]delete dias []for (d in dias) d.charAt(0)

[ “D”, “S”, “T” ](for generator, retorna uma sequence com os elementos produzidos por cada iteração)

for (d in dias where d.startsWith(“T”)) d.charAt(0)

[ “T” ]

[ 1 .. 100 ] [ 1, 2, 3, 4, .., 98, 99, 100 ](É na verdade uma instância de Range,não consome memória com a lista de elementos)

[ 1 .. 100 step 10] [ 1, 11, 21, 31, 41, 51, 61, 71, 81, 91 ] (Novamente Range)

dias = “Sáb” [ “Sáb” ](Uma sequence de um único elemento pode serInicializada/atribuída sem os ‘[]’)

reverse dias [ “Ter”, “Seg”, “Dom” ][ 1, null, 2 ] [ 1, 2 ] (Nulos não são suportados)

Tabela 2. Sintaxes de uso de sequences.

Uma característica importante das sequen-ces é que elas não admitem aninhamento;qualquer tentativa de colocar uma sequence dentro de outra irá gerar uma sequence única com todos os elementos. Por exemplo, o resultado de [ dias, [“Qua, “Qui”] ] não é [ “Dom”, “Seg”, “Ter”, [“Qua, “Qui”] ], e sim [ “Dom”, “Seg”, “Ter”, “Qua, “Qui” ]. Esta transformação é conhecida como flattening (achatamento), e embora possa parecer uma limitação, é uma caracte-rística importante do estilo de programação da linguagem. Este estilo incentiva o uso de expressões “fluentes” – onde o output de cada expressão é usado como input da seguinte, algo similar ao uso de pipes em shell scripts. Para isso funcionar, é preciso que todas as operações utilizem uma estru-tura de dados padronizada; no Unix essa

estrutura é texto ASCII, em Java FX Script (e outras linguagens) é a lista ou sequence.

O leitor expert em outras linguagens que fazem uso

pesado de listas/sequences, como as da família LISP,

sabe que tais linguagens permitem o uso de estruturas

aninhadas. Mas JavaFX Script não pretende ser uma

linguagem de programação funcional sofisticada, para

quem curte técnicas do tipo “map/reduce”; ao invés

disso, foi feita a opção por sequences com flattening

automático, o que simplifica os cenários de uso mais

importantes para JavaFX, por exemplo a inicialização

de estruturas complexas como o Scene Graph.

Observe a tentativa da JavaFX Script de usar uma sintaxe SQL-like para a manipu-lação de dados: sintaxes como insert..into,delete..from, o in e o where do for.

java 69.indb 42 26/05/2009 16:37:15

Page 43: java 69 [Introdução Spring Security] [Lido]

Edição 69 Java Magazine 43

Num detalhe importante, o leitor pode estar confuso com minha afirmação que as sequences são imutáveis, seguida por uma tabela que indica várias sintaxes para sua alteração. Explico: todas essas sintaxes criam uma nova sequence. Por exemplo:

var dias = [ “Dom”, “Seg”, “Ter” ];var diasUteis = dias;delete “Dom” from diasUteis;println(diasUteis); // [“Seg”, “Ter” ]println(dias); // [ “Dom”, “Seg”, “Ter” ]

No exemplo acima, após a atribuição diasUteis = dias, ambas variáveis apontam para a mesma sequence. Mas em seguida, o delete cria uma nova sequence e a atribui à variável diasUteis; a sequence original con-tinua existindo pois ainda é referenciada por dias. Este truque sintático – operadores como delete e insert, que executam uma atribuição ‘escondida’ – mantêm a sintaxe familiar para quem não está acostumado ao estilo funcional (no qual nunca, ou raramente, se altera o valor de variáveis preexistentes). Para mais detalhes, veja o quadro “Imperativo ou Funcional?”.

DeclaraçõesNesta seção veremos como JavaFX Script

permite declarar variáveis e funções.Na Tabela 3, podemos ver que as variá-

veis de JavaFX podem ser declaradas com var ou def. A diferença é que o def é usado para constantes (similar às variáveis final do Java), enquanto var indica variáveis propria-mente ditas (i.e., cujo valor pode variar).

As declarações estáticas de tipo são op-cionais, mas isso não significa que JavaFX Script seja uma linguagem dinamicamente tipada. Ao contrário, JavaFX é tão estati-camente tipada quanto Java; a diferença é que contamos com inferência de tipos,ou seja, a capacidade do compilador de determinar automaticamente o tipo. No exemplo var x = 5, o tipo de x é estabelecido como Integer, pois este é o tipo do valor 5com o qual a variável é inicializada. No caso específico das declarações def, como o valor inicial é mandatório, a declaração de tipo jamais é necessária.

Também salta aos olhos que JavaFX Script utiliza o “estilo Pascal” de declara-ções de tipos, ou seja nome : Tipo ao invés de Tipo nome como em Java. Apesar de parecer

VARIÁVEIS E ATRIBUTOS

Expressão Significado

var x Ilegal

var x : Integer Declara variável mutável, de tipo Integer, inicializadacom o valor default para o seu tipo (no caso, 0)

var x = 5 Declara e inicializa variável mutável, de tipo Integervar x : Integer = 5 Declara e inicializa variável mutável, de tipo Integer

def x = 5 Declara e inicializa constante, de tipo Integerdef x : Declara e inicializa constante, de tipo Integer

def x Ilegal, valor é exigido

def x : Integer Ilegal, valor é exigido

for (d in dias) { d = “Domingo” } Ilegal: é proibido modificar “variáveis induzidas”,como a variável de iteração de um for

FUNÇÕES

Expressão Significado (a : Integer) : Integer

{ return a * 2; }Declara uma função com um parâmetro Integer e tipo de retorno também Integer

(a : Integer, b : Integer){ return a + b; }

Declara uma função com dois parâmetros Integer e tipo de retorno também Integer

(nome : String){ println(“Alo, {nome}”); }

Declara uma função com um parâmetro String e tipo de retorno Void

(nome){ println(“Alo, {nome}”); }…alo(“Osvaldo”);

Declara uma função com um parâmetro String e tipo de retorno Void

(Double) : Boolean Declara uma variável cujo tipo é uma função com um parâmetro Double e tipo de retorno Boolean

var f : functionfunction

}

Declara uma variável cujo tipo é uma função com um parâme-tro Double e tipo de retorno Boolean, e inicializa-a com uma função deste tipo

(a : Double) { return a >= 0;}

Declara uma variável cujo tipo é uma função com um parâme-tro Double e tipo de retorno Boolean, e inicializa-a com uma função deste tipo

function (a : Double) { a = 5 } Ilegal: é proibido modificar parâmetros

Tabela 3. Declarações de variáveis e funções.

uma diferença gratuita e desagradável de Java, você se acostumará e verá que exis-tem bons motivos para isso (o mesmo vale para Scala, que – não coincidentemente – também usa inferência de tipos).

A mesma sintaxe de declarações pode ser utilizada em três escopos distintos:

var x = 5;function x1 () { return x; } // Retorna 5class Y { var x = 6; function x2 () { return x; } // Retorna 6 function z () { var x = 7; def f = function x3 () { return x; } // Retorna 7 }}

JavaFX suporta variáveis e funções locais, de instância, e globais. Esta última opção parece ser uma novidade, mas de fato não é, pois ocupa o lugar dos static do Java. Se num arquivo Y.fx você tiver um elemento global x, este será acessível externamente com a sintaxe Y.x, ou seja, igual às statics.Em termos de compilação e desempenho, a equivalência também permanece: vari-áveis e funções globais são transformadas pelo javafxc em variáveis e métodos static.

A inferência de tipos também funciona para funções, especialmente o tipo de retorno: raramente é preciso especificá-lo explicitamente, pois ao encontrar por exemplo uma operação return a + b no

java 69.indb 43 26/05/2009 16:37:15

Page 44: java 69 [Introdução Spring Security] [Lido]

44 Java Magazine Edição 69

corpo da função, o javafxc determina que o tipo desta expressão é o tipo estático de retorno a função. Mas alguns programa-dores podem preferir especificar o tipo de retorno, para ter certeza que este será um tipo específico (neste caso, um return e onde e não possui exatamente o mesmo tipo declarado para retorno, sofrerá uma conversão implícita se possível).

O compilador javafxc irá transformar as funções em

métodos idênticos aos do Java, com uma “assinatura”

no bytecode que inclui os tipos dos parâmetros e do

retorno, sendo que esta assinatura influi na compi-

lação e na compatibilidade binária de outras classes

compiladas com invocações ao método (função) em

questão. Assim, as funções de JavaFX Script podem ser

também invocadas a partir de classes Java, de maneira

direta e tipicamente sem nenhum overhead.

Os tipos dos parâmetros, surpreenden-temente, também podem ser inferidos. Isso é possível se houver pelo menos uma invocação à função no mesmo script, ou em atribuições ou inicializações para uma propriedade tipada como função:

function teste (a, b) { a + b }println(teste(10, 15));

class A { var b : function (a:String); }A { b: function (x) { println(x.charAt(0)) } }

No primeiro exemplo, o compilador deter-mina que os parâmetros a e b de teste() são do tipo Number, devido à presença da invo-cação teste(10, 15). No segundo exemplo, ao compilar a última linha onde instanciamos um objeto do tipo A, a function (x) {...} não exige declarar que x é uma String pois esta função está sendo atribuída à propriedade A.b, e para esta atribuição ser válida, a função no lado direito deve ter a mesma assinatura da propriedade no lado esquerdo.

Visibilidade

JavaFX suporta um conjunto completo de modificadores de visibilidade, de fato, mais completo que Java. Veja a relação completa na Tabela 4. Mais explicações (sobre a necessidade dos novos níveis) na próxima seção. Mas antes de chegar lá, podemos destacar um fato interessante: JavaFX não possui um nível de visibilidade private. Você logo entenderá o motivo.

Propriedades

JavaFX Script utiliza o termo “proprie-dade” ao invés de atributo. Propriedades são atributos de classes, mas com alguns recursos adicionais em comparação com os atributos do Java.

A Tabela 5 resume a sintaxe, que complementamos com as seguintes explicações:

VISIBILIDADESignificado

Igual a Java, permite acesso a partir de qualquer código

Igual a Java, permite acesso para a mesma classe ou derivadas, e também outras classes do mesmo package

Igual ao package-private do Java (exceto por exigir uma palavra-chave: não é a visibilidade default!), permite acesso para classes do mesmo

(Somente para propriedades) Permite inicialização em cláusulas de construção do objeto; depois disso, comporta-se como script-private

(Somente para propriedades) Permite inicialização e também leitura de qualquer código, mas não permite outras alterações exceto para código do mesmo script

script-private Sem palavra-chave, é a default: permite acesso total para código do mesmo script (seja qual for a classe, ou mesmo código “global” do script). Comparando com Java, é um nível intermediário entre e package-private

Tabela 4.

PROPRIEDADESSignificado

nome String Assim como em Java, o modificador de visibilidade (caso exista) vem no início da declaração, antes do

String

if (notprintln(“Novo nome: {nome}”);

}

Trigger de alteração. Será invocado inclusive para a atribuição inicial à variável; se for necessário discriminar esta situação, basta usar

var nome : StringnomeVelho {

println(“Velho: {nomeVelho}, novo: {nome}”);}

Trigger de alteração, com cláusula de acesso ao valor anterior da propriedade

var projetos : Projeto[]pVelhos[i .. j] = pNovos {

println(“Alterando: {pVelhos[i..j]} para: {pNovos}”);}

Trigger de alteração, com cláusula de acesso ao valor anterior, para se-quence. Neste caso temos até quatro variáveis para controle da alteração:

é a parte da sequence que foi modificada, contém os novos elementos que substituíram aquela parte ( para um ).

var osvaldo = Pessoa { nome: “Osvaldo”, cargos: [ Cargo { titulo: “Editor” }, Cargo { titulo: “Desenvolvedor” } ]}

Instanciação e inicialização de objetos (ou árvores de objetos), através da enumeração de valores iniciais para suas propriedades públicas.É também a notação de objetos literais de JavaFX Script (não por acaso, idêntica à JSON de JavaScript tipado).

Tabela 5. Propriedades.

Não se usa getters ou setters. Proprie-dades são declaradas com visibilidade pública. Para propriedades que você não deseja que possam ser modificadas arbi-trariamente, basta usar os níveis public-init(equivalente a um atributo do Java que só pode ser inicializado por um construtor) ou public-read (equivalente a um atributo do Java que possui getter, mas não setter);

java 69.indb 44 26/05/2009 16:37:16

Page 45: java 69 [Introdução Spring Security] [Lido]

Edição 69 Java Magazine 45

Não há construtores. Objetos são instan-ciados com uma sintaxe de objetos literais;

Triggers. As propriedades podem possuir triggers, que são funções invo-cadas automaticamente quando o valor da função for modificado. Isso substitui a necessidade de setters para alterações não-triviais de propriedades;

Binding. O recurso de binding (ver seção Binding) permite manter diversas propriedades associadas entre si de for-ma automática.

Para quem vem de uma linguagem OO tradicional como C++ ou Java, poderão parecer “heréticas” idéias como não en-

capsular atributos com getters e setters, ou não dispor de um nível de visibilida-de private. Mas analisando a linguagem como um todo, podemos entender seu design. A soma de recursos como visi-bilidade mais refinada (especialmente public-init e public-read), instanciação “es-tilo JSON”, triggers e binding, substitui 99% das necessidades de getters, setters e construtores. Ou seja, seus atributos (opa, propriedades!) continuarão tão bem encapsulados quanto antes, só que com um código bem mais simples – e, de quebra, algumas novas facilidades.

Quanto à visibilidade private, esta não existe de fato nem em Java – um membro

private de uma classe pode ser acessado por suas classes aninhadas ou inner classes.Classes aninhadas/inner costumam ser fortemente acopladas à sua enclosing class,justificando o acesso privilegiado. Em Ja-vaFX a lógica é igual: todo o código contido por um script .fx é fortemente acoplado (se não for, divida-o em vários scripts). JavaFX só torna explícito e homogêneo um design que, em Java, é acidental e im-perfeito. Acidental, pois não era assim no Java 1.0 – mudou no 1.1 quando as classes aninhadas/inner foram criadas. Imperfei-to, pois Java permite definir várias classes no mesmo arquivo .java (desde que só uma seja pública), mas não há privilégios de

Se o leitor observar a com as estruturas

de controle de JavaFX e estiver perguntando

“onde está o switch?”, a resposta simples é: não

tem. Mas a resposta mais longa é... tem algo

parecido , ou poderá ter logo.

Muitos designers de linguagens OO apontam

que a estrutura de controle switch é anti-OO pois

muitas vezes pode ser substituída por polimorfis-

mo ou outras técnicas. Em JavaFX, tiveram a cora-

gem de deixar o switch de fora. Isso significa que

você tem que usar ou polirmorfismo, ou cascatas

de ifs, onde normalmente usaria um switch.

Mas esta parte do design da linguagem me

parece incipiente pois, para realmente não

sentirmos falta do switch, precisamos de outros

mecanismos (o polimorfismo nem sempre é

adequado). JavaFX já possui parte da solução

(funções de primeira ordem) – é melhor ilustrar

com um exemplo prático:

[ function() { println(“Case 0”); } function() { println(“Case 1”); } function() { println(“Case 2”); } function() { println(“Case 3”); }][valor]();

Ao invés de case, usamos uma sequence

contendo uma função com o código corres-

pondente para o case do seu índice. Ao invés

de switch(valor), usamos o valor para indexar a

sequence, obtendo e executando a função que

contém o código deste “caso”. Note que os “ca-

sos” poderiam ter parâmetros e retornar valores

(desde que todos tenham a mesma assinatura:

isso será verificado pelo compilador!), o que já

tornaria esta técnica mais poderosa que o switch/

case do Java.

Observe mais uma vez a inferência de tipos

de JavaFX: no exemplo, o tipo da sequence é

function() [].Digamos que você edite apenas

um dos “casos” e coloque um parâmetro Integer

na função; então o tipo inferido será o tipo mais

elementar compatível com todos os casos – no

caso, um tipo Function genérico (herdado por

todos os tipos de função). Mas se você utilizar

a sequence como no exemplo, indexando-a e

executando a invocação com (), o compilador

exige que todas as funções possuam assinatu-

ra compatível com a da invocação – no caso,

nenhum parâmetro – e reclamará de qualquer

“caso” que seja diferente disso.

O maior problema é que nem todos os switch/

case possuem um domínio de valores como

0, 1, 2..., que se prestem ao mapeamento para

índices de sequence. O ideal seria então usar

mapas (sequences associativas), o que permitiria

criar uma estrutura como [ “Ouros”: function() {

println(“Ouros”} ], etc.; isso também permitiria

o uso de objetos arbitrários, não só números,

como chave. Infelizmente JavaFX ainda não

possui nenhum suporte nativo a estruturas de

dado deste tipo – pode-se usar as do Java como

java.util.HashMap, mas isso não teria facilidades

como uma sintaxe especializada de inicialização

e indexação.

Uma versão futura da linguagem possuirá este

suporte a mapas, provavelmente a JavaFX 2.0

(ver JFXC-642 no JIRA). Mas também seria bom

permitir a declaração de funções triviais ainda

mais simples (sem o function()), e mesmo assim,

faltaria o default.

Há linguagens, como Smalltalk, que sempre

se viraram muito bem sem o switch. Na pior

hipótese você pode simplesmente usar ifs em

cascata, o que em JavaFX talvez não seja ruim,

lembrando que if é uma expressão e você pode

escrever código como:

def sobrenome = if (nome == “Osvaldo”) “Doederlein” else if (nome == “Eduardo”) “Spínola” else “Silva”;

…o que é mais enxuto que, com um switch,

ter que fazer uma atribuição separada para

sobrenome em cada case. (Para um exemplo

tão trivial o Java permitiria usar o ternário ?:,

mas não se os cases tivessem que executar

algum statement antes do valor retornado.)

Mas esta solução ainda incomoda um pouco:

esteticamente, o primeiro ”caso” (if) não tem

um cabeçalho idêntico aos demais (else if); e

a repetição de “nome ==” também me inco-

moda um pouco, ainda que seja mais legível e

genérica que os cases. Eficiência não é um pro-

blema pois o compilador poderia reconhecer

uma cascata de ifs com estrutura similar a um

switch, e gerar código idêntico (com bytecodes

tableswitch ou lookupswitch).

java 69.indb 45 26/05/2009 16:37:16

Page 46: java 69 [Introdução Spring Security] [Lido]

46 Java Magazine Edição 69

acesso a membros privados entre estas classes – embora o mesmo argumento de alto acoplamento seja válido.

Ilustrando de forma mais aplicada as sintaxes de propriedades e construção de objetos, apresento novamente o “Alô Mundo” da JavaFX:

Stage { title: “Aplicação Alô Mundo” width: 250 height: 80 scene: Scene { content: Text { font: Font { size: 24 } x: 10, y: 30 content: “Alô, JavaFX!” } } onClose: function() { FX.exit() }}

O código acima constrói a aplicação com-pleta (ok, faltando só as declarações package e import). Este código instancia (e retorna – ver seção Controle) um objeto Stage. Este objeto é inicializado com o valor 250 para a proprie-dade width, etc. No caso da propriedade scene,seu valor é um objeto Scene que é inicializado da mesma forma, idem para a propriedade content de Scene. Finalmente, a propriedade onClose tem o tipo function (): Void, sendo inicia-lizada com uma função deste tipo.

Teoricamente, você poderia fazer o mesmo em Java, com expressões new ani-nhadas. Mas há três problemas. Primeiro, os construtores do Java são rígidos – se um objeto com os atributos a, b, c possui apenas um construtor (a,b), inicializar ape-nas a exige passar explicitamente o valor default de b, e inicializar c exige invocar setC() após a construção (saindo além da inicialização hierárquica). O segundo problema é que os frameworks Java não costumam trabalhar com “atributos funcionais” como onClose, preferindo de-sign patterns como Template Method (um método onClose() que pode ser redefinido) ou Observer (um método como addCloseLis-tener()); ambos suportam uma expressão única de inicialização, mas ao custo de código bem mais confuso devido à hor-rível sintaxe das inner classes. Terceiro, a invocação de construtores não indica o nome dos argumentos, de forma que expressões de construção longas e/ou aninhadas tendem a ficar difíceis de ler se você não souber de cor qual argumento

que vai em cada posição (ou se isso não for evidente pelos valores passados).

Alguns frameworks Java modernos adotam o pat-

tern de “APIs fluentes” no qual métodos terminam com

um return this, o que permite encadear expressões

BINDINGDeclaração Significado

def x = bind y Sempre que o valor de y mudar, este mesmo valor será copiado para x (x é um alias para y)

def x = bind y + f(10) Sempre que o valor de y mudar, a expressão y + f(10) é reavaliada e o novo resultado atribuído a x. Note que f(10) não será invocada novamente – o valor retornado anteriormente será reutilizado

def x = bind y + f(z, 10) Dessa vez, como a invocação a f() tem um parâmetro alimentado por uma variável z; se esta variável mudar, f(z, 10) será reavaliada

bound function f (x : Double) { return x * y}def z = bind f(a)

Como f é declarada como uma bound function, o bind de z reexecutará f(a) sempre que qualquer variável utilizada por f() seja alterada. Isso inclui tanto os parâmetros (como a) quanto outras variáveis externas (atributos ou globais) como y

def iniciaisDias = bind for (d in dias) d.charAt(0)

Sempre que ocorrer uma modificação na sequence dias, o for será reexe-cutado somente para os elementos modificados, resultando em alterações também incrementais na sequence iniciaisDias

def posAtual = bind Point {

x: xAtual, y:yAtual

}

Se uma das variáveis xAtual ou yAtual mudar, será construído um novo objeto Point, que será atribuído a posAtual

def posAtual = Point {

bind x: xAtual, y:yAtual

}

Se a variável xAtual mudar, a propriedade posAtual.x será modificada (não será criado um novo objeto Point). Se yAtual for alterada nada acontecerá, pois não tem bind

def x = bind y with inverse Se y for alterada, seu valor é copiado para x.Mas se x sofrer uma atribuição, seu valor é copiado para yNota: with inverse não suporta expressões mais complexas

Tabela 6. Binding.

como: new X(a).setB(b).setC(c), etc. Um método

addXxxListener() também poderia seguir este

design. Mas o resultado, mais uma vez, é bem pouco

elegante. Na minha opinião, é uma tentativa pobre de

imitar a linguagem Smalltak, na qual o estilo “fluente”

é natural devido à sua sintaxe de mensagens (não há

OPERADORES ARITMÉTICOSOperador Significado

+ - * / ++ -- Igual a Java

+= -= *= /= Igual a Java: operadores com atribuição combinada

mod Resto de divisão, como o % do Java (não há equivalente a %=)

OPERADORES RELACIONAISOperador Significado

not Negação, como o ! do Java

or Disjunção, como o || do Java

and Conjunção, como o && do Java

== != <= >= < > Igual a Java

OUTROS OPERADORESOperador Significado

instanceof Igual a Java

obj as String Typecast: como (String)obj do Java

sizeof e Retorna o tamanho de uma expressão. Para uma sequence, é o seu número de elementos. Para objetos de outros tipos (ex.: Integer), é 0 se o objeto for null, 1 se não-nulo.

Tabela 7. Operadores.

java 69.indb 46 26/05/2009 16:37:16

Page 47: java 69 [Introdução Spring Security] [Lido]

Edição 69 Java Magazine 47

parâmetros posicionais) e ao fato de todos os métodos

retornarem this por default (não existe o tipo void).

E como, na definição do Java SE 7, os conservadores

venceram a briga e ficaremos sem closures, o Java

continua condenado a gambiarras pavorosas (ainda

que sejam melhor-que-nada) como “APIs fluentes”.

Por que tudo isso é importante – não é muito oba-oba em cima de uma economia de algumas linhas de código para iniciali-zar objetos complexos? Acontece que esta facilidade sintática possui outros “efeitos colaterais” positivos. Por exemplo, você pode usar a sintaxe de notação de objetos literais do JavaFX para muitas tarefas onde tipicamente usaria XML, resultando num código que é mais enxuto e legível, fácil de emitir e interpretar (como sabe qualquer programador JavaScript que prefere JSON a XML). Um exemplo concreto disso é o formato gráfico FXD (ver Edição 67), nada mais que código JavaFX com inicializações de classes gráficas. Outro exemplo é a cons-trução da árvore de componentes e eventos da GUI, ilustrada acima: este código, além de enxuto e legível, é ideal para manipulação de ferramentas. Por tudo isso, JavaFX dispensa a necessidade de linguagens de descrição de GUI como XAML (Silverlight), MXML (Flex), XUL (Mozilla), “layouts” do Android, etc. A falta de algo equivalente (uma DSL para GUI & gráficos) não é uma lacuna de JavaFX, pelo contrário, sua presença em plataformas competidoras revela inadequações das lin-guagens de programação principais destas plataformas. Na JavaFX, o FXD é inclusive bom o suficiente para substituir o formato SVG de gráficos vetoriais1.

Binding

Binding é uma das características mais “famosas” de JavaFX Script, pois além de ser um poderoso recurso de programação em geral, é uma peça essencial para os frameworks e o estilo de programação da plataforma JavaFX.

Se você (como eu) começou aprendendo sobre binding examinando os fontes de diversos demos que só utilizam as duas

DECISÃODeclaração Significado

if (1 != 0) thenprintln(“ok!”)

elseprintln(“pane na CPU!”)

Igual a Java, exceto que a palavra-chave then é suportada(porém, opcional)

var msg =

if (1 != 0) “ok” else “pane”Igual ao operador ternário ‘?:’ do Javamsg = “ok”

ITERAÇÃO / GENERATORSDeclaração Significado

while (x++ < y) println(x) Igual a Java. A expressão while tem tipo Void

for (d in dias) println(d) Igual ao for estendido do Java 5, só muda ‘:’ para ‘in’

var nums = for (n in [3, 2, 1]) n*2 Gera uma sequence com todos os valores “retornados”nums = [ 6, 4, 2 ]

for (n in nums where n >= 0)... Filtra a iteração, ignorando elementos que não satisfazem ao .Em Java, exigiria um contendo um

for (d in dias) println(indexof d) var retorna o número ordinal do elemento iterado (0, 1, 2, ...). Tecnicamente, é um operador de sequences, pois a iteração é sempre feita sobre sequences

for/while (..) { if (a) break else continue}

Como em Java, sendo que e têm tipo Não há "gotos disfarçados" label ou label

EXCEÇÕESDeclaração Significado

try, throw, catch, finally, throws Como em Java. As expressões e têm tipo

BLOCOSDeclaração Significado

{ fazAlgo() }

{ fazAlgo(); return }Igual a Java: bloco

{ fazAlgo(); return valor }

{ fazAlgo(); valor }

Igual a Java: bloco, retornando valor.Note que o é opcional

INVOCAÇÃODeclaração Significado

new Cliente(“Osvaldo”) Igual a Java: instancia objeto e invoca construtor

m(a, b)

obj.m(a, b)

Igual a Java: invocação de método, sendo o receiver default

Tabela 8. Estruturas de controle.

1 Isso obviamente não é devido somente à sintaxe de objetos literais, mas também ao poderoso framework de Scene Graph, que define entidades gráficas suficientemente ricas para ser equivalente ao metamodelo SVG.

variantes mais simples deste recurso (bind x = y e criação de objetos com binding igualmente simples em propriedades), poderá se surpreender com a Tabela 6, que mostra uma sofisticação extraordinária. Vamos demonstrar esta capacidade com um exemplo que explora uma das sintaxes complexas, combinado com triggers para logar o que acontece:

var dias = [ “Dom”, “Seg”, “Ter” ] on replace d[i..j] = nd { println(“{d[i..j]} = {nd}”) }

def iniciaisDias = bind for (d in dias) d.charAt(0);

dias[1..2] = [ “TER”, “QUA” ];

Executando o código acima, o output será o seguinte:

-> DomSegTer -> DSTSegTer -> TERQUADST -> DTTDTT -> DTQ

As duas primeiras linhas são efeito das atribuições dos valores iniciais a dias, e por conseqüência do binding, a iniciaisDias – pois a trigger é disparada inclusive para a atribuição inicial. (Note que ao exibir sequences com o recurso de mesclagem de strings, os elementos são concatenados.) Na terceira linha, que é o

java 69.indb 47 26/05/2009 16:37:17

Page 48: java 69 [Introdução Spring Security] [Lido]

48 Java Magazine Edição 69

que mais nos interessa, “SegTer -> TER-QUA” vemos que o binding de iniciaisDiasfoi acionado pela atribuição a dias; sendo que esta atribuição modificou apenas dois dos seus elementos. Na quarta e quinta linhas, vemos que o for (d in dias) é reexecutado somente para estes elemen-tos (dias[1..2]), e as alterações de iniciaisDiastambém são feitas de maneira incremen-tal: repare que são geradas duas altera-ções independentes para os elementos de índice 1 (“S” "T") e 2 ("T" "Q"), ao invés de uma alteração única que causaria um log "DST -> DTQ".

Podemos concluir várias coisas. Primeiro, como já disse, o binding do Java vai bem além daqueles casos simplórios que você viu em javafx.com/samples; é um recurso que pode ser explorado de inúmeras formas. Segundo, as capacidades das sequences do Java são ainda mais incrementadas pelo tratamento especial de outros recursos da linguagem, como triggers e binding – de uma forma geral, a linguagem tenta otimi-zar o esforço destas operações tornando-as o mais incrementais possíveis (se você tem uma sequence de 1000 elementos e altera apenas um elemento, isso não irá gerar

execuções de triggers ou bindings consi-derando todos os 1000 elementos).

Como nada é perfeito, um alerta: binding é pesado, especialmente devido às capacida-des de avaliação incremental de sequences e expressões complexas. Para cada variável sujeita a binding e cada expressão bind, o runtime é obrigado a manter na memória estruturas de dados relativamente gran-des. É por isso que você pode encontrar na internet algumas pessoas comentando que ficaram horrorizadas ao ver que uma variável Boolean ocupava 100 bytes ou mais. Use este recurso apenas quando necessário (especialmente na JavaFX Mobile).

OperadoresJá apresentamos alguns operadores da Ja-

vaFX especializados em sequences; veremos agora os operadores mais convencionais para manipulação de valores em geral.

A Tabela 7 revela algumas das minhas poucas discordâncias do design de JavaFX Script. Alguns operadores desviam de Java, a meu ver gratuitamente: por que, por exemplo, and ao invés de &&? O argu-mento é que operadores nomeados são mais “simples” que símbolos misteriosos

como &&, mas não engulo isso, lembran-do que linguagens RIA competidoras, como JavaScript e ActionScript, utilizam os operadores simbólicos tradicionais da família C. Os operadores simbólicos são mais legíveis pois se destacam de nomes de variáveis e funções; ao ler um código como aa || bb && cc, a distinção entre operadores/operandos é imediatamente clara, o que não ocorre para aa or bb and cc – que exige um “parsing mental” para reconhecer or e and como operadores e as demais palavras como identificadores de variáveis. Pior que isso, vejo algumas inconsistências: a exclamação ! foi substi-tuída por not como operador de negação, mas no operador diferente-de !=, conti-nuamos vendo a exclamação indicando negação. Mais: o ‘|’ de [a | a > 5] e o wherede for (a in b where a > 5) têm exatamente o mesmo significado... nada é perfeito, e na minha opinião, a sintaxe de operadores não-simbólicos é um lugar onde o design de JavaFX Script derrapou.

Outras divergências me parecem OK. O operador de typecast as é mais elegante que o do Java, pois sendo posfixado, é coerente com a ordem de avaliação, ex.: dVar * 2.0 as

Ao serem apresentados à JavaFX, muitos de-

senvolvedores têm a seguinte reação: aprovam

as funcionalidades, o framework, mas... isso

precisava de uma nova linguagem? Não daria

para suportar todos os recursos da JavaFX com

APIs orientadas à linguagem Java, ou talvez, uma

sintaxe “Java estendida” (mantendo compati-

bilidade retroativa) ao invés de inventar outra

linguagem separada?

A resposta curta: Sim, seria possível fazer

tudo com Java ou com uma extensão de Java...

porém, não seria uma boa idéia. Vamos explicar

os porquês – a “resposta longa”.

Produtividade Competitiva

Todas as plataformas RIA competidoras

utilizam alguma linguagem de programação

considerada de “alta produtividade” – pelo

menos segundo alguns critérios, como alta

densidade de código (mais funcionalidade com

menos linhas de código) e facilidade de proto-

tipação. As competidoras incluem JavaScript,

ActionScript, e linguagens XML como XAML e

MXML (para estas últimas, a vantagem é o uso

de ferramentas visuais).

JavaFX Script possui diversas características

de alta produtividade, como: inferência de

tipos, binding, sequences, inicialização decla-

rativa de estruturas hierárquicas de objetos,

sintaxes de alto nível para diversas necessida-

des de programação geral (desde o simples re-

laxamento na pontuação até o for “turbinado”),

e sintaxes especiais para algumas APIs.

Agilidade

Quando se fala em evolução da linguagem

Java, não podemos nos esquecer que a Sun não

é dona do Java. A especificação da linguagem,

bem como de todas APIs formais, é controlada

pelo Java Community Process (JCP). Embora a

Sun mantenha certas prerrogativas e um alto

grau de influência no JCP, isso não inclui carta

branca para fazer o que quiser com a platafor-

ma. Em especial, a evolução de especificações

preexistentes é sempre “torturante” pois

precisa levar em conta os interesses de diver-

sos players com voz no JCP, e possivelmente

grande investimento na tecnologia em ques-

tão. A quebra de compatibilidade retroativa é

virtualmente impossível.

A Sun chegou atrasada à briga do RIA. Se fos-

se seguir o caminho de estender a linguagem

Java (mesmo que isso fosse tecnicamente uma

boa idéia), ou criar a JavaFX sob os auspícios do

JCP, o lançamento da JavaFX 1.0 levaria pelo

menos o dobro do tempo, e a sua evolução até a

JavaFX 2.0 levaria 3-4 anos ao invés de um ano.

Isso liquidaria qualquer chance da JavaFX de

competir. Órgãos de padrões como o JCP são

excelentes para tecnologias já razoavelmente

maduras, mas são quase sempre péssimos para

criar coisas completamente novas – a inovação

raramente acontece em comitês.

java 69.indb 48 26/05/2009 16:37:17

Page 49: java 69 [Introdução Spring Security] [Lido]

Edição 69 Java Magazine 49

Integer, temos primeiro uma multiplicação entre variáveis Double, depois sua conversão para Integer, e observe também que não pre-cisamos usar parênteses – (dVar * 2.0) as Integer– pois a precedência do as é mais fraca (i.e., o typecast é avaliado depois da maioria dos outros operadores). E o sizeof é um conceito bastante interessante, coerente com o design orientado a expressões de JavaFX Script.

JavaFX não possui operadores de ma-nipulação de bits, como |, &, ^, ~, <<, >>e >>> do Java. O veterano de C/C++/Java dentro de mim também não gostou disso à primeira vista, mas acabei entendendo, pois estes operadores são de uso muito raro na enorme maioria das aplicações, e JavaFX Script é uma linguagem dedicada à camada de aplicação – não se supõe que alguém vá usá-la para “escovações de bits” como algoritmos de compressão ou criptografia. Principalmente lembrando que JavaFX é uma linguagem “parceira” de Java: é trivial invocar métodos de casses Java a partir de JavaFX e vice-versa, misturar ambas classes no mesmo projeto/IDE etc.

Além disso, JavaFX reserva os tokens << e >> para ou-

tro propósito: escape de literais externas. Por exemplo, se

você tiver que invocar um método bind() de uma classe

Java, pode fazê-lo com obj.<<bind>>(argumentos).

Sem o escape isso seria ilegal por que bind é uma

palavra-chave em JavaFX. Java 7 também terá um

mecanismo de escape similar,

ControleJavaFX Script, como qualquer linguagem

de programação, precisa de estruturas de controle como decisões e loops. Você poderia imaginar que pelo menos nesta área, a linguagem seria praticamente igual a Java. Engano, também aqui JavaFX apre-senta inovações poderosas, muito embora mantenha uma boa similaridade sintática com Java. Veja a Tabela 8.

Começaremos pela novidade concei-tual: JavaFX Script é uma linguagem orientada a expressões. Não existe a dualidade entre “statements” (que não geram nenhum valor, como o if do Java) e “expressões” (que retornam um valor, como x + y). Porém, nos casos onde não há nenhum valor que faça sentido associar

CONTROLEDeclaração Significado

Pessoa { var nome : String; var sobrenome : String; function nomeCompleto () { “{nome}{sobrenome}” }}

Declara uma classe

craque = Pessoa { nome: “Mané” sobrenome: “Garrincha”}

Instancia (aloca e inicializa) objeto de uma classe

Pessoa();craque.nome = “Mané”craque.sobrenome = “Garrincha”

Instancia (aloca e inicializa) objeto de uma classe(Classes JavaFX não podem ter construtores, mas a sintaxe

é suportada por questão de homogeneidade)

list java.util.ArrayList(100);

Instancia (aloca e inicializa) objeto de uma classeNeste caso é uma classe Java, que tem construtores comparâmetros, que podemos invocar de forma normal

IPessoa { abstract function nomeCompleto ();}

Classe abstrata pura (substitui interfaces)

A extends B, C, D {...} Herança

C init { println(“init ok!”); }

{ println(“postinit ok!”); }}

O bloco init é invocado após a alocação do objeto e a inicialização de todas as propriedades (inclusive de todas as classes-base). Os

são invocados depois disso, e se for o caso, depois que todos os init da hierarquia

var y = 0; function f () { y + y }}

}

Pode-se redefinir tanto funções quanto propriedades.No caso das propriedades, o serve apenas para modificar o valor default e/ou a cláusula

Tabela 9. Classes.

a determinada expressão, seu tipo é de-finido como Void.

Isso pode parecer malandragem, qual é a diferença entre um statement e uma ex-pressão Void? A maior diferença é técnica: a gramática da linguagem fica mais simples e unificada, o único efeito do Void é não per-mitir o uso de determinada expressão no lado direito de lugares que exijam um valor, como uma atribuição. Porém, podemos ver que a linguagem faz um grande esforço para que quase tudo seja uma expressão normal (não-Void). Notavelmente, as estru-turas de controle if e for são expressões que retornam valores. Vemos também que num bloco de código, o return é geralmente des-necessário para retornos com valor – basta terminar o bloco com um valor, como:

def function par (n : Number) { n mod 2 == 0 }

O bloco {} em si é uma expressão que possui valor, o qual pode ter tipo Void (se termina por um return sem valor ou outra expressão de tipo Void) ou outro tipo qualquer.

E não, a Tabela 8 não está incompleta: Veja o quadro “Cadê o switch?”.

Generators

Uma vantagem do design orientado a expressões de JavaFX, e seu uso de tipos de dados de alto nível como sequences e estruturas de controle avançadas como generators (for), é que o javafxc tem oportunidade para fazer otimizações importantes. Por exemplo, ao conhecer o for da JavaFX Script, você talvez tenha se horrorizado ao imaginar que este sempre irá gerar uma sequence com os valores produzidos por cada iteração

java 69.indb 49 26/05/2009 16:37:17

Page 50: java 69 [Introdução Spring Security] [Lido]

50 Java Magazine Edição 69

do loop. Mas não é exatamente assim; o compilador só faz isso se necessário. Assim, no código

def x = [1, 2, 3]def y = for (n in x) n * 2

…a sequence será de fato gerada, no caso [2, 4, 6], e atribuída a y. Porém, neste outro código:

def x = [1, 2, 3]for (n in x) n * 2

…o for só irá avaliar a expressão n * 2para cada n in x, mas nenhuma sequence será criada, pois o “valor de retorno” do

Na minha mania de aprender novas linguagens

mexendo em código dos outros, cheguei ao se-

guinte trecho de um demo (javafx.com/samples/

SmokeParticles/):

var parts: Particle[]; … function update() : Void { insert Particle { x : 84 y : 164 timer : 100 acc : bind acc vx : 0.3 * random.nextGaussian() vy : 0.3 * random.nextGaussian() - 1 } into parts; var i = sizeof parts - 1; while( i >= 0 ) { parts[i].update(); if( parts[i].isdead()) delete parts[i.intValue()]; i--; } }

Seu funcionamento é o seguinte: primeiro um

novo objeto Particle é criado e inserido ao final da

sequence parts; depois, um loop varre todos os

elementos que já estavam na sequence, invocan-

do os métodos update() e isdead(), e deletando

da sequence aqueles que estão “mortos”. Mas

achei esse código feio, confuso, então resolvi

reescrevê-lo:

function update() : Void { parts = [ for (p in parts where not p.update()) p Particle { x : 84 y : 164 timer : 100 acc : bind acc vx : 0.3 * random.nextGaussian() vy : 0.3 * random.nextGaussian() - 1 } ] }

Esta nova versão faz uma substituição única

da sequence antiga pela nova, a qual é criada

da seguinte forma: primeiro temos um for

que retorna todos os elementos da sequence

anterior que continuam vivos (juntei a fun-

cionalidade de isdead() a update()), e depois

temos a nova Particle. O ‘[...]’ mais externo serve

concatena a sequence gerada pelo for com o

objeto final, sendo que graças ao flattening

automático, o resultado será uma sequence

simples com todos estes elementos.

A nova versão é característica do estilo fun-

cional, evitando alterações repetitivas como

insert e delete. Sobrou uma alteração de

variável (parts = ...), mas é uma só, e mesmo

esta atribuição só restou por que eu não quis

reescrever o programa todo. É um código bem

mais “limpo”, menor (10 linhas ao invés de 14)

e mais simples (sua complexidade ciclomática

– quantidade e aninhamento de estruturas de

controle – é menor.)

Mais importante, a versão funcional é idên-

tica a uma descrição formal / matemática do

algoritmo, que podemos enunciar como: “o

novo conjunto de partículas é formado pelas

partículas preexistentes que após o update()

continuem vivas, mais uma partícula nova”. É

por isso que tanta gente gosta de programa-

ção funcional: é o estilo de programação que

permite traduzir, de forma direta, algoritmos

especificados de forma matematicamente

rigorosa (que é quase sempre a descrição mais

enxuta e elegante possível).

Bem, agora as más notícias. Testando meu

novo código, este funcionou, mas com um

desempenho muito pior. O problema é que

a sequence parts é amarrada, via binding, ao

scene graph da animação do programa; porém,

o binding de sequences não é otimizado para o

cenário de substituição total de uma sequence

(com uma atribuição explícita), apesar de ser

otimizado para manipulações pontuais como

insert e delete. A otimização em questão evita

que o scene graph inteiro seja reconstruído

em cada frame da animação, o que resulta em

péssimo desempenho. Ou seja, não se trata

de um bug/limitação de desempenho das se-

quences propriamente ditas, mas somente da

combinação entre sequences e binding, ou

talvez, do runtime do scene graph. Registrei um

novo bug descrevendo o problema (javafx-jira.

kenai.com/browse/JFXC-2911). É o tipo de coisa

que, infelizmente, podemos esperar de um

software complexo como a JavaFX que ainda

é praticamente recém-lançado no momento

em que escrevo. Mas não tira o mérito do

estilo de programação funcional ou do design

de sequences (o JIRA da JavaFX registra uma

grande quantidade de bugs similares, a maioria

corrigidos antes mesmo do release 1.0 – mas o

trabalho obviamente ainda não terminou)

for não está sendo utilizado de qualquer forma (como termo de outra expressão, lado-direito de atribuição, etc.).

ClassesJavaFX é uma linguagem OO baseada em

classes, com sintaxe básica parecida com Java, mas com pelo menos um grande desvio do design de Java.

A Tabela 9 resume a sintaxe das classes de JavaFX. Não existem interfaces, apenas clas-ses, e a herança múltipla é suportada para tudo (funções abstratas e concretas, e até mesmo propriedades). Classes da JavaFX po-dem inclusive herdar qualquer coisa de Java

(tanto classes quanto interfaces). Ou seja, JavaFX Script unifica nossas class e interfacenuma única entidade, também não exigindo distinguir entre extends e implements.

Como JavaFX faz isso? Se você observar os arquivos gerados pelo javafxc, verá que uma classe C da JavaFX gera um par de .class, que se você descompilar gerando arquivos .java (ou examinar com o javap), verá que correspondem a uma interface C.Intf e uma classe C que implementa esta interface. Junto com alguns outros truques de compilação, isso permite integrar o paradigma de herança múltipla genera-lizada da JavaFX Script ao modelo OO

java 69.indb 50 26/05/2009 16:37:18

Page 51: java 69 [Introdução Spring Security] [Lido]

Edição 69 Java Magazine 51

do bytecode / JVM, que suporta herança múltipla apenas para interfaces com mé-todos abstratos.

ConclusõesEste artigo encerra uma primeira “trilogia”

de JavaFX, na qual cobrimos os aspectos principais desta nova plataforma: tecnologia RIA, mobilidade, linguagem de programa-ção, pontos principais do framework. A partir deste ponto, minha expectativa é que um leitor que sabe programar Java e tem in-teresse pela plataforma JavaFX possa andar com seus próprios pés, chegando ao ponto de desenvolver aplicações RIA sofisticadas para desktop e dispositivos móveis.

Há duas partes da JavaFX que cobrimos de forma superficial: os recursos de mídia (ver Edição 67) e as APIs javafx.* (ver Edição 68). Estes temas renderiam, seguramente, pelo menos mais dois capítulos da série.

Mesmo na linguagem JavaFX Script, coberta neste artigo, existem tópicos específicos que poderíamos explorar, como a integração com Java, ou o desempenho.

Mas preferi parar por aqui, por três mo-tivos. Primeiro, a plataforma JavaFX ainda é muito recente e ainda é difícil avaliar o interesse dos leitores por uma cobertura tão contínua e abrangente. Segundo, o mundo não parou por causa da JavaFX, e há outros temas que pretendo cobrir nas próximas edições. Terceiro, a JavaFX ainda está em rápida evolução: no caso específico dos frameworks, não vou gastar nosso tempo (meu e dos leitores) com um “artigão” sobre os frameworks da JavaFX 1.1, quando sei que já em junho deste ano (quando nossa próxima Edição já estaria nas bancas) a Sun terá lançado a JavaFX 1.5, com muitas novidades especialmente nas APIs. Resumindo, espero que o leitor

Osvaldo Pinali Doederlein [email protected]É Mestre em Engenharia de

Software Orientado a Objetos,

membro individual do Java Community

Process e trabalha na Visionnaire Virtus

como arquiteto e desenvolvedor.

Dê seu feedback sobre esta edição!

A Java Magazine tem que ser feita aoseu gosto. Para isso, precisamos sabero que você, leitor, acha da revista!

Dê seu voto sobre este artigo, através do link:

www.devmedia.com.br/javamagazine/feedback

seu Feedback

sob

reeeestaedição

tenha apreciado estes primeiros artigos, tanto quanto eu apreciei escrevê-los... che-gou a hora de fazer uma pausa, mas com planos de voltar à JavaFX daqui a algumas edições, com as baterias recarregadas.

java 69.indb 51 26/05/2009 16:37:18

Page 52: java 69 [Introdução Spring Security] [Lido]

SEÇÃO JAVA: NESTA SEÇÃO VOCÊ ENCONTRA ARTIGOS INTERMEDIÁRIOS E AVANÇADOS SOBRE JAVA

52 Java Magazine Edição 69

De que se trata o artigo:

O artigo aborda o resultado da JSR-310, a JSR que está definindo a nova API de data e hora que será

incorporada na plataforma Java. A arquitetura e as principais classes e interfaces da API são discutidas

e exemplificadas. Além disso, são abordadas as lacunas presentes nas classes atuais (Date e Calendar) e

como a javax.time endereça tais problemas.

Para que serve:

Apresentar a nova API de datas e horas que será incorporada na plataforma Java, provendo discussões

sobre a sua arquitetura e exemplos de uso da API, além de comparações com as classes atuais.

Em que situação o tema é útil:

O tema é importante para qualquer um que deseje estar atualizado sobre as novas tendências da pla-

taforma Java. A manipulação de datas e horas é peça-chave em qualquer implementação e a criação de

uma nova API tende a facilitar muito a vida do desenvolvedor.

Novos tempos: javax.time:

O artigo aborda a nova API para representação de datas e horas da plataforma Java e como ela facilita a

vida do desenvolvedor Java, corrigindo bugs e endereçando problemas das classes atuais Date e Calendar.

A nova API possui representações distintas para datas que serão utilizadas para cálculos computacionais

e datas que serão utilizadas por seres humanos. Além disso, temos representações padrão para tipos de

dados que atualmente precisamos criar como durações, períodos e intervalos.

1 A nova especificação para representação de datas e horas dentro da plataforma Java, denominada javax.time neste artigo, está sendo criada pela JSR 310. O link para acesso à JSR pode ser obtido na seção de Links.

Neste artigo conheceremos a nova API de data e hora que está sendo elaborada para a plataforma Java

SE 7. O foco da nova API é resolver vários problemas que afetam os desenvolvedores Java há anos, presentes nas classes java.util.Date e java.util.Calendar.

Por que uma nova API?A arquitetura elaborada para as classes Date

e Calendar, ambas do pacote java.util é bastante questionável. Veremos algumas dessas de-cisões arquiteturais dúbias, além de “bugs” da API atual, no decorrer do artigo.

Outro grande problema é a falta de tipos para representar unidades comuns no dia-a-dia de qualquer desenvolvedor como, por exemplo, períodos, instantes, durações, entre outros. Sem classes que representem essas unidades do “mundo real”, é necessária a criação de soluções paliativas por conta e risco dos desenvol-vedores. Isso resulta em mais codificação e código legado para manutenção.

Esses pontos claramente abrem espaço a uma nova abordagem para o tratamento de datas e horas dentro da plataforma Java.

Alguns dos problemas apresentados

por Date e Calendar

Um dos principais problemas das classes atuais é a inconsistência. A classe java.util.Date não representa uma data, mas sim um instante na linha do tempo. Desta forma, não temos como representar somente uma data ou somente o tempo. Outro exemplo de in-consistência é o fato da classe Date utilizar anos com base em 1900, enquanto a Calendarrequerer os anos completos, incluindo o século. O código apresentado a seguir, apesar do uso de um construtor descon-tinuado (deprecated), ilustra a criação de uma data cujo ano será 3909, ao contrário do que parece ao ler o código.

Date date = new Date(2009, 2, 1);

O início dos meses em 0 (Zero) na classe Calendar também é algo que tem atrapalhado a vida dos desenvolvedores Java de forma considerável. Por exemplo, para criar uma instância de Calendar que represente a data 01/01/2009, temos que escrever o seguinte código:

Calendar calendar = new GregorianCalendar(2009, 0, 1);

Além disso, temos uma série de outros problemas arquiteturais ou de imple-mentação:

Os objetos são mutáveis, inseguros em ambiente multi-thread, requerendo sincronização;

Não há como formatar uma instância de Ca-lendar usando as classes do pacote java.text;

Não existe opção para representar períodos ou durações de forma padro-nizada;

As APIs atuais exigem muito código para tarefas rotineiras de manipulação de datas e horas. Sem mencionar ainda que muitas dessas “tarefas rotineiras” constituem casos de uso comuns e poderiam ser implementados pelas próprias APIs.

Esses são apenas alguns dos proble-mas que a JSR 3101 irá resolver. Os já velhos conhecidos problemas devido às

java 69.indb 52 26/05/2009 16:37:19

Page 53: java 69 [Introdução Spring Security] [Lido]

DANIEL CICERO AMADEI E MICHAEL NASCIMENTO SANTOS

alterações no horário de verão também estão sendo endereçados. Além de tudo isso, você verá que a API é muito mais intuitiva e irá lhe poupar muitas e muitas linhas de codificação.

Princípios de Design da JSR 310A JSR 310 tem sido elaborada com alguns

princípios para facilitar seu uso e entendi-mento e tornar seu código mais robusto e de fácil leitura.

Baseada em padrões

A nova API está sendo construída to-talmente alinhada com o ISO-8601, um padrão internacional para representação de datas e horas.

Imutável

Os principais objetos da nova API serão imutáveis. Não será possível alterá-los após a construção. Também serão thread-safe, podendo até mesmo ser singletons.

A seguir, um primeiro exemplo, da cria-ção de uma data (sem a hora!):

LocalDate date = LocalDate.date(2009, 1, 1);

Nesse caso, criamos uma data com a classe javax.time.calendar.LocalDate. Essa clas-se representa uma data sem fuso horário (time zone2) no padrão ISO-8601, resultan-do em 2009-01-01. Caso desejemos alterar o ano dessa data, por exemplo, para 2010 não iremos utilizar um método set(). Neste caso, devemos utilizar um método with(),que cria uma nova instância da classe com o ano desejado. O código ficaria conforme apresentado a seguir:

date = date.withYear(2010);

Edição 69 Java Magazine 53

2 Utilizaremos os termos em inglês para a zona de fuso horário, time zone e fuso horário como offset, como veremos no decorrer de todo o artigo para que não precisemos usar os termos em português, muito mais incomuns até mesmo aqui no Brasil.

Repare na atribuição ao objeto date com o resultado da invocação do método. Isso é necessário, pois é criado um novo objeto, mantendo o original inalterado, pois os objetos envolvidos são imutáveis.

Interfaces Fluentes

As classes e interfaces seguem o padrão de fluência para permitir uma melhor legibilidade do código. Isso transforma as invocações a mais do que um método em sentenças de fácil leitura. O código apresentado a seguir, além do ano, altera o mês e o dia.

date = date.withYear(2010).withMonthOfYear(3). withDayOfMonth(2);

Clareza

Os métodos são bem definidos e indicam claramente seu propósito. Por exemplo, para subtrair dois anos de uma data qual-quer, utilizamos o seguinte código:

date = date.withYear(2010).withMonthOfYear(3). withDayOfMonth(2); date = date.minusYears(2);

Isso irá resultar na data 2008-03-02. Mui-to mais claro do que o método roll(int field, int amount) da classe Calendar.

Extensível

Através de pontos de extensão, utilizan-do conceitos do design pattern Strategy,é possível controlar e customizar como a API se comporta em relação às datas e horas. Mesmo assim, não é necessário ser um especialista para usar a API. São fornecidas implementações padrão para a maioria dos cenários.

Um exemplo desses “ganchos” para ex-tensibilidade é a interface javax.time.calendar.DateAdjuster, capaz de realizar ajustes em uma data de forma padronizada. Você simplesmente implementa essa interface e

a utiliza para ajustar suas datas de forma padronizada e bem definida.

Além disso, a javax.time traz consigo uma classe utilitária, a javax.time.calendar.DateAd-justers, contendo implementações dos casos de uso mais comuns para o ajuste de datas. Essas implementações devem satisfazer a maioria das necessidades de desenvolvi-mento. O código apresentado a seguir ilustra o ajuste sendo realizado em uma data:

LocalDate date = Clock.systemDefaultZone().today();date = date.with(DateAdjusters.next(DayOfWeek.MONDAY));

O código que apresentamos, além do ajuste da data, apresenta uma nova classe: javax.time.calendar.Clock. Essa classe é um fa-çade para o acesso à data e hora correntes. O método today(), que invocamos na classe Clock, retorna a data corrente como uma instância de LocalDate.

Voltando a falar sobre o ajuste da data, ele ocorre na invocação ao método with(). Infor-mamos DateAdjusters.next(DayOfWeek.MONDAY) como parâmetro do método. O objeto re-tornado pelo método next() é responsável

java 69.indb 53 26/05/2009 16:37:21

Page 54: java 69 [Introdução Spring Security] [Lido]

54 Java Magazine Edição 69

por ajustar a data para a segunda-feira subsequente à data informada. Avaliando as datas, caso executemos tal código no dia 05/02/2009, após o ajuste, a nova data (lembre-se da imutabilidade!) será dia 09/02/2009.

Ainda no âmbito dos Adjusters, outro exemplo muito interessante de sua aplica-bilidade seria o ajuste das datas para dias úteis. Você pode, ainda, implementar seu próprio adjuster – digamos, para saltar fe-riados obtidos de um cadastro de feriados do seu sistema.

Duas escalas para lidar com tempo

A javax.time apresenta duas formas dis-tintas para lidar com o tempo. Uma escala voltada para máquinas, denominada Con-tinuous e a outra com foco em datas para seres humanos, denominada Human.

ContinuousEssa abordagem da javax.time é voltada para

máquinas e representa o tempo na forma de um número incremental, sem muito signifi-cado para seres humanos, porém com gran-de valor para uso em processamentos que requerem cálculos envolvendo timestamps.

Instant

A classe javax.time.Instant representa um ponto instantâneo na linha do tempo, um

instante de tempo, conhecido também como timestamp. Possui precisão de nanos-segundos e 96 bits para armazenamento. Através dessa abordagem, é possível arma-zenar até algumas centenas de vezes uma data equivalente ao tempo de existência do universo. (Para os curiosos, o universo tem em torno de 13,8 bilhões de anos.) A seguir, um exemplo onde validamos se um instante é superior a outro utilizando o método isAfter().

Instant instante1 = Clock.systemDefaultZone().instant(); //qualquer código aqui

Instant instante2 = Clock.systemDefaultZone().instant();boolean avaliacao = instante1.isAfter(instante2);

Duration

A classe javax.time.Duration representa uma duração de tempo. Dentro da javax.time, ela representa a duração entre dois instantes. O instante inicial que forma uma instância de Duration é inclusivo e o final é exclusivo. Apesar de armazenar dados provenientes de lá, a classe Durationé desconectada e independente da linha do tempo. O código apresentado a seguir ilustra o uso da classe Duration:

Instant agora = Clock.systemDefaultZone().instant();Instant umMinutoMais = agora.plusSeconds(60);

Duration duration = Duration.durationBetween(agora, umMinutoMais);System.out.println(duration);

No trecho de código apresentado, vemos primeiramente a criação de dois instantes. O primeiro representa o momento exato da execução, enquanto que o segundo derivamos a partir do primeiro com a soma de 60 segundos. Repare no método plusSeconds(). Ele é conciso, bem definido e indica exatamente seu propósito e a unidade manipulada. Após a criação dos instantes, criamos uma duração entre eles, que deverá conter exatamente 60 segun-dos. Ao imprimir a duração no console,

3 Até a finalização deste artigo, a classe InstantInterval ainda não estava finalizada e funcional na implementação de referência da javax.time e o código apresentado como exemplo ainda não estava funcionando corretamente.

temos a impressão da duração utilizando o padrão ISO-8601.

InstantInterval

A classe javax.time.InstantInterval represen-ta um intervalo de instantes na linha do tempo. A classe pode possuir intervalos inclusivos, exclusivos ou algum dos inter-valos pode não estar associado, isso quer dizer que podemos criar o intervalo com apenas o instante de início e posteriormen-te associar o instante final.

O código apresentado3 a seguir ilustra a criação de um intervalo a partir de dois instantes e a posterior verificação se um terceiro intervalo está contido entre eles:

Instant agora = Clock.systemDefaultZone().instant();Instant umMinutoMais = agora.plusSeconds(60);

InstantInterval intervalo = InstantInterval. intervalBetween(agora, umMinutoMais);boolean contido = intervalo.contains(Clock. systemDefaultZone().instant());

No exemplo, por utilizarmos o método “padrão”, o intervalo inicial é inclusivo e o final é exclusivo. Existe outro método que recebe valores booleanos indicando se desejamos que cada um dos intervalos seja inclusivo (true) ou exclusivo (false). Além disso, podemos construir a instância de InstantInterval a partir dos métodos “buil-der”: intervalFrom() e intervalTo().

HumanEssa abordagem da javax.time é voltada

para seres humanos. Ela representa os valores de datas e horas utilizando campos com classes específicas para representar cada um dos dados do calendário: ano, mês, dia, hora, minuto e segundo. Além desses campos mais comuns, temos algu-mas outras classes ou enumerações para representar, por exemplo, o dia do ano, a semana do ano, os nanossegundos de cada segundo, entre outras.

Através da abordagem para seres huma-nos, temos formas (classes!) para representar datas e horas, datas sem hora, horas sem data, offsets e time zones.

java 69.indb 54 26/05/2009 16:37:23

Page 55: java 69 [Introdução Spring Security] [Lido]

Edição 69 Java Magazine 55

Datas e Horas locais (sem time zone ou offset)

Os tipos mais simples presentes dentro da javax.time são os tipos chamados de “locais”. Esses tipos podem representar data ou hora de forma isolada ou as duas em conjunto. São chamadas de locais por não estarem associados a um offset ou time zone.

LocalDate

A primeira classe que mereceria nossa atenção seria a javax.time.calendar.LocalDate.Como já estamos cansados de ver exem-plos envolvendo essa classe, pois é a que estamos acompanhando no decorrer do artigo, veremos algo a mais.

A representação dos campos de datas e horas dentro das classes é efetuada através de classes com este propósito. Com isso, essas classes contém métodos implemen-tando ações comuns, requeridas de cada um desses campos que compõem nossas datas e horas. A javax.time utiliza como pa-drão os métodos get() retornando valores numéricos para tais campos, por exemplo, getYear() retorna o ano como um inteiro e os métodos to() retornam as classes específi-cas, no caso do ano, seria a classe javax.time.calendar.field.Year. O exemplo apresentado a seguir ilustra o uso do método toYear().

LocalDate hoje = Clock.systemDefaultZone().today();Year ano = hoje.toYear();boolean bissexto = ano.isLeap();

No exemplo, obtemos o ano e, a partir do objeto criado, verificamos se ele é bissexto. Repare como isso seria trabalhoso caso o ano fosse representado somente pelo tipo primitivo (int). Teríamos que fazer esse cál-culo manualmente, cada um em seu projeto, testar esse código e mantê-lo.

No exemplo apresentado a seguir, temos a obtenção do mês, representado pela enu-meração javax.time.calendar.field.MonthOfYear e, a partir dela, obtemos o último dia do mês representado pela classe javax.time.calendar.field.DayOfMonth.

LocalDate hoje = Clock.systemDefaultZone().today(); MonthOfYear mes = hoje.toMonthOfYear(); DayOfMonth ultimoDiaMes = mes.getLastDayOfMonth (hoje.toYear());

Vemos aqui também, com a obtenção do último dia do mês, o grande valor no uso de classes específicas em comparação com tipos primitivos. O cálculo do último

dia do mês é resolvido automaticamente pela API, poupando você, desenvolvedor, desse (grande) trabalho.

LocalTime

A classe javax.time.calendar.LocalTime repre-senta uma hora sem time zone ou offset. O trecho de código apresentado a seguir imprime a hora corrente e, posteriormen-te, subtrai uma hora e imprime o valor atualizado.

LocalTime agora = Clock.systemDefaultZone().currentTime();System.out.println(agora);

agora = agora.minusHours(1);System.out.println(agora);

LocalDateTime

A classe javax.time.calendar.LocalDateTime re-presenta uma data e hora sem time zone ou offset. O trecho de exemplo apresentado a seguir imprime a hora corrente e posterior-mente subtrai 36 horas e imprime o valor atualizado.

LocalDateTime agora = Clock.systemDefaultZone(). currentDateTime();System.out.println(agora);

agora = agora.minusHours(36);System.out.println(agora);

No exemplo, caso a primeira data e hora fosse representada por “2009-02-07T11:50:08.093”, após a subtração de 36 horas, teríamos “2009-02-05T23:50:08.093”. Repare que o cálculo ocorreu corretamente e alterou até mesmo a data.

Datas e Horas com offsetAs datas e horas com offset representam

um valor relativo ao UTC (Coordinated Universal Time ou Tempo Universal Coor-denado). Esses valores relativos, ou offsets, estão geralmente casados com as áreas de fuso horário (time zones), porém a javax.time separa os dois conceitos: offsets e time zones em classes distintas. O objetivo dessa separação é tratar trocas de offset por uma mesma time zone devido a horários de in-verno ou verão.

OffsetDate

A classe javax.time.calendar.OffsetDate repre-senta uma data com um offset em relação ao UTC. Por exemplo, ao criar um objeto

OffsetDate aqui no Brasil, na região que segue o horário de Brasília, temos como offset o valor -03h00min, ou seja, se em Brasília são 16h, o horário UTC estará marcando 13h.

O trecho de código apresentado a seguir ilustra a obtenção da data atual consideran-do o offset:

OffsetDate hoje = Clock.systemDefaultZone().offsetDateTime(). toOffsetDate();

Caso esteja sob o offset de Brasília, ao imprimir o objeto, a string “2009-02-07-03:00” teria sido impressa no console, seguindo o padrão ISO-8601 para datas e horas com offset.

OffsetTime

A classe javax.time.calendar.OffsetTime repre-senta um horário com um offset em relação ao UTC, seguindo o mesmo padrão da classe OffsetDate.

O trecho de código apresentado a seguir ilustra a obtenção do horário atual considerando o offset. Após isso, a criação de uma nova instância de OffsetTime contendo o mesmo horário, porém com o offset encontrado no Japão, que é +09h00min. Após isso, fazemos uma comparação dos dois horários com o intuito de ilustrar que a comparação levará em conta o offset.

OffsetTime hojeBrasil = Clock.systemDefaultZone().offsetDateTime().toOffsetTime();

OffsetTime hojeJapao = hojeBrasil.withOffset(ZoneOffset. zoneOffset(9));boolean horarioJapaoPosterior = hojeJapao.isAfter(hojeBrasil);

Após a execução do código apresentado, a variável horarioJapaoPosterior irá armazenar o valor true indicando que a hora no Japão é posterior.

OffsetDateTime

A classe javax.time.calendar.OffsetDateTimerepresenta uma data e um horário com um

N o t a d o D e v M a n

Thread-safe: Thread-safe ou, melhor dizendo, thread-safety é o conceito que usamos para nomear a situação em que o acesso de múltiplas threads a um elemento no mesmo momento não apresenta resultados inconsistentes, sem que uma thread tenha interferência sobre os dados manipulados por outra thread.

java 69.indb 55 26/05/2009 16:37:24

Page 56: java 69 [Introdução Spring Security] [Lido]

56 Java Magazine Edição 69

offset em relação ao UTC, seguindo o padrão dos dois exemplos vistos até o momento. O código a seguir ilustra a obtenção de uma OffsetDateTime.

OffsetDateTime hojeBrasil = Clock.systemDefaultZone(). offsetDateTime();

Ao imprimir essa variável no console, temos uma string representando a data, horário e o offset seguindo o padrão ISO: “2009-02-09T23:20:54.171-03:00”.

Time ZonesAlém de objetos capazes de armazenar

o offset, temos a classe javax.time.calendar.ZonedDateTime que armazena também o time zone. O time zone é representado pela classe javax.time.calendar.TimeZone que tem o propósito de tratar regras e exceções das alterações nos offsets das regiões mundiais. Essas altera-ções geralmente se devem a mudanças no horário de verão ou inverno.

Dentro da javax.time, é possível instanciar a classe TimeZone a partir de um identificador da base de time zones zoneinfo4 ou a partir do offset em relação à UTC.

O código apresentado a seguir ilustra a obtenção de duas instâncias de ZonedDateTime,a primeira com o time zone padrão da JVM, configurado como “América/Sao_Paulo” e o segundo forçando o uso do time zone de Paris.

ZonedDateTime agora = Clock.systemDefaultZone().zonedDateTime();System.out.println(agora);

TimeZone timeZone = TimeZone.timeZone(“Europe/Paris”);agora = Clock.system(timeZone).zonedDateTime();System.out.println(agora);

Ao executar o código apresentado, as da-tas e horas correspondentes ao time zone informado são impressas no console:

2009-02-09T23:37:18.968-03:00 UTC-03:002009-02-10T03:37:18.968+01:00 Europe/Paris

Repare que a primeira string impressa apresenta o time zone como UTC-03:00, isso por que não há um identificador correspondente para este time zone, ao

contrário do que ocorreu com o time zone de Paris, que criamos a partir do identi-ficador, que é apresentado na impressão do objeto.

Uma forma equivalente de obter a ins-tância de ZonedDateTime à que utilizamos é a apresentada a seguir, uma vez que o time zone de Paris corresponde ao offset de uma hora em relação ao UTC:

ZonedDateTime agora = Clock.systemDefaultZone(). zonedDateTime(); System.out.println(agora);

TimeZone timeZone = TimeZone.timeZone(ZoneOffset. zoneOffset(1)); agora = Clock.system(timeZone).zonedDateTime(); System.out.println(agora);

Matchers e ResolversComo já dissemos, a javax.time recorre a

conceitos do design pattern Strategy para que você possa customizar pontos de seu comportamento. Um exemplo pelo qual já passamos foi o dos Adjusters que permitem a realização de ajustes em datas e horas de forma bastante flexível.

Além dos Adjusters, a javax.time nos provê o conceito de Matchers e Resolvers, que vere-mos agora.

Matchers

Os Matchers possuem a responsabilidade de realizar consultas em datas e horas de forma muito simples e flexível. Eles reduzem drasticamente a quantidade de código e a lógica empregada neste tipo de operação.

O código apresentado a seguir ilustra a consulta à data (e hora) atual. Nesse caso consultamos se o ano é 2009, valorizando uma variável booleana denominada ano2009.Como estamos realmente em 2009, essa variável será valorizada com true.

LocalDateTime agora = Clock.systemDefaultZone().dateTime();boolean ano2009 = agora.matches(Year.isoYear(2009));

A consulta envolvendo o horário é prati-camente idêntica, conforme pode ser visto a seguir:

LocalDateTime agora = Clock.systemDefaultZone().dateTime(); boolean vinteUmaHoras = agora.matches(HourOfDay. hourOfDay(21));

É possível realizar tais operações, pois cada uma dessas classes (Year, HourOfDay

e as outras classes representando os elementos do calendário) implementa as interfaces necessárias para executar o método matches().

A interface que representa o Matcherpara a consulta em datas é a javax.time.calendar.DateMatcher, que possui um úni-co método boolean matchesDate(LocalDate input). Já a interface para a consulta em horários é a javax.time.calendar.TimeMatchere ela segue o mesmo padrão da outra que vimos, possuindo um único método boolean matchesTime(LocalTime time).

Essas interfaces estão disponíveis para você, desenvolvedor, implementar sua própria estratégia de consulta nas datas ou nos horários. Com isso, você garante que terá essa lógica implementada em um objeto coeso e reutilizável.

A Listagem 1 apresenta um exemplo de implementação de DateMatcher para verificar se a data possui um dia ímpar ou não.

A classe javax.time.calendar.DateMatcherspossui alguns matchers pré-configurados para você utilizar. Entre os matchers que já vêm por padrão temos, por exemplo, um para verificar se estamos durante a semana ou em um final de semana, se é o primeiro ou último dia do mês, além de alguns outros.

O código apresentado a seguir ilustra o uso da classe DateMatchers para a veri-ficação se a data corrente é um final de semana.

LocalDateTime agora = Clock.systemDefaultZone().dateTime(); boolean finalDeSemana = agora.matches(DateMatchers. weekendDay());

Como visto, a classe DateMatcher pode nos auxiliar com a verificação de datas e nos auxiliar muito em tarefas do mundo real como, por exemplo, verificar se de-terminada data está dentro do domingo de páscoa ou na sexta-feira santa.

Resolvers

Assim como os matchers, os Resolverssão pontos de extensibilidade disponí-veis na javax.time. Através deles você pode indicar como deseja que uma data invá-lida seja tratada, por exemplo, ao criar uma data no dia 29 de fevereiro em um

4 A base de dados denominada zoneinfo ou tz é um conjunto das zonas de fuso horário de todo o mundo. Essa base de dados também é chamada de Olson Database devido ao nome de seu criador, Arthur David Olson.

java 69.indb 56 26/05/2009 16:37:24

Page 57: java 69 [Introdução Spring Security] [Lido]

Edição 69 Java Magazine 57

Listagem 1. Exemplo do uso de um DateMatcher customizado para realizar a consulta de dias ímpares

package br.com.jm.javax.time.human.matchers;

//imports...

public class ExemploMatcherDiaImpar {

public static void main(String[] args) throws Exception { LocalDateTime agora = Clock.systemDefaultZone().dateTime(); boolean diaImpar = agora.matches(new DiaImparMatcher()); System.out.println(diaImpar); }}

class DiaImparMatcher implements DateMatcher { @Override public boolean matchesDate(LocalDate data) { if (data.getDayOfMonth() % 2 == 0) { return false; } else { return true; } }}

Listagem 2. Uso de static imports para minimizar a verbosidade do código no uso de Resolvers

package br.com.jm.javax.time.human.resolvers;

import static javax.time.calendar.field.DayOfMonth.dayOfMonth;import static javax.time.calendar.field.MonthOfYear.monthOfYear;import static javax.time.calendar.field.Year.isoYear;

import javax.time.calendar.DateResolvers;import javax.time.calendar.LocalDate;

public class ExemploResolverSI {

public static void main(String[] args) throws Exception { LocalDate data = DateResolvers.nextValid().resolveDate(isoYear(2009), monthOfYear(2), dayOfMonth(29));

System.out.println(data); }}

ano que não seja bissexto. A classe javax.time.calendar.DateResolvers possui algumas implementações dos casos de uso mais comuns onde possa vir a ser necessário o uso de um Resolver.

O exemplo apresentado a seguir ilustra a criação de uma data utilizando um resolver provido pela classe DateResolversque resolve uma data inválida como a próxima data válida.

LocalDate data = DateResolvers.nextValid().resolveDate(Year. isoYear(2009), MonthOf Year.monthOf Year(2), DayOfMonth.dayOfMonth(29));

Ao imprimir tal data no console, temos como data apresentada 2009-03-01. Caso você tenha achado o código verboso demais, é possível utilizar o recurso de static imports para reduzir a verbosidade. A Listagem 2 apresenta tal opção.

PeríodosOs períodos, dentro da javax.time, são

cidadãos de primeira-classe. Isso quer dizer que existem classes capazes de representá-los, ao contrário do que você encontra nas APIs atuais, onde não há for-ma padrão para representar períodos.

Através da representação dos períodos, podemos expressar durações de tempo da maneira tratada pelos seres humanos como, por exemplo, a duração de uma reunião ou de suas férias.

Como dito, existe uma classe para cada parte do período:

javax.time.period.field.Daysjavax.time.period.field.Hoursjavax.time.period.field.Minutesjavax.time.period.field.Monthsjavax.time.period.field.Secondsjavax.time.period.field.Weeksjavax.time.period.field.Years

E uma classe para representar o perío-do como um todo: javax.time.period.Period.

O código apresentado a seguir representa a criação de um período de duas horas:

Period period = Period.hours(2);

A partir desse momento, o objeto re-presenta o determinado período para o qual foi criado. Ao imprimir tal período no console, é impressa sua representação de acordo com o padrão ISO-8106. Essa representação para o período de duas horas é “PT2H”.

Uma das grandes vantagens no uso de objetos especializados para os períodos é permitir que você execute operações nesse objeto. Isso resultará na criação de outro objeto para representar o novo perí-odo resultante da operação. O objeto que representa o período também é imutável. A seguir, uma subtração de quarenta mi-nutos de nosso período de duas horas:

period = period.minusMinutes(40);

Ao executar tal operação, o período ainda permanece com duas horas e menosquarenta minutos e necessita ser normali-zado para representar o período real, que seria de uma hora e vinte minutos.

Normalização

O método normalize() retorna uma cópia do período normalizado para os limites padrão dos campos de data e hora, levan-do em conta as seguintes regras:

12 meses em um ano;60 minutos em uma hora;60 segundos em um minuto;1.000.000.000 de nanossegundos em

um segundo.

Por exemplo, um período de 13 meses é normalizado para um ano e um mês e a criação de um período de 5000 minutos com o código Period.minutes(5000) resulta em um período normalizado de 83 horas e 20 minutos.

Caso você necessite ainda realizar a normalização por dias, quebrando cada 24 horas em um dia, você deve utilizar o método normalizedWith24HourDays(), que neste nosso exemplo resultaria em um período de três dias, onze horas e vinte minutos.

java 69.indb 57 26/05/2009 16:37:24

Page 58: java 69 [Introdução Spring Security] [Lido]

ConclusãoVocê conheceu um pouco sobre a nova

especificação para representar datas e horas dentro da plataforma Java. Essa nova API tenta trazer várias facilidades e corrigir problemas conhecidos das opções atuais, buscando transformar seu código em algo mais legível e simples. Passamos por todos os pontos mais importantes da nova API, fornecendo exemplos pontuais e focados, tentando ambientar você com os novos conceitos.

A JSR 310, que está definindo a nova API, é aberta e você pode contribuir para seu

Michael Nascimento Santos [email protected] É um dos spec-leads da JSR-310

e expert em outras cinco JSRs.

Ganhou um JavaOne Rock Star

Speaker Award pela sua palestra sobre a JSR-310

em 2008 no JavaOne. Atua como Senior Technical

Consultant na Summa Technologies do Brasil.

Daniel Cicero [email protected]É Bacharel em Sistemas de

Informação pelo Mackenzie

e pós-graduado pela Fundação

Vanzolini. Trabalha com Java desde 1999 e possui

as certificações SCJP, SCWCD, SCBCD, SCDJWS, SCEA,

BEA Certified Developer: Integration Solutions e BEA

Certified SOA Architect. Já atuou como Desenvolve-

dor, Analista e Arquiteto de Sistemas e atualmente

é Consultor em Arquitetura BEA.

jsr-310.dev.java.net

Site de desenvolvimento da JSR 310, onde você pode

obter acesso a todos os artefatos relacionados à nova

API, além de participar de seu desenvolvimento,

cadastrando-se nas listas de discussão.

jcp.org/en/jsr/detail?id=310

Site oficial da JSR 310, parte do JCP.

joda-time.sourceforge.net

Site da Joda Time, API que está servindo de base

para o desenvolvimento da JSR 310.

Dê seu feedback sobre esta edição!

A Java Magazine tem que ser feita aoseu gosto. Para isso, precisamos sabero que você, leitor, acha da revista!

Dê seu voto sobre este artigo, através do link:

www.devmedia.com.br/javamagazine/feedback

seu Feedback

sob

reeeestaedição

Faça um up grade em sua carreira.

Em um mercado cada vez mais focado

em qualidade ter conhecimentos apro-

fundados sobre requisitos, metodologia,

análises, testes, entre outros, pode ser a

diferença entre conquistar ou não uma

boa posição profissional. Sabendo disso a

DevMedia lança para os desenvolvedores

brasileiros sua primeira revista digital

totalmente especializada em Engenharia

de Software. Todos os meses você irá

encontrar artigos sobre Metodologias

Ageis; Metodologias tradicionais (document dr iven) ; ALM (appl icat ion lifecycle management); SOA (aplicações orientadas

a servicos); Analise de sistemas; modelagem;

Métricas; orientação à objetos; UML; testes

e muito mais. Assine já!

Conhecimento faz diferença!

Faça já sua assinatura digital! | www.devmedia.com.br/esF já i t di it l! |já i d l! d di

Edição Especial

ProjetoEntenda o conceito de Arquitetura de Software e

como trabalhar com os Estilos Arquiteturais

RequisitosConheça os principais conceitos envolvidos

na Engenharia de Requisitos

Verificação, Validação & TesteFerramentas Open Source e melhores

práticas na gestão de defeitos

Especial Processos

Melhore seus processos através da análise de risco e conformidade

Veja como integrar conceitos de Modelos Tradicionais e Ágeis

Veja como integrar o Processo Unificado ao desenvolvimento Web

mag

azine

Entenda os principais conceitos sobreTestes e Inspeção de Software

Engenharia de SoftwareSaiba seu significado e para que serve

Mais de 60 mil downloadsna primeira edição!

desenvolvimento. Acesse o site da JSR (veja seção de Links) e faça parte da definição do futuro da linguagem. O código apresentado neste artigo está disponível para download no site da revista, contando com um JAR da javax.time compilado durante a escrita do arti-go. Como a API ainda está sendo concebida, é possível que quando o artigo chegar a você, leitor, algo possa ter sido alterado. Devido a isso, deixamos aqui a sugestão de baixar os fontes da última versão da API e adequar os exemplos às possíveis alterações. Acesse também a lista de discussões para entender o rumo que está sendo dado à API.

java 69.indb 58 26/05/2009 16:37:28

Page 59: java 69 [Introdução Spring Security] [Lido]

Edição 69 Java Magazine 59

java 69.indb 59 26/05/2009 16:37:29

Page 60: java 69 [Introdução Spring Security] [Lido]

SEÇÃO JAVA: NESTA SEÇÃO VOCÊ ENCONTRA ARTIGOS INTERMEDIÁRIOS E AVANÇADOS SOBRE JAVA

60 Java Magazine Edição 69

De que se trata o artigo:

Apresentação da nova ferramenta da Sun para a plataforma Java ME: o Java ME Platform SDK,

o sucessor do Wireless Toolkit. Neste artigo, as principais novidades trazidas por esta ferramenta

são apresentadas de uma forma clara e objetiva para o leitor.

Para que serve:

Proporcionar uma apresentação objetiva das principais funcionalidades da nova ferramenta de

desenvolvimento da plataforma Java ME. Esta apresentação concede ao leitor uma visão geral,

mas completa, do que de novo ele pode vir a utilizar daqui para frente no desenvolvimento de

suas aplicações.

Em que situação o tema é útil:

No momento em que uma ferramenta que usamos com frequência surge com uma versão nova,

é sempre válido dar uma olhada nas principais novidades que ela vem trazendo. Estas novidades,

geralmente, vêm para melhorar nossa produtividade, além de nos proporcionar mais subsídios,

a fim de desenvolvermos aplicações ainda melhores.

Java ME Platform SDK 3:

Assim como os seres vivos, os softwares de computador também evoluem a partir do momento

em que se inicia um novo ciclo. No caso da principal ferramenta de desenvolvimento da plata-

forma Java ME, o Wireless Toolkit, este seu novo ciclo trouxe-lhe evoluções bastante expressivas.

Mudanças que vão desde o nome, passando pelo novo conceito da ferramenta, até chegar às

suas novas funcionalidades.

A ferramenta que antes era considerada um simples toolkit (caixa de ferramenta), agora passa

a ser um completo SDK, contando com um ambiente integrado de desenvolvimento. Editor de

código, emuladores, nova máquina virtual e APIs são somente algumas das muitas novidades

trazidas por esta nova ferramenta. Sem falar que até o seu nome é novidade, pois agora a ferra-

menta é chamada de Java ME Platform SDK 3.

Com todas essas novidades é possível constatar o grande passo que a plataforma Java ME dá

em direção a uma maior popularização da plataforma. Pois com o ambiente de desenvolvimento

integrado baseado no NetBeans, novos desenvolvedores terão mais facilidades de criar as suas pri-

meiras aplicações, o que garante uma maior chance de crescimento da comunidade Java ME.

1 Trecho baseado no artigo ‘Introdução à Evolução’. (fonte Wikipedia)

Segundo a Biologia, o processo permanente de mudança que vem transformando a vida na

Terra, desde o seu princípio mais simples até a sua atual diversidade, é conhecido como Evolução. A evolução ocorre quan-do um ser vivo se reproduz, e pequenas mudanças aleatórias nos seus genes fazem com que o seu descendente seja diferente dele próprio. Essas mudanças, se benéficas, fazem com que o indivíduo sobreviva o tempo necessário para se reproduzir, dando início a um novo ci-clo de transformações, o que resulta no surgimento de novas espécies1.

Num paralelo entre o processo de evolução dos seres vivos com o de um software de computador, verificamos como ambos são parecidos. O software, geralmente, inicia o seu clico de vida de forma bem simples, com poucas funcionalidades, somente com o intuito de atender certa demanda do momento. À medida que vai sendo utilizado, o software, se for bom, acaba aguçando a criatividade dos usuários, que solicitam novas versões mais aperfeiçoadas e com mais funcionalidades. Estas solicitações induzem o software a entrar no clico de evoluções, resultando em novos releases.

Neste artigo, falaremos sobre como este processo evolutivo dos softwares atingiu o Wireless Toolkit (WTK). Apre-sentaremos algumas das principais novidades que a Sun Microsystems pre-parou, justificando a mudança do seu nome para Java ME Platform SDK 3.

De Toolkit para SDKO fato de a Sun ter mudando o nome

do WTK não deve causar muito espanto

aos desenvolvedores, tendo em vista que esta não é a primeira vez. Desde o surgimento da plataforma Java ME, por volta de 1999, esta já é a segunda vez que a Sun muda o nome da ferramenta. O nome original, Java 2 Platform Micro Edition Wireless Toolkit, foi substi-tuído em 2007, devido à nova versão

1.5 (ou 5) da plataforma Java. Desde então, a Sun retirou o famigerado “2” de todos os nomes de suas plataformas e ferramentas. Com isto, o que era J2ME virou Java ME, o que também acabou refletindo na primeira mudança de nome do WTK para Sun Java Wireless Toolkit.

java 69.indb 60 26/05/2009 16:37:30

Page 61: java 69 [Introdução Spring Security] [Lido]

ERNANDES MOURÃO JÚNIOR

Edição 69 Java Magazine 61

A mudança do nome na nova versão, que agora insere o termo SDK (Standard Development Kit), se deve ao fato da ferramenta proporcionar um ambiente de desenvolvimento completo, e não somente os emuladores, ferramentas de monitoração (e.g. monitor de memória), códigos de exemplo, documentação, etc. O pacote agora também vem com editor de código com assistência de codificação (veja a seção “Netbeans “Lite”). Além disso, a plataforma Java ME é suportada de forma muito mais completa (o antigo WTK suportava apenas a configuração CLDC, exigindo toolkits separados para CDC e outras variantes). Um arsenal completo que eleva a categoria da fer-ramenta, justificando o acréscimo do termo SDK.

NetBeans “Lite”De longe a mais importante e impac-

tante novidade do Java ME Platform SDK 3 é o ambiente de desenvolvimento integrado (veja Figura 1), baseado na plataforma NetBeans. Nas versões anteriores da ferramenta, todo o desen-volvimento das aplicações (e.g. escrita de código) tinha que ser feito numa ferramenta (IDE) à parte, como por exemplo, Eclipse, NetBeans, VistaMax, etc. O trabalho do WTK era executar os emuladores, alterar configurações de ambiente da plataforma, monitoramen-to de memória, dentre outras funciona-lidades auxiliares. IDEs como Eclipse e NetBeans, por exemplo, permitiam que o WTK pudesse ser integrado, possibilitando ao desenvolvedor uma transparência do seu uso.

As principais ferramentas deste am-biente de desenvolvimento integrado são o editor de código, gerenciador de projetos e arquivos, integração com o

Figura 1.

Ant, configurações do projeto (e.g. pro-priedades do arquivo JAD), ofuscador de código, além de outras de cunho mais geral, encontradas em qualquer distri-buição do NetBeans.

Quem já trabalha com o Netbeans Mo-

bility Pack vai se sentir em casa neste novo ambiente, pois ambos são prati-camente o mesmo. Além disso, aqueles que, porventura, decidirem migrar para o NetBeans Mobility Pack futuramente, já que este dispõe de mais funcionalida-

java 69.indb 61 26/05/2009 16:37:30

Page 62: java 69 [Introdução Spring Security] [Lido]

62 Java Magazine Edição 69

des, não encontrarão barreiras. Pois o arquivo de projeto do Java ME Platform SDK 3 é totalmente compatível com o Mobility Pack, o que facilita muito a migração entre as ferramentas.

A KVM se DespedeApós quase dez anos desde sua chega-

da, a máquina virtual da Java ME, a Kilo Virtual Machine (KVM), finalmente encerra o seu ciclo de vida. Este fim já era esperado, já que há alguns anos, a KVM já não estava mais presente nos dispositivos móveis disponíveis no mercado, sendo esta substituída pela CLDC HotSpot Vir-tual Machine. Um projeto mais moderno e robusto, que já conseguia atender melhor as atuais demandas por desempenho.

O que prolongou um pouco mais a vida da KVM foi o fato da Sun continuar utilizando-a em seus emuladores. Até a última versão do WTK, a 2.5.2, todos os emuladores ainda eram baseados na KVM. No entanto, com a chegada do Java ME Platform SDK 3 a Sun finalmente “aposentou” a KVM, trazendo de uma vez por todas, a CLDC HotSpot Virtual Machine também para os seus emulado-res, inclusive para a configuração CDC. Com esta mudança, o comportamento das aplicações no emulador ficou mais parecido ao encontrado nos dispositivos reais.

Dentre as principais vantagens da CLDC HotSpot Virtual Machine, com-parada à KVM, estão a compilação dinâmica das instruções de bytecode em instruções nativas (veja o quadro “Com-pilação Just-in-time (JIT)”), menor con-sumo e fragmentação de memória, maior economia da bateria, dentre outras. Em termos de números, a execução de uma instrução compilada dinamicamente, chega a ser cinquenta vezes mais rápida do que uma instrução interpretada.

Para conhecer um pouco mais sobre a CLDC HotSpot Virtual Machine e a sua chegada aos dispositivos móveis, veja a seção Links, além do artigo “Java: Uma perspectiva”, da Edição 65.

Descobrindo as DiferençasExiste na Internet uma iniciativa cha-

mada de Wireless Universal Resource File (WURFL), aonde desenvolvedores e entusiastas vêm tentando catalogar todos os dispositivos móveis dispo-níveis no mercado, assim como suas características. O objetivo é fornecer uma base de dados centralizada para os desenvolvedores. Neste caso, um arquivo XML, afim de que eles pos-sam conhecer, antecipadamente, as principais diferenças que existem de um dispositivo para outro, além de ter uma idéia da fatia de mercado que suas aplicações estão abrangendo.

Com o objetivo de facilitar o acesso às informações providas pelo WURFL (para saber mais sobre esta iniciativa, veja a seção Links), a Sun desenvolveu uma nova funcionalidade, no Java ME Platform SDK 3, chamada Device Da-tabase Search, que acessa essa base de dados de uma forma fácil e rápida. O

Figura 2.

2 Ferramenta utilitária do LWUIT que serve para editar arquivos de recurso do framework, como por exemplo, definição de tema, imagens, textos internacionalizados, etc.

usuário pode tanto solicitar para ver a lista completa de todos os dispositivos disponíveis, como ele também pode aplicar alguns filtros (e.g. fabricante, modelo, JSRs suportadas, tamanho de tela, etc.), a fim de facilitar a busca pelo dispositivo desejado. O resultado é apresentado numa lista, onde mode-lo e fabricante são identificados. Para ver os detalhes de um determinado dispositivo, basta selecioná-lo na lista, que todas as suas informações serão exibidas numa outra lista ao lado (veja Figura 2).

LWUIT Ganha ForçaA equipe do projeto Lightweight User

Interface Toolkit (LWUIT) deve estar orgulhosa com esta conquista. Tendo em vista a grande popularização deste projeto entre os desenvolvedores Java ME, a Sun não perdeu tempo em tentar transformar este projeto numa espécie de padrão dentro da comunidade de desenvolvedores. Os engenheiros da Sun devem ter percebido a quantidade de projetos que existem na Internet, que

N o t a d o D e v M a n

Ant: Ant é uma ferramenta utilizada para automatizar a construção de software. Ela é similar ao make, mas é escrita na linguagem Java e foi desenvolvida inicialmente para ser utilizada em projetos desta linguagem. (fonte Wikipedia)

java 69.indb 62 26/05/2009 16:37:31

Page 63: java 69 [Introdução Spring Security] [Lido]

Edição 69 Java Magazine 63

visam melhorar a vida dos desenvolve-dores, no tocante do desenvolvimento de interfaces gráficas mais sofisticadas. Com isso, a Sun não hesitou e incorporou o LWUIT como uma de suas bibliotecas padrão, disponibilizou uma aplicação exemplo e integrou uma de suas ferra-mentas utilitárias, o Resource Manager2,dentro do Java ME Platform SDK 3. Ala-vancando de vez o nome LWUIT dentro da comunidade Java ME.

O LWUIT, para quem ainda não co-nhece, é um framework de componentes gráficos inspirado no Swing da plata-forma Java Standard Edition (Java SE), especificamente modelado e construído para ambientes restritos em poder de processamento e memória, como o dos disposit ivos móveis. O LWUIT traz para o mundo móvel, algumas das fun-cionalidades para o desenvolvimento de interfaces gráficas já conhecidas no desktop e que são bem características do Swing, como por exemplo, layouts (e.g. FlowLayout), renders (componentes que especificam a forma como um objeto é desenhado na tela), manipuladores de evento (e.g. ActionListener), etc.

Com toda esta integração, para um desenvolvedor acrescentar o suporte ao LWUIT à sua aplicação dentro do Java ME Platform SDK 3, basta somente alguns passos: acessar as propriedades do projeto, selecionar -

, clicar no botão e sele-cionar a biblioteca LWUIT, que já aparece na lista, junto com as demais bibliotecas disponíveis na ferramenta. Além disso, a aplicação exemplo é bem completa, o que serve como uma boa referência ini-cial para os desenvolvedores que estão começando no LWUIT (para saber mais sobre LWUIT, veja a Edição 60 e a seção Links). Ela apresenta diversos exemplos de várias partes do framework.

Encontrando o “Gargalo”Como se os problema de lógica não fos-

sem o bastante, os problemas de desem-penho também tem sido uma constante

3 Determinado trecho de um processamento que demora muito para ser executado, afetando o tempo final de resposta de um processo.

Figura 3. Tela do profiler que mostra os tempos de execução dos métodos da aplicação

java 69.indb 63 26/05/2009 16:37:31

Page 64: java 69 [Introdução Spring Security] [Lido]

64 Java Magazine Edição 69

nas aplicações atuais, principalmente nas móveis, devido às exigentes demandas por mais funcionalidades, sem falar das restrições de processamento, inerentes aos dispositivos móveis.

A fim de também facilitar mais esta tarefa dos desenvolvedores, já que por muito tempo esta também foi executada com o auxilio de APIs como System.out.println() e System.currentTimeMillis(), foram criados os monitores de processamento (profiler). São ferramentas que monitoram toda a execução da aplicação, registrando os tempos de execução e a quantidade de vezes que cada método foi executado. Informações muito valiosas quando se está à procura do “gargalo”3 de um de-terminado processo. No Java ME Platform SDK 3, esta ferramenta de monitoração é a mesma encontrada em outras distribuições do NetBeans, também usada para testes em aplicações Java SE e Java EE.

Para ativar o profiler para determinada aplicação no Java ME Platform SDK 3, basta habilitar a opção Enable profiler nas pro-priedades do emulador utilizado. Durante a execução, o profiler registra num arquivo (e.g. data.prof), todas as informações sobre o código que está sendo executado. Ao final da execução, é preciso informar ao SDK, através da opção Profile>Import Java ME SDK Snapshot, o caminho do arquivo gerado pelo profiler, a fim de que a infor-mação coletada seja apresentada. Nesta

nova tela que é mostrada (veja Figura 3), o desenvolvedor pode ver o tempo gasto para executar cada método e a quantidade de vezes em que ele foi executado, além de ainda poder agrupar todas estas informa-ções por classe ou por pacote. Dando uma visão mais macro dos tempos de execução de cada componente da aplicação.

E mais JSRsA cada dia novas APIs são finalmen-

te especificadas, tornando-se aptas a serem implementadas por algum fa-bricante, que suporte a plataforma Java ME em seus dispositivos móveis. O que normalmente acontece é a implemen-tação dessas APIs chegarem primeiro às ferramentas de desenvolvimento, tendo em vista uma maior facilidade de implementá-las em plataformas Windo-ws ou Linux, por exemplo, para depois chegarem aos dispositivos.

No Java ME Platform SDK 3, três novas APIs estão finalmente disponíveis para os desenvolvedores: Mobile Sensor API (JSR 256) (veja o artigo da Edição 55), XML API for Java ME (JSR 280) e a Java Binding for the OpenGL ES API (JSR 239). A primeira é responsável por fornecer acesso a alguns sensores (e.g. acelerômetro) disponíveis em certos dispositivos móveis (veja o quadro“Trabalhando com Sensores no Emu-lador”). A JSR 280, por sua vez, define

uma API exclusiva para manipular ar-quivos XML com parsers SAX2 e DOM. A idéia é acabar com a fragmentação que existe atualmente, onde cada API que precisa manipular XML define o seu próprio mecanismo para desempe-nhar este trabalho (e.g. Web ServicesSpecification (JSR 172)). E finalmente, a JSR 239 vem para prover o suporte ao desenvolvimento de gráficos 3D através da biblioteca OpenGL ES, a qual é um subconjunto da OpenGL 1.3.

Para fechar o pacote das novas API, o Java ME Platform SDK 3 também dispo-nibiliza aplicações exemplo para cada nova API suportada, inclusive as que já eram suportadas. Um ótimo “pontapé inicial” para quem está começando a trabalhar com as APIs mais recentes.

Quanto mais Emuladores, MelhorÉ inquestionável a qualidade dos emu-

ladores disponibilizados pelo Java ME Platform SDK 3, assim como os de suas versões anteriores. Todos eles seguem à risca cada ponto das especificações das APIs, dando maior segurança ao desen-volvedor sobre a corretude do seu código. Se nenhuma exceção for lançada, alertan-do sobre alguma operação indevida, é porque ele está no caminho certo.

No entanto, por mais que as especi-ficações sirvam para definir uma base comum, além de diminuir as chances de incompatibilidade entre as diferentes im-plementações, no mundo real as coisas não são tão perfeitas assim. É comum encontrar problemas de incompatibilidade entre uma implementação feita para o Windows, que não funciona no Linux, e vice-versa. No mundo móvel então, é ainda pior. Aplica-ções feitas para rodar num dispositivo da Nokia podem precisar de ajustes para ro-dar perfeitamente num Motorola ou Sony Ericsson, por exemplo. Por mais que sigam a risca o que está na especificação, sempre é possível ter algo na implementação (in-clusive bugs) que gera um comportamento diferente. A complexidade e as restrições dessas plataformas móveis potencializam ainda mais este problema.

Tendo em vista essas possíveis dife-renças, os testes em outras plataformas

A característica da plataforma Java que per-

mite que suas aplicações sejam possíveis de

serem executadas em diferentes plataformas

(e.g. Windows e Linux), sem necessidade de

recompilação, é o fato do seu código-fonte

ser compilado para uma representação inter-

mediária, conhecida como bytecode. Mas sua

execução depende de outra aplicação, esta sim

dependente de plataforma: a máquina virtual,

que interpreta o bytecode.

Os ganhos em portabilidade com este código

intermediário, por outro lado, gera problemas

de desempenho, pois a interpretação é bem

menos eficiente que a execução de código

nativo. Entretanto, o problema pode ser re-

solvido com ajuda da técnica de compilação

Just-in-time (JIT), que consiste na compilação

do bytecode para código nativo durante a

execução da aplicação. No momento em que

um método vai ser executado, este é convertido

numa representação de código de máquina. Por

isso o termo Just-in-time que, em português,

significa “no momento exato”. Este código

compilado fica salvo na memória, pronto para

execuções futuras.

Além da plataforma Java, a .NET também

utiliza esta técnica. Neste caso, o código inter-

mediário convertido pela máquina virtual .NET

é o Microsoft Intermediate Language (MIL). Para

saber mais sobre a JIT, veja a seção .

java 69.indb 64 26/05/2009 16:37:31

Page 65: java 69 [Introdução Spring Security] [Lido]

Edição 69 Java Magazine 65

se tornam muito importantes para uma aplicação Java ME, que deseja rodar em dispositivos de mais de um fabricante. Nesta versão do Java ME Platform SDK 3 é possível importar outros emu-ladores desenvolvidos, por exemplo, pela Nokia, Samsung, Motorola, Sony Ericsson, dentre outros, para dentro da ferramenta e usá-los para testar suas aplicações. Uma funcionalidade já en-contrada no NetBeans Mobility Pack.

Para importar novos emuladores, é preciso informar o caminho do SDK do fabricante, o qual os emuladores pertencem. Para isto, deve-se acessar Tools>Java Platforms, selecionar o tipo de plataforma J2ME, clicar em Add Plaform,selecionar Custom Java ME MIDP Pla-tform Emulador e informar os caminhos solicitados pelo restante do wizard. Após ter configurado a nova platafor-ma, basta acessar as propriedades do projeto e selecionar a nova plataforma e o emulador a ser utilizado.

Testes em emuladores é realmente uma “mão na roda”, pois facilitam muito o desenvolvimento, tendo em

vista a rapidez que é por em execução a aplicação no emulador. Entretanto, eles nunca vão substituir o teste no disposi-tivo real, pois, se de um emulador para outro já existem diferenças, imagine do emulador para o hardware.

Suporte OficialCom exceção do sistema operacional

Symbian, outros sistemas como Palm OS e Windows Mobile, também bem populares no mercado, nunca foram referência pelo seu suporte à plataforma Java ME, pelo contrário. Esta questão, acredito, deve-se ao fato que ambos pos-suem, desde muito cedo, suas próprias

plataformas nativas (baseadas em C) de desenvolvimento de aplicações. Ambas muito bem difundidas e poderosas, e que acabou gerando uma comunidade de desenvolvedores duradoura.

Com relação ao Palm OS, a Sun até que se esforçou na época do lançamento da primeira versão do Wireless Toolkit (ainda MIDP 1.0), disponibilizando uma máquina virtual que podia ser instalada nos dis-positivos da empresa Palm. No entanto, a investida não vingou, talvez pelo desinte-resse da própria Palm, e o projeto ficou pelo caminho. A IBM também tentou, lançando uma máquina virtual chamada Websphere Everyplace Micro Environment (WME),

Existem algumas APIs Java ME que interagem

com alguns tipos de hardware ou serviço, que

vem integrado a algumas linhas de dispositivos

móveis. Por exemplo, a Mobile Sensor API (JSR

256), que interage com sensores (e.g. acelerô-

metro); a Location API (JSR 179), que captura os

dados de um GPS; e a Payment API (JSR 229), que

fornece serviço de pagamentos em geral.

Imaginar como se testa uma aplicação desen-

volvida com estas APIs, no dispositivo real, não

é difícil. Pois neste caso, o hardware ou serviço

está presente no dispositivo e a API vai acessá-lo

para poder retornar suas informações. Mas o que

acontece quando não se tem o dispositivo real em

mãos, para testar a aplicação? A resposta é sim-

ples: para cada API que interage com um hardwa-

re ou serviço, os emuladores do Java ME Platform

SDK executam tais papéis, simulando-os.

No caso da JSR 256, para a qual a emulação

de sensores é mais uma novidade do Java ME

Platform SDK, o desenvolvedor pode alterar

as informações que o acelerômetro retorna.

Desta forma, o desenvolvedor pode informar

novos valores para as coordenadas x, y e z, que

representam a leitura tridimensional deste tipo

de hardware.

Para acessar as ferramentas de simulação dos

emuladores, o desenvolvedor precisa acessar a

opção View>External Events Generator, dispo-

nível no próprio emulador. Depois disto, uma

nova tela será apresentada, com uma série abas

nela. Cada aba, por sua vez, representa um tipo

de hardware ou serviço que pode ser simulado.

No caso do acelerômetro, a aba Sensors é a que

fornece os meios para simulá-lo. Nesta mesma

aba, o Java ME Platform SDK ainda fornece a

simulação de um sensor de temperatura.

N o t a d o D e v M a n

OpenGL: OpenGL é uma API aberta utilizada na computação gráfica para desenvolvimento de aplicativos gráficos, ambientes 3D, jogos, entre outros. (fonte Wikipedia)

java 69.indb 65 26/05/2009 16:37:31

Page 66: java 69 [Introdução Spring Security] [Lido]

66 Java Magazine Edição 69

com suporte ao MIDP 2.0. A Palm dessa vez até esboçou um incentivo, publicando a VM da IBM no seu site como um produto homologado. Porém, em 2008, o incentivo acabou e a Palm retirou o apoio. Hoje este projeto está parado no tempo, assim como o próprio Palm OS, que vem sumindo do mercado aos poucos.

A história da plataforma Java ME no sis-tema operacional da Microsoft não é muito diferente da vivida pela Palm. Esta também é marcada pela dificuldade de encontrar uma máquina virtual robusta e sólida, o que ajudaria a difundir melhor a Java ME nos populares PDAs da empresa de Bill Gates. No entanto, por mais que o suporte seja fraco, o Windows Mobile chega ainda a ser melhor que o Palm OS, com relação a Java ME. Nas versões para smartphones do Windows Mobile, por exemplo, até existe uma máquina virtual que já acompanha o dispositivo. Por mais que seja restrito em recursos, ainda serve para rodar aplicações mais simples. A IBM também investiu na Java ME para o Windows Mobile, disponi-bilizando uma versão paga da sua máquina virtual, WME, voltada para versões ante-riores deste sistema.

Mas agora, as coisas parecem que vão melhorar para os desenvolvedores Java ME que querem rodar suas aplicações no Windows Mobile. A Sun está disponibili-zando, no Java ME Platform SDK 3, uma

Ernandes Mourão Júnior [email protected]É Bacharel em Informática pela

Universidade de Fortaleza e desen-

volvedor certificado Java (SCWCD, SCB-

CD e SCMAD). Atualmente exerce os cargos de Analista

de Desenvolvimento de Sistemas e Líder Técnico Java ME

no Instituto Atlântico, em Fortaleza/CE. Recentemente

foi premiado como um dos vencedores do Sony Ericsson

Content Awards 2008, com a aplicação EcoMate.

http://java.sun.com/javame/downloads/

sdk30ea.jsp

Página de download do Java ME Platform SDK 3

http://java.sun.com/j2me/docs/pdf/CLDC-

HI_whitepaper-February_2005.pdf

CLDC HotSpot™ Implementation Virtual Machine

http://wurfl.sourceforge.net/

WURFL: Wireless Universal Resource File

https://lwuit.dev.java.net/

LWUIT: Lightweight User Interface Toolkit

http://pt.wikipedia.org/wiki/JIT

JIT: Just-in-time

Dê seu feedback sobre esta edição!

A Java Magazine tem que ser feita aoseu gosto. Para isso, precisamos sabero que você, leitor, acha da revista!

Dê seu voto sobre este artigo, através do link:

www.devmedia.com.br/javamagazine/feedback

seu Feedback

sob

reeeestaedição

máquina virtual para o Windows Mobile 6, que pode tanto ser instalado em um emulador do próprio sistema operacional no PC, quanto num dispositivo real. Tudo o que o desenvolvedor precisa fazer é instalar a maquina virtual (veja Figura 4), através do arquivo ,que se encontra disponível no SDK na pasta

,no emulador ou no dispositivo. Além de executar as aplicações, o desenvolvedor ainda tem a possibilidade de depurar suas aplicações tanto no emulador quanto no dispositivo real.

Com mais esta plataforma dando supor-te à Java ME, agora com a assinatura da Sun, a plataforma Java dá mais um passo muito importante na consolidação do seu nome nas principais plataformas móveis do mercado.

ConclusãoA Sun, com certeza, acertou com o Java

ME Platform SDK, pois a falta do ambiente de codificação do Wireless Toolkit atra-palhava, de certa forma, os novos desen-volvedores. O problema era que estes não conseguiam, rapidamente, codificar um

. Haja vista que precisavam usar um editor de código externo, importar o projeto para o toolkit, etc.

Com o Java ME Platform SDK tudo ficou mais integrado. A facilidade de criar um projeto, codificar, escolher o emulador e colocar para executar são características muito importantes, que todo iniciante, em qualquer plataforma, gosta de ter. Entretan-to, o Java ME Platform SDK é indicado so-mente para aplicações de teste ou pequenas, pois algumas funcionalidades importantes no desenvolvimento de aplicações mais

complexas, como depuração e controle de versão, não estão disponíveis. Nesses casos, o recomendado mesmo é o NetBeans Mobi-lity Pack, que oferece o ambiente completo do NetBeans mais uma série de ferramentas específicas para Java ME.

Figura 4. Ícone que mostra a máquina virtual Java ME no

Windows Mobile 6.

java 69.indb 66 26/05/2009 16:37:33

Page 67: java 69 [Introdução Spring Security] [Lido]

Edição 69

06_Ernandes_JavaME.indd 67 05/06/2009 17:00:24

Page 68: java 69 [Introdução Spring Security] [Lido]

SEÇÃO JAVA: NESTA SEÇÃO VOCÊ ENCONTRA ARTIGOS INTERMEDIÁRIOS E AVANÇADOS SOBRE JAVA

68 Java Magazine Edição 69

De que se trata o artigo:

O artigo apresenta técnicas e práticas provadas de integração de aplicações Java com outras aplica-

ções, sistemas e bancos de dados. Projetos de integração apresentam muitas complexidades técnicas

e muitas possibilidades técnicas em Java tais como JMS, JCA, JDBC, RMI, HTTP e SOAP. O artigo mostra

como escolher estas tecnologias e como utilizá-las adequadamente através de padrões de integração

de aplicações (EIP).

Para que serve:

O artigo é útil para que desenvolvedores possam conhecer os riscos associados à integração de

sistemas Java com outros sistemas e aplicar as melhores práticas de mercado e padrões de integração

para mitigar e eliminar estes riscos. Projetos com riscos técnicos reduzidos possuem maior garantia de

sucesso, maior qualidade, estabilidade e manutenções mais simples e facilitadas.

Em que situação o tema é útil:

Em projetos de TI que requerem integrações de todo tipo, como bancos de dados relacionais, bases de

dados em outros formatos, sistemas de filas de mensagens, aplicações legadas em plataformas baixas e altas

ou aplicativos como CRM (Customer Relationship Management) e ERP (Enteprise Resource Planning).

Estratégias de Integração de Aplicações Java EE:

Integrar aplicações Java com outros sistemas não é uma tarefa trivial. Para reduzir riscos e manter

projetos sob controle, devemos usar práticas provadas de integração de sistemas.

As melhores práticas de integração são denominadas padrões EAI (EAI Patterns) e foram populari-

zadas por Gregor Hohpe através do seu livro Enterprise Integration Patterns. Estas práticas permitem

que um arquiteto ou desenvolvedor escolha as estratégias mais eficientes de integração de sistemas

Java com outros sistemas e produza soluções mais perenes e econômicas.

Estas práticas de integração também são fundamentais para empresas que estejam buscando

iniciativas SOA e BPM, pois permitem gerir adequadamente a criação e evolução de serviços (ativos)

em repositórios de serviços (ESB).

Um processo simples para que você possa aprender a integrar sistemas em projetos envolve os

seguintes passos: (1) Coletar os requisitos arquiteturais de interoperabilidade; (2) Desenvolver solu-

ções independentes de tecnologia para cada requisito arquitetural coletado; (3) Estudar os exemplos

disponibilizados na referência [1]; (4) Estudar as tecnologias Java mais adequadas para cada requisito

(ex: WebServices ou RMI); (5) Implementar os cenários com as tecnologias Java escolhidas; (6) Testar

as soluções em ambiente de homologação.

Integrar aplicações não é uma tarefa tri-vial. Protocolos diversos, APIs exóticas, tecnologias e ambientes complexos e

cronogramas agressivos são alguns aspectos que desafiam diariamente analistas desen-volvedores Java EE.

Conto aqui uma história que resume estes desafios. Uma equipe necessitava enviar emails de sua aplicação Java. Uma tarefa aparentemente trivial, que muitos desenvolvedores vivem todos os dias. A equipe não possuía experiência com a API JavaMail, mas com a ajuda de um recurso externo a equipe se capacitou e desenvolveu o código necessário para suportar a integração, que neste caso ocorreria com o servidor Microsoft Exchange. Código implementado, tes-tes internos realizados com sucesso e aprovação gerencial. Aparentemente o problema foi resolvido.

A vida real, entretanto, guarda surpresas. Na véspera da semana de implementação, o código foi implantado na empresa do cliente (vamos chamá-la de empresa ACME), mas os casos de uso que requeriam a integração com o Microsoft Exchange não funciona-vam. Todos os olhos e atenções (e culpas) foram lançados para o servidor de email da Microsoft. Após a descoberta que o servidor de email do cliente (v2007) estava em uma diferente versão do ambiente interno da desenvolvedora (v2003), modificações no ambiente de desenvolvimento foram rea-lizadas para adequar o servidor. Nenhum resultado positivo foi alcançado. O pânico se instalou!

Mais investigações foram realizadas e a equipe descobriu que o servidor de email de produção não residia na mesma rede do servidor de aplicação do cliente, mas em um distante local remoto (em outra cidade) em um provedor com um acesso controlado por um firewall. O analista de

infra-estrutura do cliente não foi questio-nado o bastante para informar este fato. Para encurtar a história, a equipe desco-briu que o envio de emails neste ambiente requeria o uso de certificados e protocolos com garantia de transporte seguro (SMTP sobre SSL). Noites mal-dormidas, um atra-

so de algumas semanas no cronograma, um cliente relativamente estressado e o desafio foi finalmente vencido.

Que lições podemos aprender com esta história? Enumero algumas abaixo:

serem integrados sejam exatamente iguais;

java 69.indb 68 26/05/2009 16:37:33

Page 69: java 69 [Introdução Spring Security] [Lido]

MARCO AURÉLIO DE SOUZA MENDES

Edição 69 Java Magazine 69

isto é, a organização física do ambiente de produção do cliente. Diagramas UML de implantação são uma ferramenta útil neste aspecto;

requisitos não-funcionais que possam interferir na intero-perabilidade;

real do cliente.

O leitor mais experiente pode questionar as lições aprendidas neste exemplo.

. Mas devemos lembrar que senso comum não é prática comum.

Seja um “Indiana Jones” de aplicações Java na sua

empresa. Faça uma arqueologia de software nas apli-

cações Java da sua empresa e colete os erros e lições

aprendidas. Os erros do passado são uma excelente

fonte de aprendizado para projetos futuros.

O objetivo deste artigo é mostrar a você como tornar senso comum em prática comum, isto é, evitar erros comuns de in-

tegrações de sistemas em projetos e evitar estresses desnecessários. Vamos abordar estratégias e técnicas para organizar o seu trabalho, organizados da seguinte forma nas seções seguintes deste artigo:

Iremos conhecer aqui fundamentos da integração de sistemas;

Java. Aqui iremos citar as principais tec-nologias e padrões Java para a integração de aplicações;

conhecer aqui as melhores práticas de mercado para integrar aplicações;

Vamos abordar aqui as principais tarefas necessárias durante um projeto para ga-rantir uma boa interoperabilidade de suas aplicações Java.

Estilos, Níveis e Topologias de Integraçãoinimigo, para , Sun Tzu, A

Arte da Guerra.Como conhecer o inimigo? Primeiramente

devemos compreender que interoperabili-dade é um mecanismo arquitetural, ou seja, uma preocupação importante de um proje-to e que, portanto, requer a atenção técnica ainda no começo do projeto. Devemos in-vestigar as interoperabilidades requeridas no nosso projeto através do estilo, nível e topologia associados, pois para cada um ha-verá uma abordagem técnica diferenciada e tecnologias distintas em Java.

Colete os requisitos arquiteturais diretamente com

representantes do seu cliente em reuniões conjuntas

com o analista de requisitos. Normalmente analistas

de requisitos têm dificuldade de capturar e expressar

informações técnicas, o que implica em informações

truncadas e novas descobertas indesejadas no final

do projeto.

A interoperabilidade de aplicações pode se apresentar em quatro estilos, conforme Gregor Hohpe [1]. 1. O primeiro estilo é a transferência de arquivos, onde duas aplicações compar-tilham as informações através de um arquivo texto ou binário. O protocolo FTP é um exemplo popular de tecnologia que suporta este estilo;2. O segundo estilo, talvez o mais popu-lar, é através de dados compartilhados em bancos de dados;3. O próximo estilo é através de procedi-mentos remotos (RPC), onde um progra-ma cliente invoca uma funcionalidade em outra máquina. As tecnologias de WebServices são exemplos normalmente associados a RPC;4. O último estilo é através de passagem de mensagens. Programas com suporte a filas de mensagens, como a especificação Java JMS, são exemplo deste estilo.

Pare um minuto e responda: Qual o estilo requerido no exemplo citado de interoperabilidade com o Microsoft Exchange? (Resposta no final deste artigo).

Além dos estilos, podemos classificar a interoperabilidade em níveis, listados a seguir:1. Nível de dados. Como integrar fontes de dados relacionais ou em outros forma-tos e como reduzir a sua redundância?

N o t a d o D e v M a n

Requisitos Funcionais e Requisitos Não-Funcionais:

Requisitos funcionais expressam os desejos dos interessados do projeto na perspectiva da funcionalidade. Exemplos incluem cadastros, relatórios e fluxos de trabalho. Requisitos não-funcionais expressam atributos de qualidade de um sistema tais como desempenho, usabilidade, disponibilidade ou portabilidade.

Requisitos funcionais e não-funcionais importantes para o negócio (prioritários) e complexos formam o conjunto de requisitos arquiteturais que devem ser foco inicial de qualquer projeto de TI.

Requisitos funcionais e não-funcionais coletados podem responder a perguntas sobre escolhas de estratégias e tecnologias sobre interoperabilidade. Por exemplo, restrições sobre desempenho podem eventualmente influenciar na escolha de uma integração com soquetes ao invés de XML e Web Services.

java 69.indb 69 26/05/2009 16:37:34

Page 70: java 69 [Introdução Spring Security] [Lido]

70 Java Magazine Edição 69

A integração em nível de dados foca na movimentação de dados entre aplicações com o objetivo de compartilhar o mesmo dado entre aplicações diferentes;2. Nível de Interfaces de Aplicação (API). Como integrar APIs de aplicação em outras tecnologias que não sejam Java? A integração via APIs passa pela chamada de funções através de proto-colos síncronos (RPC) ou assíncronos (mensagens);3. Nível de Processos de Negócio. Domínio do mundo BPM/SOA, a integração em nível de processos de negócio foca no desenvol-

Figura 1. Mash-up do Internet Google. Diferentes aplicações foram integradas aqui em nível de camada de apresentação.

Podemos ver no exemplo acima blogs de diferentes autores, o Google Talk e mesmo uma aplicação de previsão de tempo.

Figura 2. A topologia de comunicação ponto a ponto liga

duas aplicações diretamente. A topologia Hub and Spoke usa

um barramento central (Hub) para ligar múltiplos clientes.

vimento de componentes de alto nível que irão fornecer interfaces de alto nível que podem ser considerados serviços;4. Nível de Apresentação. Popularmente conhecidos como mash-ups, integram apli-cações através de um conjunto de vários portlets (janelas visuais independentes) que residem em um determinado portal. A Figura 1 mostra um exemplo de integração neste nível.

Um novo teste: Qual o nível associado ao exemplo

citado de interoperabilidade com o Microsoft Exchan-

ge? (Resposta no final deste artigo).

Estilo de Interoperabilidade APIs/Tecnologias JavaTransferência de Arquivos Streams I/O; Soquetes

Bancos de Dados Compartilhados JDBC

Procedimentos Remotos (RPC) Servlets, JCA, Web Services/SOAP

Passagem de Mensagens JMS, Web Services/SOAP

Tabela 1. Tecnologias Java para suportar estilos de interoperabilidade.

Níveis de Interoperabilidade APIs/Tecnologias JavaNível de Dados JDBC

Nível de Interface de Aplicação Servlets, EJB/RMI, JCA, Web Services/SOAP, JavaMail

Nível de Processos de Negócio JBI (Java Business Integration), OpenSOA SCA

Nível de Apresentação Portlets

Tabela 2. Tecnologias Java para suportar níveis de interoperabilidade.

Topologias de Interoperabilidade APIs/Tecnologias JavaPonto a ponto Servlets, WebServices/SOAP, EJB/RMI

Hub and Spoke JBI, OpenSOA SCA

Tabela 3. Tecnologias Java para suportar topologias de interoperabilidade.

Finalmente, devemos considerar tam-bém a questão da topologia da aplicação. Dois modelos clássicos existem:1. Comunicação Ponto a Ponto. A inte-gração ponto a ponto é também chamada de integração oportunista e ocorre dire-tamente entre dois sistemas que queiram conversar. Quando conectamos uma TV diretamente a um DVD, usamos intuitiva-mente esta topologia de integração;2. Comunicação Hub and Spoke. Topolo-gia popularizada pelos ESB (um tipo par-ticular de Hub and Spoke), esta topologia usa um mediador central para comunicar cada aplicação (Spoke) que deseje conver-sar. Nenhuma aplicação conversa direta-mente com outra aplicação. Isto pode pa-recer confuso e complexo, mas considere (na sua sala de TV dos sonhos) como você poderia integrar adequadamente uma televisão digital, um computador, um sistema de som 7.1, um DVD, um vídeo-cassete (para as fitas de formatura da sua família), um projetor e um vídeo-game de última geração. É claro neste exemplo que usar um aparelho central para gerir todas as conexões é mais vantajoso. O Home-Theater é um hub na sua sala de TV dos sonhos e pode ligar todos os fios dos aparelhos (Figura 2).

Mais um desafio: Qual a topologia associada ao

exemplo citado de interoperabilidade com o Micro-

soft Exchange? (Resposta no final deste artigo).

Colete os requisitos arquiteturais de interope-

rabilidade na sua aplicação. Para cada requisito

arquitetural, defina o estilo, nível e topologia

associada.

java 69.indb 70 26/05/2009 16:37:35

Page 71: java 69 [Introdução Spring Security] [Lido]

Edição 69 Java Magazine 71

Tecnologias de Interoperabilidade Java

, Sun Tzu.A plataforma Java foi desenhada e evo-

luída nos últimos anos com um grande suporte para interoperabilidade. Conside-re como exemplo simples a especificação JDBC. Projetada de forma elegante para suportar a portabilidade de sistemas operacionais e bancos de dados, ela é um exemplo que suporta a integração do estilo (ver Tabela 1) banco de dados compartilha-dos, em nível (ver Tabela 2) de dados.

Diversas outras tecnologias foram proje-tadas para suportar outros estilos e níveis. Apresentamos alguns exemplos nas Tabe-las 1, 2 e 3, sem nos ater aos detalhes da API, que podem ser encontrados em arti-gos anteriores da revista Java Magazine.

As Tabelas 1, 2 e 3 mostram que é fun-damental escolher adequadamente a tática (tecnologia) conforme o tipo de terreno (estilo, nível ou topologia).

Padrão EAI Pergunta endereçadaComo eu posso integrar múltiplas aplicações de forma que elas possam trocar informações?

Como uma aplicação se comunica com outra através de mensagens?

Como uma aplicação se conecta a um canal de men-sagens para enviar e receber mensagens?

Como mensagens podem ser usadas para transferir dados entre aplicações?

Como mensagens podem ser enviadas para outro sistema se o originador não tem todas as informa-ções necessárias?

Como um consumidor de mensagens (ex: Microsoft Exchange) pode selecionar que tipos de mensagens ele deseja receber.

Tabela 4. Padrões EAI usados para resolver a interoperabilidade com o Microsoft Exchange.

N o t a d o D e v M a n

Diagramas de Casos de Uso:

Diagramas de casos de uso são visualizações de negócio usadas por analistas de requisitos para o auxílio na coleta e entendimento de requisitos. Estes diagramas possuem atualmente grande popularidade na comunidade de analistas e podem ser ferramentas poderosas para a coleta de interoperabilidades. No nosso exemplo, poderíamos representar a interoperabilidade do envio do e-mail com o seguinte diagrama.

Note que neste diagrama o Microsoft Exchange suporta a operação de envio de email e por isso é chamado de Ator Secundário.

Não use as tecnologias Java no primeiro combate a

um problema de interoperabilidade. A tecnologia é se-

cundária e deve ser considerada apenas após a correta

coleta e desenvolvimento dos requisitos arquiteturais e

definição dos estilos, níveis e topologia.

Padrões de Integração de Aplicações (EIP)-

damente a situação e um bom general lida cuidadosamente com ela. Se não é vantajoso, nunca envie suas tropas; se não lhe rende ganhos, nunca utilize seus homens; se não é uma situação perigosa, nunca lute uma batalha

, Sun Tzu.Conhecemos o inimigo. Conhecemos as

ferramentas. Entretanto, a grande chave na interoperabilidade de aplicações é saber como aplicar as tecnologias Java a nosso fa-vor. Neste aspecto, introduzimos o conceito de um padrão de integração de aplicações.

Um padrão EIP é uma solução provada aplicável ao

contexto de integração de aplicações corporativas.

O livro Enterprise Integration Patterns [1] apresenta 65 padrões de integração de sistemas. Cada padrão resolve um proble-ma particular no contexto de integração de aplicações corporativas e pode ser usado junto com outros padrões EIP para solucio-nar um problema do mundo real.

Consideremos, para ilustrar o conceito, um problema similar ao citado no começo deste artigo. Poderíamos formalizar os re-quisitos arquiteturais da seguinte forma:

R1. A aplicação ACME deve interoperar com o servidor Microsoft Exchange 2007 através de protocolos SMTP para envio de emails.

R2. O transporte para interoperabilidade com o servidor de emails deve garantir confidencialidade e integridade das in-formações enviadas através do uso do protocolo SMTP sobre SSL.

Ao lermos o livro EAI Patterns, captu-ramos alguns padrões candidatos para o problema acima. Estes padrões são docu-mentados na Tabela 4.

O primeiro padrão da Tabela 4 nos diz que a solução provavelmente será resolvida com um mecanismo assíncro-no. Dadas as restrições de protocolos no requisito R1, vemos que a especifi-cação Java nos sugere a especificação JavaMail.

O segundo e terceiro padrões nos diz que teremos um canal para o envio e recebi-mento de informações e este canal deve se conectar a um sistema de email como

java 69.indb 71 26/05/2009 16:37:35

Page 72: java 69 [Introdução Spring Security] [Lido]

72 Java Magazine Edição 69

o Microsoft Exchange. Ao examinarmos a classe Transport, da API do JavaMail, veremos que ela possui esta função. Natu-ralmente, um Message Endpoint requer uma implementação da especificação JavaMail. Assumamos neste exemplo que usamos o JBoss AS para esta solução.

O quarto padrão nos diz que devemos enviar um documento textual. Ao obser-vamos novamente a classe Transport, nota-mos que ela possui um método send() que

Figura 3. Esquema da solução de integração com o MS Exchange Server

espera como argumento um objeto do tipo Message, que modela um Document Message.

O quinto padrão endereça os requisi-tos de segurança. Um enriquecedor de conteúdo permite adicionar à mensagem original informações adicionais. No nosso caso, estas informações adicionais serão de segurança, que nos permite que a mensagem seja entregue em servidores que operem sobre protocolo SSL. Ao exa-minarmos a hierarquia da classe Transport,vemos a classe SMTPSSLTransport. Esta classe fornece a funcionalidade de envio de emails sobre canal seguro (confidencia-lidade e integridade).

O último padrão está fora do escopo Java, mas ele indica que alguém deve configurar o servidor Exchange para não aceitar men-sagens SMTP, mas somente mensagens SMTP sobre SSL. O padrão Consumidor Seletivo representa este mecanismo.

Listagem 1. Fragmento de Código para Envio de Email.

…Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());Properties props = new Properties();props.put(“mail.smtp.host”, SMTP_HOST_NAME); // Servidor de emailprops.put(“mail.smtp.auth”, “true”); // Requer autenticacaoprops.put(“mail.debug”, “true”); props.put(“mail.smtp.port”, SMTP_PORT); // Porto do servidor de emailprops.put(“mail.smtp.socketFactory.port”, SMTP_PORT);props.put(“mail.smtp.socketFactory.class”,“javax.net.ssl. SSLSocketFactory” ); //Enriquecedor da mensagem com SSL

props.put(“mail.smtp.socketFactory.fallback”, “false”);

Session session = Session.getDefaultInstance(props, new javax.mail. Authenticator() { protected PasswordAuthentication getPasswordAuthentication() {

return new PasswordAuthentication(“username”, “password”); }});

Message message = new MimeMessage(session);InternetAddress addressFrom = new InternetAddress(from);message.setFrom(addressFrom);message.setSubject(“OLÁ EIP”);message.setText(“Padrões EIP organizam e comunicam as soluções Java!”);Transport.send(message);...

Se conectarmos os padrões EIP teremos o desenho da nossa solução apresentado na Figura 3.

O trecho de código acima mostra estas peças conectadas.

Este fragmento de código pode ser en-tendido como a realização do esquemático da Figura 3.

Para um problema simples, naturalmen-te, podemos até ir intuitivamente para uma tecnologia ou um código, mas isso é como começar a correr uma maratona sem preparação física adequada. Os padrões representam esta preparação física. Eles permitem que você pense nos aspectos da solução sem se ater aos detalhes da tec-nologia. Ao escolheremos uma tecnologia Java determinada, ela será a conseqüência dos padrões, que naturalmente devem suportar os requisitos arquiteturais es-pecificados.

Para problemas complexos de integra-ção do mundo real, entretanto, devemos conhecer e aplicar os padrões EIP. Outra excelente fonte de padrões é o livro POSA [2], que contém mais de uma centena de padrões arquiteturais, entre eles diversos padrões EIP.

Como exemplo de padrões EIP usados para modelar aplicações com integração complexa, dita aplicações EAI, poderíamos citar os padrões descritos na Tabela 5.

Um Processo para Interoperar Aplicativos

batalha, ele pode conduzir as suas tropas para até mil milhas, mesmo para uma batalha decisiva. Se ele não sabe nem o lugar nem a hora de uma batalha, então o seu lado esquerdo não pode aju-dar a sua direita e a ala direita não pode salvar a esquerda; a tropa da frente não pode auxiliar a tropa da retaguarda, nem a tropa da retaguarda

Sun Tzu.Conhecer um processo para solucionar

problemas técnicos é fundamental. Saber a hora e o lugar das ações é fundamental, es-pecialmente nos mecanismos arquiteturais de interoperabilidade.

Podemos resumir o processo de aplicação das estratégias e padrões EIP da seguinte forma:

1. Colete os requisitos arquiteturais de interoperabilidade. Uma boa fonte para

java 69.indb 72 26/05/2009 16:37:36

Page 73: java 69 [Introdução Spring Security] [Lido]

Edição 69 Java Magazine 73

Padrão EAI Comentários

Message Broker

Captura a essência das soluções ESB de mercado. Note que o termo ESB, em sua definição original, é um padrão ou

estilo arquitetural e não uma tecnologia ou especificação.

Produtos como o JBoss ESB ou Apache ServiceMix podem ser vistos como produtos que implementam o padrão

EIP Message Broker.

Process Manager

Captura a essência das soluções BPMS de mercado. O padrão Process Manager permite que uma integração com

múltiplas fontes de dados e aplicações possam ser integradas através de um fluxo de trabalho arbitrário.

Produtos como o JBoss BPM ou IBM WebSphere Process Server são exemplos deste padrão.

A linguagem BPEL (Business Process Execution Language) é um exemplo de linguagem usada para descrever os

fluxos do padrão Process Manager.

Normalizer

Padrão usado para implementar a interoperabilidade com múltiplos protocolos em aplicações ESB.

Um produto como o JBoss ESB, por exemplo, suporta FTP, HTTP, SMTP, HTTPS e diversos outros formatos para inte-

roperar aplicações.

No interior da sua solução, vemos que o padrão Normalizer foi usado para suportar isso.

Tabela 5. Padrões EAI tipicamente usados em aplicações BPM/SOA/ESB.

isso são atores secundários em diagramas de casos de uso. Eles normalmente reve-lam sistemas e aplicações que devem ser integrados. Especifique detalhadamente estes requisitos para que não existam dúvidas sobre as versões de servidores, topologias e protocolos exatos a serem utilizados;

2. Desenvolva soluções independentes de tecnologia para cada requisito arquitetural de interoperabilidade. Para isso, identifi-que os estilos, níveis e topologias de cada requisito arquitetural de interoperabilidade.

N o t a d o D e v M a n

Processo Unificado (UP):

O UP (Unified Process) é um processo para desenvolvimento de software baseado no conceito de um projeto centrado em arquiteturas de software. Em termos simples isso significa reduzir os riscos técnicos do projeto nas suas fases iniciais através do ataque aos requisitos mais prioritários e complexos através de provas de conceito que busquem mitigar e eliminar estes riscos.

O UP possui diversas variantes como por exemplo o popular IBM Rational Unified Process, o Enterprise Unified Process de Scott Ambler ou o processo ágil OpenUP.

Expresse então a sua solução através dos padrões EIP encontrados em [1] e [2];

3. Estude os exemplos (mais complexos e além do escopo deste artigo) disponí-veis em [1];

4. Para cada solução independente de tecnologia, escolha as tecnologias Java mais adequadas para resolver o seu pro-blema. Use as Tabelas 1, 2 e 3 como ponto de partida e então estude as especificações de cada tecnologia apresentada e produtos Java que suportem estas especificações;

5. Prove a sua solução. Talvez a dica mais valiosa, a sua solução deve ser provada com um código real e que possa capturar um cenário de utilização do seu sistema;

6. Teste a sua solução em ambiente idên-tico ao de produção. Envolva o usuário e faça testes reais e significativos, pois este é o passo mais complexo. Aplicações não tes-tadas adiam riscos e podem levar a proble-mas graves no fim do projeto. Em cenários mais complexos onde você não tem acesso ao aplicativo sendo interoperado, considere o uso de ferramentas como o jMOCK ou EasyMock. Recomendo, neste particular, o excelente artigo Mocks Aren’t Stubs, de

Martin Fowler, e o artigo “Testando com Mocks de forma fácil”, Edição 62;

7. Garanta que você realizou os passos 1-5 no começo do projeto. Requisitos de interoperabilidade são complexos e devem ser endereçados no do projeto. Se você usa um processo derivado do UP (Unified Process), os itens 1-5 para todos os requisitos arquiteturais devem estar fina-lizados até o 3/10 temporal do seu projeto. Se você usa processos ágeis, enderece estes requisitos nos primeiros sprints/iterações.

ConclusõesEste artigo apresentou, de forma introdutó-

ria, princípios que devem nortear aplicações que requerem integrações de sistemas. Co-loco abaixo um guia de estudo para os mais interessados no assunto.

1. Certifique-se de conhecer os funda-mentos de integração de sistemas. Estilos, topologias e especificações são funda-mentais e livros como [1] e [2] são fontes fundamentais;

2. Estude antecipadamente as ferramentas e APIs Java para suportar os estilos e topo-logias acima;

java 69.indb 73 26/05/2009 16:37:36

Page 74: java 69 [Introdução Spring Security] [Lido]

74 Java Magazine Edição 69

3. Nunca acredite em tecnologias que não foram provadas no seu projeto. Negocie tempo do seu gerente de projeto para provar conceitos e realizar testes de integração. Se você não realizar esta negociação no começo do projeto, espere estresses, noites mal dormidas e problemas na entrega do seu código;

4. Lembre-se que o mundo não é centrado em Java. Você precisará conhecer peças e protocolos além da linguagem Java para se tornar um bom arquiteto de integrações;

5. Teste o seu código de integração. Já observei diversos problemas em projetos devido a processos de testes de integração falhos e que aconteceram literalmente na entrega do projeto.

O leitor curioso deve ter notado o uso de ícones diferenciados para representar padrões EIP. Estes ícones estão disponíveis gratuitamente em formato Visio no próprio portal de Gregor Hohpe (EAI Patterns).

Para o leitor ainda mais curioso que busca aqui as respostas para as perguntas feitas ao longo do artigo, o problema tem como solução: o estilo Passagem de Mensagens, integração em Nível de Aplicação e topologia Ponto a Ponto. Boas integrações!

Marco Aurélio S. Mendes [email protected]É consultor independente de

Arquitetura de Software e

Engenharia de Software com mais de

16 anos de experiência em projetos de TI. É também

professor de pós-graduação dos cursos de Estratégias

de Arquitetura de Sistemas do IGTI e Engenharia de

Software do IEC/PUC-Minas. Ele mantém artigos

diversos sobre Arquitetura, Java e Engenharia de

Software no seu blog http://blog.marcomendes.com.

martinfowler.com/articles/

mocksArentStubs.html

Descreve o conceito de Mocks e que ele pode ser usado para simular aplicações externas no contexto de projetos de integração de aplicações.

eaipatterns.com/

Site central dos padrões EIP e que resume muito material interessante sobre integração de aplicações.

eaipatterns.com/downloads.html

Recursos sobre EIP e em particular o stencil (plugin) Microsoft Visio para desenhar EIP.

epf.eclipse.org/wikis/openup/

Open UP. Processo de desenvolvimento gratuito baseado nos conceitos do UP.

Dê seu feedback sobre esta edição!

A Java Magazine tem que ser feita aoseu gosto. Para isso, precisamos sabero que você, leitor, acha da revista!

Dê seu voto sobre este artigo, através do link:

www.devmedia.com.br/javamagazine/feedback

seu Feedback

ssoobb

rreeeeeestaedição

Referência primária sobre a integração de apli-

cações corporativas, escrito por Gregor Hohpe,

arquiteto de soluções do Google.

Continuação do clássico livro POSA – vol 01, de

1996. O primeiro livro sobre padrões arquitetu-

rais de IT e referência obrigatória para sistemas

que requeiram integrações complexas.

Clássico livro sobre estratégias e táticas de guerra.

Ganhou popularidade recentemente no mundo

dos negócios ao ser adaptado por vários autores

para situações “militares” vividas em projetos de

TI por gerentes, analistas e desenvolvedores.

java 69.indb 74 26/05/2009 16:37:39

Page 75: java 69 [Introdução Spring Security] [Lido]

Edição 69 • Java Magazine 75

Existem momentos onde a estrutura faz toda a diferença.

Se o tempo é ruim, você encontra na Alog um porto seguro. Isto porque

sua empresa reduz custos e melhora a governança em TI. Entre em

contato e descubra porque a Alog é líder em hosting gerenciado.

REDUÇÃO DOS CUSTOS AUMENTO DA GOVERNANÇA EM TI

0800 282 3330 | alog.com.brHOSTING GERENCIADO | COLOCATION | CONTINGÊNCIA | E-MAIL CORPORATIVO | CONECTIVIDADE | SERVIÇOS PROFISSIONAIS

07_MarcoAurelio_Estrategia de integracao.indd 75 05/06/2009 16:58:11

Page 76: java 69 [Introdução Spring Security] [Lido]

76 Java Magazine Edição 69

java 69.indb 76 26/05/2009 16:37:46