Anda di halaman 1dari 119

Editores Osvaldo Doederlein (osvaldo@javamagazine.com.br) Eduardo Spnola (eduspinola@gmail.

com) Arte Diagramao - Romulo Araujo Capa - Antonio Xavier Produo Gerncia de Marketing - Kaline Dolabella Atendimento ao leitor A DevMedia possui uma Central de Atendimento on-line, onde voc pode tirar suas dvidas sobre servios, enviar crticas e sugestes e falar com um de nossos atendentes. Atravs da nossa central tambm possvel 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 atravs do telefone 21 3382-5025. Edies anteriores Adquira as edies anteriores da revista Java Magazine ou de qualquer outra publicao do Grupo DevMedia de forma prtica e segura, em www.devmedia.com.br/anteriores. Publicidade publicidade@devmedia.com.br 21 3382-5025 Anncios - Anunciando nas publicaes 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 preos e formatos de anncios. Java, o logotipo da xcara de caf Java e todas as marcas e logotipos baseados em ou referentes a Java so marcas comerciais ou marcas registradas da Sun Microsystems, Inc. nos Estados Unidos e em outros pases.

NDICE [Easy Java, Core] Um pouco de Groovy Uma linguagem de scripts simples e 100% compatvel com Java Marcelo Castellani [Core, Web] JBoss Application Server 5 As principais novidades do JBoss AS 5 Bruno Rossetto Machado e Joo Paulo Viragine [Web, Tutorial] Spring Security Segurana simples, poderosa e portvel - moda do SpringFramework Michel Zanini [Core, Web, Mobile] JavaFX Script Uma referncia didtica da linguagem JavaFX Script, uma das principais peas da plataforma JavaFX Osvaldo Pinali Doederlein [Vanguarda, Core] Novos tempos: javax.time A nova API de Data e Hora, que facilita a programao e corrige falhas histricas das suas antecessoras Daniel Cicero Amadei e Michael Nascimento Santos [Mobile] Java ME Platform SDK 3 As novidades do novo SDK para Java ME, que substitui o antigo Wireless Toolkit Ernandes Mouro Jnior [Boas Prticas] Estratgias de Integrao de Aplicaes Java EE Melhores prticas de interoperabilidade Java para o desenvolvimento de aplicaes robustas Marco Aurlio de Souza Mendes [Core, Expert] Estratgias de Integrao de Aplicaes Java EE Desenvolvendo aplicaes concorrentes estveis e escalveis com a java.util.concurrent Ronaldo Blanch Rocha

Um pouco de Groovy

Marcelo Castellani Marcelo Castellani (castellani@itautec.com) analista de sistemas snior na Itautec S/A e atua na rea de desenvolvimento desde 1996, passando por linguagens como Visual Basic, C, C++ e Java. Mantm o blog hype quino (www.hypequino.com) aonde fala de novas tecnologias em matrias curtas. De que se trata o artigo: Apresenta uma introduo a linguagem dinmica Groovy, que possibilita ter uma produtividade de linguagens dinmicas como Python e Ruby dentro da mquina virtual Java, sem emendas. Para que serve: Tornar o desenvolvimento em Java mais rpido e produtivo, alm de apresentar novos conceitos, como closures, no disponveis na linguagem Java, que podem facilitar a vida do desenvolvedor em tarefas corriqueiras. Em que situao o tema til: Para agilizar o desenvolvimento de aplicaes Java, otimizando situaes onde a mesma muito verbosa, como manipulao de XML por exemplo. Groovy possibilita, atravs de mecanismos como closures, uma sintaxe mais limpa e produtividade em alto nvel. Um pouco de Groovy: possvel programar para a plataforma Java sem usar a linguagem Java, e ainda por cima ser extremamente produtivo. Groovy uma linguagem dinmica, flexvel e que se integra com Java sem emendas, alm de fornecer recursos como closures e atribute accessors, no disponveis na linguagem padro da JVM. Groovy, ao contrario de outras linguagens dinmicas, possibilita gerar bytecodes Java e possibilita o uso de toda a infra-estrutura j desenvolvida para suas aplicaes. Introduo Linguagens dinmicas esto 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 saram de seus nichos e passaram a fazer parte das rodinhas de conversa de desenvolvedores Java, outrora um tanto quanto seletivos. Esses, ento, descobriram um admirvel novo mundo, com closures, tipos de dados complexos e facilidades que no existem na sua linguagem preferida. Foi mais ou menos nesse meio que surgiu o embrio do que viria a ser o Groovy. Como tudo comeou No dia 29 de agosto de 2003 James Strachan publicou em seu blog o primeiro artigo sobre aquilo que viria a ser o Groovy (veja em Links o endereo do post). Ele deixava bem claro as suas intenes na poca: minha idia inicial fazer uma pequena linguagem dinmica, 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 cdigo Java j existente. James procurava uma linguagem dinmica para desenvolver em plataforma Java, e em seu post ele deixava claro que as opes da poca no eram interessantes. Ele no queria apenas uma linguagem dinmica, mas sim algo que pudesse ser integrado ao que ele j tinha pronto em Java, algo que acelerasse seu desenvolvimento e que no o obrigasse a jogar tudo o que tinha de cdigo Java j pronto e testado (e em produo) no lixo. Enfim, ele queria algo que no 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 idia, iniciaram o desenvolvimento da linguagem. Foi em 2004, com a fundao 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), alm do parser bsico da linguagem. O embrio do projeto estava pronto e a partir da no teria mais como voltar atrs.Groovy

evoluiu desconhecido por algum tempo, e at dezembro de 2007 vrias verses foram lanadas sob o nmero 1.1.x. Em 7 de dezembro de 2007 a verso final da famlia 1.1 foi lanada, e ento nomeada Groovy 1.5 devido s diversas modificaes realizadas na mesma. Hoje a linguagem uma especificao do JCP (JSR 241) e considerada a segunda linguagem oficial da plataforma.Ao contrario do que alguns pensam, Groovy no um concorrente do Java, mas uma ferramenta de apoio, como veremos neste artigo. O que Groovy? O web site oficial da linguagem possui uma das melhores definies sobre a linguagem, a qual reproduzo a seguir: Groovy uma linguagem gil e dinmica para a Plataforma Java com recursos que so inspirados em linguagens como Python, Ruby e Smalltalk, tornando-os disponveis aos programadores Java, usando uma sintaxe mais prxima do Java. Ou seja, Groovy possui uma sintaxe semelhante ao Java, mas com o poder de linguagens dinamicamente tipadas. Mas Groovy no apenas uma linguagem de script. Groovy pode ser compilada, gerando bytecodes Java, ou seja, um arquivo de cdigo fonte Groovy pode virar um arquivo .class (e esse recurso voc no encontra por exemplo no JRuby). Isso garante que a nica coisa que voc precisa para rodar seus cdigos Groovy no ambiente de produo a mquina 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 integrado com o Java sem emendas, o que no acontece com seus concorrentes, por assim dizer. Mais do que isso, o Groovy totalmente integrado ao Java no mais baixo nvel. Por exemplo, se voc instanciar um objeto do tipo Date em Groovy esse nada mais do que uma instncia de java.util.Date. E tudo funciona de maneira transparente por que, por debaixo dos panos, tudo bytecode Java. A voc me pergunta ok, ento 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 no so encontrados na linguagem Java, como closures.E Groovy possui um grande aliado, o Grails, um framework de produtividade baseado em Spring e Hibernate que permite o desenvolvimento de aplicaes Java EE com a mesma agilidade do pessoal do Ruby on Rails (e sem configurar centenas de arquivos XML!). Outro ponto importante que ambos, Groovy e Grails, so hoje propriedades da SpringSource, empresa que mantm o framework Spring. A empresa adquiriu a G2One, que cuidava de ambos, em 11 de novembro de 2008 e em seu site (novamente na seo Links) possvel 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/compilador e outras ferramentas. Felizmente o NetBeans nos fornece tudo o que precisamos (e at mais) num nico pacote.O NetBeans uma excelente IDE mantida 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 verso 6.5 da IDE rodando no Mac OS X verso 10.5.6. Voc pode baixar gratuitamente o NetBeans de seu site (veja o endereo no quadro Links). Caso deseje usar o Eclipse (que tambm suporta Groovy via plugins) ou outra IDE para testar os cdigos deste artigo, ou mesmo um editor de textos simples como o GEdit do Gnome ou o Notepad do Windows, voc dever configurar o ambiente. Para isso recomendo que acesse a pgina do projeto na internet. Porm, caso ainda no 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 comear nossa viagem pelo admirvel 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 suficiente para apresentar muitos recursos, 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 aplicao Java. Voc ver uma categoria Groovy na janela de Novo Projeto, mas ela tem apenas um template para a criao de um projeto Grails. Como este no o escopo deste artigo vamos ignorar essa categoria de projetos. Para isso use a categoria Java, como na Figura 1. Clique no boto Prximo e ento informe 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 no colocamos nem um pouco de Groovy no projeto, ele um tradicional e simples projeto de aplicao Java que voc j conhece.

Vamos adicionar ento o Groovy ao projeto. Para isso clique com o boto 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 opo Ativar Groovy, como na Figura 2.

Figura 1: Criao de um novo projeto Java.

Figura 2: Adicionando Groovy ao projeto


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 mgica para ns.

Figura 3: Nosso projeto agora tem Groovy.


Por padro o NetBeans criar um arquivo .java no nosso projeto. Remova-o pois no o usaremos, e ento crie um pacote chamado org.groovy.maonamassa para adicionarmos os cdigos-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.

Figura 4: Um JFrame com uma caixa de texto dentro.


Agora vamos adicionar um arquivo .groovy em nosso projeto. Para isso clique sobre o pacote criado e clique com o boto de atalho do mouse. Selecione ento a opo 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 no faz essa diferenciao como o Java. Vamos adicionar o cdigo nossa classe Groovy. Para isso, digite o cdigo da Listagem 1. Listagem 1. Nossa classe Groovy package org.groovy.maonamassa class AloMundoGroovy { def saudacao = "Al mundo, em Groovy !!!!"

} Perceba que no usamos ponto-e-vrgula no final de nossa declarao, e que usamos a palavra reservada def na criao de nosso objeto (sim, objeto, da classe Object). O restante deve ser conhecido para programadores Java. Nossa classe Groovy est pronta para uso. Basta editarmos o cdigo de nosso JFrame para colocar tudo em funcionamento. O cdigo do JFrame dever ficar como apresentado na Listagem 2. Listagem 2. O cdigo 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") // private void initComponents() { jTextField1 = new javax.swing.JTextField(); setDefaultCloseOperation(javax.swing. WindowConstants.EXIT_ON_CLOSE); getContentPane().add(jTextField1, java.awt.BorderLayout.CENTER); pack(); }// /** * @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 } Repare na linha em negrito, nela que chamamos o mtodo getSaudacao() de nossa classe Groovy. Se

voc olhou o cdigo da Listagem 1 e no achou esse mtodo no se preocupe, ele criado atravs 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 cdigo. 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 automaticamente os getters e setters. A mesma classe da Listagem 1, escrita em Java, teria o dobro do tamanho. Veja na Listagem 3. Listagem 3. Nossa classe AloMundoGroovy em Java - um tanto quanto prolixo , no acha? package org.groovy.maonamassa; public class AloMundoJava { String saudacao = new String(); public String getSaudacao() { return saudacao; } public void setSaudacao(String saudacao) { this.saudacao = saudacao; } }

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 invs de sete), e ambos funcionam bem juntos, como possvel ver na Figura 5.

Figura 5: Nosso projeto em execuo.


O leitor mais atento deve ter reparado no .toString() junto ao nosso mtodo getSaudacao(), 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 no definimos o tipo de nosso objeto no momento da sua criao com o def. Listagem 4 e remova o .toString() da Listagem 2. Verifique que agora ambos os mtodos getter e setter trabalham com String e no com Object. possvel ser menos verboso ainda e deixar de utilizar o def, pois ele pode ser omitido quando especificamos o tipo do objeto. Listagem 4. Nossa classe Groovy modificada package org.groovy.maonamassa class AloMundoGroovy { // aqui voc pode omitir o def def String saudacao = "Al mundo, em Groovy !!!!" }

GDK Assim como o Java possui a JDK, o Groovy possui a GDK. fcil confundir-se quando pensamos nisso pois todo objeto Java pode ser usado dentro do Groovy, mas o contrario no verdade. A GDK estende a JDK adicionando mtodos que no existem originalmente nos objetos Java. Um exemplo seria como obter o tamanho de uma determinada instancia de uma classe. Em Java isso bem confuso pois existem objetos que usam o mtodo length() (como os que so instancias de arrays e Strings), outros usam o mtodo size() (como os que so instancias de Collections e Maps). Temos at um getLength()(para java.lang.reflect.Array) e o mtodo groupCount(), para instancias da classe Matcher. Groovy, atravs de um dispositivo chamado MetaClass, possibilita que todos esses objetos utilizem um mesmo mtodo para obter o tamanho de um objeto: o size(). Isso possibilita termos o cdigo da Listagem 5, onde temos tanto um ArrayList quanto uma String usando o mesmo mtodo, o size(). 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() } } Outra vantagem do GDK sobre a biblioteca padro do Java que Groovy no diferencia entre tipos primitivos e objetos. Em Groovy a expresso valor01 + valor02, considerando valor01 e valor02 do tipo java.lang.Integer, retorna a soma dos dois inteiros. Mas o Groovy vai alm, definindo uma equivalncia entre operadores e mtodos: no caso, a expresso acima ser interpretada como valor01.plus(valor02). Se voc quiser criar novas classes com suporte a operadores, basta definir nela o mtodo que ser chamado para cada operao (para + o mtodo o plus(), para - o mtodo o minus(), para ++ next() e por a vai - consulte a documentao do Groovy para a lista de mtodos e operaes correspondentes). Pense na utilidade prtica disso. Quantas vezes voc j no teve uma classe em que seria conveniente usar o operador + para somar uma instncia com outra e teve que apelar para mtodos mirabolantes como somaClasse() ou append()? Em Groovy basta definir o mtodo correto e, ao avaliar a operao, o Groovy procura o mtodo correspondente. Isso s possvel por que o Groovy usa o conceito de MetaClass apresentado acima. Quando o compilador encontra uma expresso como valor01 + valor02 num cdigo Groovy, ele gera um bytecode diferente do que gera quando encontra essa mesma expresso num arquivo de cdigo Java, pois chamadas de mtodos so redirecionadas pelo MetaClass do objeto, o que possibilita ao Groovy interceptar, adicionar, redirecionar e remover cdigo em tempo de execuo. esse truque que possibilita valor01 + valor02 tornar-se valor01.plus(valor02) em tempo de execuo. Claro que todo esse poder tem um preo: um cdigo Groovy ligeiramente mais lento do que um cdigo Java durante a execuo, 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 optaramos por Java quando precisamos de velocidade, e por Groovy quando precisamos de facilidades e performance no um dos requisitos principais. Pode parecer, com todo esse

pargrafo, que Groovy um elefante pesado e lento, mas Groovy apenas um pouco mais lento que Java. Na Listagem 6 possvel encontrar um exemplo de como sobrescrever o operador + atravs do uso do mtodo plus(). Criei uma classe chamada SomaODobro que, quando tem duas instncias somadas, realiza a adio e depois a multiplicao para retornar o resultado. Veja o cdigo. 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 } }

importante ressaltar que sim, possvel, em Groovy, ter mais de uma classe dentro de um arquivo de cdigo fonte como visto acima. As classes podem, inclusive, ser pblicas, ao contrrio do Java, onde podemos ter apenas uma classe pblica por arquivo. Veja nas Listagens 7 e 8 um exemplo simples. Listagem 7. Um arquivo Groovy com duas classes pblicas 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(); } Closures Um dos recursos mais teis e apaixonantes de linguagens dinmicas so os closures, ou fechamentos, ou blocos, que do um poder de fogo enorme no desenvolvimento. Closures nada mais so do que pedaos de cdigo tratados como objetos, e como tal podem receber parmetros e retornar valores. E como a JVM no sabe se o cdigo que est rodando Groovy ou Java, perfeitamente possvel dizer que um closure apenas mais objeto para a JVM, tal qual uma String ou um Integer. Uma aplicao robusta e poderosa de closure na classe File da GDK. O Groovy estende o objeto File padro do Java e adiciona um mtodo eachLine(), que recebe como parmetro um closure: new File(arquivo.txt).eachLine { println it } O closure nada mais do que o bloco { println linha }, que ser executado para cada iterao 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 sada padro usando o println() (o it representa a linha recebida). Tudo isso em apenas uma linha de cdigo. Outro exemplo bem interessante apresentado a seguir, onde temos um tipo de dado do Groovy (o Range, que um intervalo representado com dois nmeros separados por dois pontos simples, como em 1..100, que inclui os nmeros de 1 a 100); e o mtodo each(), que varre cada membro do Range, e depois executa a closure que o imprime. (1..10).each { println it } Ok, mas o que esse tal de it no meu cdigo? Ele uma varivel conhecida como Magic variable, ou varivel mgica, algo que no precisa ser declarado pra existir. it pode ser visto como um membro da classe que define os closures do Groovy, ele quem recebe o parmetro padro quando esse no declarado. Veja como fica a opo de uso de uma varivel explcita no lugar da varivel mgica. (1..10).each { valorAtual -> println valorAtual } o sinal de -> que separa a declarao de variveis do corpo do closure. Mas closures no so teis apenas para imprimir um valor na sada padro, eles podem ser usados para operaes complexas, sua imaginao o limite. O poder dos closures Vamos criar um exemplo pra demonstrar um pouco do poder e da elegncia do uso de closures. Crie um novo projeto Java e adicione Groovy a ele como visto anteriormente. Adicione uma nova classe Groovy chamada Aluno e ento insira o cdigo da Listagem 9. 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() } } Nessa classe temos duas propriedades, o nome do aluno e o nmero de sua matrcula. O nome dever ser informado no momento da criao do objeto, atravs de nosso construtor e o nmero da matrcula sugerido atravs do uso de um membro esttico que incrementado a cada nova instancia criada (perceba que esse recurso no deve ser usado em situaes reais, mas encaixa como uma luva nesse exemplo). Redefinimos tambm o mtodo toString(), para possibilitar uma impresso simplificada de nossos valores, quando necessrio. Perceba que fao uso dos getters e setters sem os declarar pois, como foi visto antes, eles so criados automaticamente quando definimos membros de classe sem especificar sua visibilidade. Na Listagem 10 instanciamos, em um arquivo main.java trs objetos de nossa classe e imprimimos seus dados, usando o toString(). Listagem 10. A classe Main.java, instanciando trs 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()); } } O resultado ser algo como: Matricula: 1 Nome: Marcelo Matricula: 2 Nome: Giuliana Matricula: 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. 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() } } } Modifique o arquivo Main.java para que fique como na Listagem 12. 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(); } } Ao chamarmos o mtodo imprimeListaAlunos() faremos uso de um closure para percorrer todos os membros do ArrayList da classe Aula (atravs do each()). Agora faa um teste e escreva as classes Aluno e Aula em Java e veja quantas linha a mais de cdigo seriam necessrias para o mesmo resultado. A maior parte das linguagens e recursos que se prope a enxugar o cdigo o faz s custas de clareza. Isso no acontece em Groovy: o cdigo continua perfeitamente legvel, mesmo com linhas a menos. Em alguns casos, como no exemplo acima, at mais fcil ler um cdigo Groovy do que um cdigo Java. Para onde ir agora? Groovy extremamente poderosa e pode lhe ajudar muito em seus projetos Java. Ela particularmente til para processamento de texto graas a um poderoso suporte a expresses regulares, para processamento de listas e de arquivos graas ao uso de closures e principalmente para o processamento de XML, onde o Java deveras confuso e prolixo. Alm disso Groovy a base do Grails, framework de produtividade para o desenvolvimento de aplicaes web que une a poderosa infra-estrutura do Spring e Hibernate simplicidade das idias do Ruby on Rails. Grails possibilita o desenvolvimento de aplicaes complexas de maneira rpida e indolor, gerando uma aplicao web totalmente compatvel com Java EE em um arquivo .war. Para aprender mais sobre Groovy d uma olhada na pgina do projeto na web. Existem dzias de exemplos e informao relevante para que voc torne-se produtivo rapidamente. Alm disso, interessante dar uma olhada no livro Groovy em ao, escrito por Dierk Knig junto a Andrew Glover, Paul King, Guillaume Laforge (o mantenedor do projeto) e Jon Skeet, publicado pela editora AltaBooks. (O original, Groovy in action, publicado pela Manning, caso ingls no seja um problema). Groovy simples e poderoso e merece sua ateno. O tempo que ir ganhar quando comear a us-lo compensar e muito seu aprendizado. Links http://radio.weblogs.com/0112098/2003/08/29.html Post de James Strachan, onde surgiu a idia sobre o Groovy http://www.springsource.com/node/836 Pgina da SpringSource comentando a compra da G2One http://www.netbeans.org Site do NetBeans, a nica IDE que voc precisa http://grails.codehaus.org Site do Grails, framework para aplicaes web que usa o Groovy como base http://groovy.codehaus.org

Site do Groovy Saiba Mais www.devmedia.com.br/articles/viewcomp.asp?comp=11412 Auditrio Virtual DevMedia - Groovy na web com Struts 2 www.devmedia.com.br/cursos/listcurso.asp?curso=55 Curso Online - Introduo ao Groovy www.devmedia.com.br/articles/viewcomp.asp?comp=8982 Java Magazine 32 - Groovy: Java Atravs de Scripts

JBoss Application Server 5

Joo Paulo Viragine bacharel em Cincia da Computao pela Unesp. Trabalha como Arquiteto de Solues na JBoss, a division of Red Hat, onde uma de suas atribuies ser o evangelista oficial de Seam no Brasil. Acumula cerca de 7 anos de experincia na tecnologia Java, tendo atuado em projetos da rea de Governo e Finanas. Possui as certificaes: SCJP e SCWCD.

Bruno Rosseto bacharel em Sistemas de Informaco pela Universidade Mackenzie e atua com desenvolvimento de software com a plataforma Java h quatro anos. Possui experinciaem projetos Java EE nas reas automotivas, e-commerce,e outros projetos de misso crtica. Participou do projeto ganhador do Duke s Choice Awards de 2005 - SIGA Sade. Atualmente consultor da Summa Technologies do Brasil. De que se trata o artigo: Aps trs 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 diferenas em relao sua antecessora baseada no JBoss Microkernel. Alm disso, detalhar as principais novidades em mensageria, clustering, balanceamento de carga, cache, transaes e monitorao. Para que serve: O JBoss Application Server 5 serve para disponibilizar os recursos necessrios execuo de aplicaes Java EE 5. Sua arquitetura flexvel permite total controle, customizao e tuning, conforme as necessidades do desenvolvedor. Alm disso, sua instalao simples e rpida. Em que situao o tema til: O artigo atualiza o leitor em relao s mudanas mais expressivas da nova verso do JBoss Application Server, o servidor de aplicaes mais utilizado do mundo.

JBoss Application Server 5: O JBoss Application Server 5 resultado de trs anos de pesquisas e desenvolvimento, que culminou em um total redesenho da arquitetura interna do servidor de aplicaes. Alm da compatibilidade total especificao Java EE 5 e do suporte ao JDK 6, a principal caracterstica dessa nova verso a substituio do JBoss Microkernel pelo JBoss Microcontainer. Com o JBoss Microcontainer, possvel desenvolver servios baseados em POJOs, no sendo mais necessrio implementar MBeans. Com isso, a integrao de novos mdulos torna-se ainda mais dinmica e rpida, o que facilita customizar, excluir ou acoplar novos servios. possvel tambm integrar componentes baseados nos antigos MBeans, mdulos OSGi, entre outros. Houve tambm mudanas significativas no mecanismo de classloader para a utilizao do Virtual Deployment Framework (VDF), o qual garante que toda dependncia do deploy seja satisfeita antes da disponibilizao do servio. Os principais mdulos tambm sofreram evolues, como: clustering, mensageria, cache, binding de portas, etc. A interface grfica do novo JBossAS tambm foi atualizada, e foi criado o projeto Jopr - uma interface web para monitorao e controle de toda a infraestrutura JBoss, o que possibilita, entre outras coisas: a criao de novos datasources, deploy de pacotes, monitorao de pools de conexo, mantendo um histrico de aes e grficos para futuras consultas. Dessa forma, ficou muito mais fcil cuidar dos seus JBosses. O lanamento do JBoss AS 5 apenas o comeo de uma nova era para os projetos JBoss, uma vez que outras solues, como a Plataforma SOA, Portais, etc., podero usufruir desse robusto e performtico servidor de aplicaes. A verso 5 do JBoss Application Server, que a partir desse momento chamaremos simplesmente AS5, foi resultado de uma maratona de trs anos de pesquisas e desenvolvimento que culminou em um total redesenho da arquitetura interna do servidor de aplicaes. Essa verso marca o incio de uma nova era para o servidor de aplicaes mais popular, querido e utilizado do mundo. No se trata apenas de uma nova verso do servidor de aplicaes, mas de todo um ambiente em estado da arte para execuo da prxima gerao de projetos desenvolvidos pela JBoss. Sobre a JBoss JBoss, apesar de ser sinnimo de servidor de aplicaes, no 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 persistncia ORM (Object Relational Mapping) mais utilizado do mundo e que muito influenciou a especificao 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 componentes de negcio EJB 3.0, aumentando a produtividade e disponibilizando inmeros componentes para facilitar e acelerar o desenvolvimento de aplicaes corporativas em Java. O reconhecimento do poder do JBoss Seam por parte da comunidade deu origem JSR 299 - Web Beans. Ver Edio 58. Alm de influenciar o futuro da plataforma Java EE, seja com participaes nas JSRs, seja com a implementao de referncia de JSRs, a JBoss conta hoje com a participao de brasileiros, funcionrios da Red Hat Brasil, como principais desenvolvedores em diversos projetos da comunidade JBoss, dedicando-se em tempo integral a atividades de desenvolvimento e suporte a clientes. Dentre esses projetos, podemos destacar: o prprio JBoss AS, o JBoss Rules - motor de regras e BRMS (business rule management system), JBoss AOP - framework para AOP (programao orientada a aspectos), JBoss SX (framework de segurana da JBoss), JBoss Profiler (ferramenta de profiling baseada em log), JBoss Messaging (JMS provider), JBoss ESB (para integrao SOA, ver Edio 59) e JBoss Portal (soluo 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 funcionrios da Red Hat/JBoss, inegvel a contribuio da comunidade durante todos esses anos de existncia da jboss.org. Essa

contribuio de extrema importncia para a sobrevivncia e qualidade dos projetos. A contribuio no feita apenas com desenvolvimento de cdigo fonte, mas tambm com participao em fruns de discusso, relato de bugs, pedido de novas funcionalidades, elaborao/traduo de documentao, blogs pessoais, eventos organizados pela comunidade, etc. Veja os links de referncia no final do artigo para saber mais informaes sobre como contribuir com a comunidade JBoss Novidades Uma das novidades da verso 5 do JBoss AS a compatibilidade total especificao Java EE 5. Apesar de a verso 4.x j suportar grande parte da especificao Java EE 5 (EJB 3.0, JPA, JAX-WS, etc.) e ser um dos primeiros servidores de aplicaes a suportar a especificao de EJB 3.0, o suporte Java EE 5 no era completo nem certificado. A certificao era uma caracterstica bastante requisitada por clientes corporativos da Red Hat, principalmente em relao garantia de compatibilidade das aplicaes desenvolvidas. O suporte ao JDK 6 tambm uma novidade dessa verso. Apesar de suportar o Java 6 desde a verso 4.2, na verso 5 que esse suporte foi aprimorado e tornou-se padro para execuo do servidor de aplicaes. Alm da certificao Java EE 5 e do suporte ao Java 6, o destaque dessa verso, sem dvida nenhuma, fica a cargo do JBoss Microcontainer. O AS5 faz parte de uma nova gerao do servidor de aplicaes, construdo com base no novo JBoss Microcontainer. O JBoss Microcontainer resultado de uma completa reescrita do JBoss JMX Microkernel (utilizado nas verses das sries 3.x e 4.x do JBoss AS) e o substitui completamente para suportar a utilizao direta de POJOs e o uso como um projeto independente do servidor de aplicaes JBoss, seguindo a tendncia e evoluo do desenvolvimento Java EE com a utilizao de novos paradigmas como AOP, injeo de dependncia e inverso de controle, e o foco na utilizao de POJOs (como EJB 3.0, JPA, Spring, Guice, entre outros). O AS5 utiliza o JBoss Microcontainer para fazer a integrao dos servios disponibilizados pelo servidor de aplicaes, entre eles: container Servlet/JSP; container EJB; gerenciador de deploy, entre outros, disponibilizando, assim, um ambiente Java EE padro. O JBoss AS no um servidor de aplicaes monoltico - com um nico kernel fornecendo os servios requeridos pela especificao Java EE - mas sim, uma coleo de componentes independentes e interconectados, cada um deles com foco em uma funcionalidade especfica requerida pela especificao Java EE. Essa arquitetura flexvel possibilita que novos servios possam ser facilmente adicionados e os servios desnecessrios possam ser removidos. Se houver necessidade de um servio adicional, simplesmente fazemos o deploy do servio desejado. De maneira anloga, se no precisamos de um servio, podemos simplesmente remov-lo. A Figura 1 mostra uma viso geral de como os servios so associados e disponibilizados pelo Microcontainer. Como resultado, temos um servidor de aplicaes totalmente customizado s nossas necessidades, com o uso eficaz de recursos do servidor fsico (CPU, memria, disco).

A flexibilidade tamanha, que os servios construdos com base no JBoss Microcontainer podem ser utilizados de maneira independente em outros ambientes/servidores de aplicaes no 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 extremamente leve, pode ser utilizado para disponibilizar servios at mesmo em um ambiente Java ME. Desse modo, abre-se um novo horizonte de possibilidades para aplicaes mveis que passam a usufruir dos servios enterprise, sem a necessidade de utilizao de um ambiente/servidor Java EE completo. O JBoss Microcontainer utiliza o conceito de injeo de dependncias (IoD) para interconectar e disponibilizar os servios do servidor de aplicaes. Alm disso, pode ser utilizado como container de injeo de dependncias de propsito geral ao estilo Pico Container

e Spring. Como amplamente consolidada no Java 5, toda configurao do JBoss Microcontainer pode ser realizada atravs de anotaes ou XML, dependendo do local onde a informao de configurao est localizada (classes Java ou arquivos de configurao). Alm de tudo isso, o JBoss Microcontainer possui classes de testes utilitrias que estendem o JUnit e tornam a configurao e a execuo de testes unitrios uma tarefa extremamente simples, permitindo que o desenvolvedor acesse POJOs e servios nas classes de testes com apenas algumas linhas de cdigo. Todo o mecanismo de classloader do JBoss AS tambm foi modificado para utilizar o avanado conceito do Virtual Deployment Framework (VDF). O VDF foi desenvolvido para abstrair, simplificar e unificar a manipulao de arquivos pelo servidor de aplicaes. Denominado Virtual File System (VFS) Class Loader, esse novo mecanismo de classloader, alm do uso do VDF para localizar bibliotecas e classes, faz uso extensivo de AOP para aspectizar o deploy de aplicaes/servios no servidor de aplicaes. O VFS faz a anlise dos deploys produzindo meta-informaes que sero utilizadas pelo JBoss Microcontainer para instanciar, interconectar e controlar o ciclo de vida e dependncia dos deploys. O JBoss Microcontainer utiliza uma mquina de estados para garantir que toda e qualquer dependncia do deploy seja satisfeita antes de disponibilizar o servio. Modularizao dos servios - Maior possibilidade de escolha e flexibilidade Um grande avano do AS5 foi a modularizao dos servios internos do servidor de aplicaes em projetos independentes. Essa modularizao no traz impactos diretos para o usurio final, mas faz parte de uma importante estratgia da JBoss em disponibilizar os vrios servios Java EE como projetos independentes. Assim, esses servios podem ser consumidos a la carte em diferentes ambientes, e no apenas no prprio servidor de aplicaes, o que permite grande flexibilidade e liberdade de escolha. Remover servios to simples quanto adicionar novos. Muitas das principais funcionalidades do AS5 so providas da integrao de vrios outros projetos JBoss, entre eles: JBoss EJB 3.0 - Implementao da ltima verso da especificao EJB 3.0 - A especificao de EJB 3.0 faz parte de uma total reestruturao da especificao EJB. E tem por objetivo a simplificao do desenvolvimento; JBoss Messaging - Reescrita completa do antigo JBossMQ (que o provedor JMS padro no JBoss AS das sries 4.x). uma implementao de JMS de alta performance compatvel com a JSR-914, com suporte out-of-thebox a cluster de filas e tpicos, com tolerncia a falhas transparente e um sistema de redistribuio de mensagens inteligente. hoje o provedor de mensageria padro do AS5, alm de ser parte integrante da infraestrutura do JBoss ESB; JBoss Cache - a implementao de cache utilizada no AS5. utilizado principalmente em conjunto com o JGroups para fornecer uma soluo completa de cluster. Entre as diversas caractersticas est o buddy replication: permite que o cache seja replicado apenas para um buddy (companheiro) no cluster, evita a sobrecarga de outros ns no cluster sem necessidade, realiza uma espcie de backup do estado do n; JBoss WS - Implementao da pilha de web services compatvel com a especificao JAX-WS 2.0/JAXRPC. Alm de implementar toda a especificao de Web Services, foi criada uma camada de abstrao que possibilita que se pluguem outras implementaes. Por exemplo: podemos utilizar a implementao nativa do JBoss WS, o Metro (implementao de web services da Sun), ou ainda o CXF (implementao da Apache), sem qualquer tipo de impacto sobre o JBoss AS. Assim, o usurio tem total liberdade para escolher a implementao que melhor se adapta s suas necessidades. No final do ms de maro, foi anunciado que os esforos sero focados em uma nica implementao: JBossWS-CXF, ou seja, as prximas verses do JBoss AS viro com o CXF nativo. Aqueles que usam o JBoss WS nativo no precisam se preocupar, pois a transio ser realizada gradativamente e trar grandes benefcios, principalmente no que diz respeito a solues SOA; JBoss Transactions - o gerenciador de transaes padro no AS5. O JBoss Transactions foi adquirido em

2005 da Arjuna/Hewlett-Packard - um gerenciador de transaes extremamente rpido e robusto. Resultado de mais de 18 anos de experincia dos seus criadores em gerenciamento de transaes, foi a primeira implementao de JTA e JTS do mercado; JBoss Web - o container Web/Servlet do AS5, comumente conhecido como "Tomcat on stereoids". Tem sua implementao baseada no Apache Tomcat 6.0 e inclui suporte a conectores baseados no Apache Portable Runtime (APR) para alcanar maior performance e escalabilidade, podendo, em alguns casos, equiparar-se ao Apache HTTP Server ou at super-lo; JBoss Security - Alm do suporte a JAAS, foi atualizado para suportar mecanismos de autorizao plugveis: SAML, XACML e SSO. A Tabela 1 compara os principais servios utilizados no AS5 e no seu sucessor (JBossAS 4.2.3), para facilitar a visualizao da evoluo de verses entre os dois.

Tabela 1: Matriz de comparao de verso entre o JBossAS 4.2.3 e o JBossAS 5


O AS5 suporta nativamente POJOs, MBeans e OSGi bundles (com ajuda do Apache Felix). Suportar um novo modelo de componentes to simples quanto implementar uma nova fachada para o JBoss Microcontainer. Isso permite que o JBoss AS suporte qualquer outro modelo de componentes existente ou que ainda est por vir; j est preparado, portanto, para o sistema de mdulos que ser implementado no Java 7. Novidades em Cluster Uma das melhorias no AS5 foi a criao de um novo mecanismo de integrao entre o JBoss Cache e o Hibernate/JPA para a utilizao de Second Cache Level (ou cache L2, introduzido no Hibernate 3.3). Existem basicamente quatro tipos de objetos que podem participar de um Second Cache Level: entidades, collections, resultados de query e timestamps. Nas verses 4.x, apenas um nico cache podia ser utilizado para armazenar 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 lentido na busca de objetos na rvore de cache. Essa verso tambm permite buddy replication de Stateful Session Beans. Com buddy replication, possvel diminuir a carga de memria e o trfego na rede. A Figura 2 mostra uma arquitetura com seis ns, onde cada n possui os seus dados e um cache do n anterior. Quando ocorre queda de um dos ns, automaticamente o n que possua o cache do n em queda assume o comando, guardando tambm o cache do n anterior, fechando o crculo. 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 verses 4.2.x, buddy replication era configurada no arquivo $JBOSS_HOME/server/all/deploy/jbossweb-cluster.sar/META-INF/jboss-service.xml (apenas camada web). J o AS5 centraliza toda a configurao de cache no servio chamado Cache Manager, que est localizado em $JBOSS_HOME/server/all/deploy/cluster/jboss-cache-manager.sar. Com a utilizao do JBoss Messaging em vez do JBossMQ, a clusterizao do provider de mensageria tambm mudou. O antigo JBossMQ era executado em modo HA-Singleton, ou seja, apenas uma instncia de JBoss executava o provider de mensageria por vez. Com o JBoss Messaging, possvel ter todos os ns ativos para o servio de mensageria, proporcionando um balanceamento de carga entre os diversos ns, caso ocorra uma sobrecarga no servidor. Para que as filas sejam consideradas clusterizadas,

necessrio adicionar o atributo Clustered com valor True na declarao da Queue ou Topic, conforme mostra a Listagem 1. 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> A configurao do servio de portas tambm mudou. Com a utilizao de POJOs e AOP no Microcontainer, as portas agora so injetadas conforme a necessidade da configurao. O servio ServiceBindingManager o responsvel por fazer a associao entre as portas e cada um dos servios, por exemplo, HTTP na porta 8080, AJP na porta 8009, etc. Na verso 5.0, ocorre uma chamada ao arquivo bootstrap.xml (Listagem 2), que o responsvel por carregar algumas configuraes em tempo de inicializao. O bootstrap.xml est configurado para utilizar o arquivo de configurao de portas bindings.xml, o qual j possui algumas configuraes pr-definidas que podem ser utilizadas e customizadas conforme a necessidade do usurio. 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> A Listagem 3 mostra a injeo das configuraes de portas disponveis. No caso, esto sendo injetadas as configuraes de PortsDefaultBindings, Ports01Bindings, Ports02Bindings e Ports03Bindings. Listagem 3. Trecho do arquivo bindings.xml - definio de alias <bean name="ServiceBindingStore" class="org.jboss.services.binding.impl. PojoServiceBindingStore"> <!-- 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> A definio das configuraes PortsDefaultBindings e beans do tipo ServiceBindingSet (Listagens 4 e 5). Ports01Bindings realizada com a injeo de

Listagem 4. Trecho do arquivo bindings.xml - definio 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 cant be applied --> <parameter><null/></parameter> </constructor> </bean> Listagem 5. Trecho do arquivo bindings.xml - definio de Ports01Bindings <bean name="Ports01Bindings" class="org.jboss.services.binding.impl. ServiceBindingSet"> <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 cant be applied --> <parameter><null/></parameter> </constructor> </bean> O trecho referente a port offset atua diretamente na configurao de StandardBindings (Listagem 6), realizando uma somatria no valor de cada porta. No caso, o PortsDefaultBindings ir manter as configuraes conforme esto no arquivo, pois seu port offset est definido com valor 0, porm a configurao Ports01Bindings ir somar 100 em cada uma das portas. Portanto, para o Ports01Bindings, a porta 1099 ser 1199, a porta 1098 ser1198, a porta 8080 ser 8180, e assim por diante. Listagem 6. Trecho do arquivo bindings.xml - definio de StandardBindings - portas padro <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> $JBOSS_HOME o diretrio de instalao do JBoss AS5. $PROFILE o diretrio referente ao profile/configurao, por exemplo: default, all, web, etc. As portas padro do JBoss Application Server so definidas no bean StandardBindings, o qual realiza a associao de cada porta a cada servio especfico. A Listagem 6 mostra um trecho da declarao do StandardBindings, em que o servio Naming (JNDI) est sendo associado porta 1099 e porta RMI 1098. Com a utilizao do ServiceBindingManager, torna-se mais fcil a utilizao de vrias instncias de JBoss AS no mesmo servidor fsico. Desse modo, a configurao de portas mantida em um nico lugar, o que facilita a manuteno. Injeo de POJOs utilizando o Microcontainer Os arquivos que terminam com jboss-beans.xml so utilizados pelo Microcontainer para realizar a injeo de POJOs. So semelhantes aos -service.xml que eram utilizados nas verses 4.x. A maioria dos servios do AS5 j foi convertida para POJOs. Porm, ainda restam alguns MBeans das verses antigas que utilizam os -service.xml, os quais sero substitudos em verses futuras. Para facilitar o entendimento da injeo de POJOs realizada pelo Microcontainer, criamos a classe PojoServiceExample (Listagem 7). Listagem 7. Classe PojoServiceExample package jm.exemplos.pojo; public class PojoServiceExample { public PojoServiceExample() { System.out.println("Construtor de PojoServiceExample()"); } } uma classe muito simples, com apenas um mtodo construtor que imprime uma mensagem na tela. A Listagem 8 mostra o arquivo jboss-beans.xml, o qual possui a declarao do POJO com o nome 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> Ao realizar o deploy, dever ser exibida a mensagem conforme mostra a Listagem 9. 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() Esse exemplo mostra a forma mais simples de disponibilizar um POJO utilizando o Microcontainer. Basicamente todos os servios, mdulos e suas dependncias so injetados como POJOs e manipulados dessa forma, sem a necessidade de ter de implementar uma interface ou estender uma classe abstrata. Instalao Para a instalao, utilizaremos a verso binria da distribuio do JBoss AS. Para fazer o download do AS5, basta acessar a pgina de download (ver Links) e selecionar o arquivo jboss-5.0.1.GA.zip. O site JBoss.org disponibiliza tambm verses anteriores e um Release Notes de cada uma das verses. Recomendamos a utilizao da verso GA (General Availability), que a verso estvel da distribuio. O nico pr-requisito para execuo do JBoss AS uma mquina virtual Java (JRE) 1.5 ou superior instalada. Na verso 5, no h mais a necessidade de instalao do JDK, pois o AS5 j vem com o ECJ (compilador do Eclipse JDT), necessrio para compilar JSPs. O AS5 pode ser instalado e executado utilizando uma mquina virtual Java 5 ou 6 em qualquer Sistema Operacional. Os binrios compilados com as duas JDKs esto disponveis no site www.jboss.org. Apesar de o nmero de downloads do binrio compilado com Java 6 ser superior e ser considerado uma verso experimental, a verso com Java 5 a chamada verso primria e recomendada para utilizao em produo. Caso queira rodar o AS5 compilado com JDK 5 utilizando JRE 6, quatro bibliotecas devem ser copiadas do diretrio /client para o diretrio /lib/endorsed. So elas: jbossws-native-saaj.jar; jbossws-native-jaxrpc.jar; jbossws-native-jaxws.jar; jbossws-native-jaxws-ext.jar. Porm, utilizando o binrio compilado com JDK 6 em uma JRE 6, nenhuma alterao necessria.O que muda em geral o script de inicializao de cada ambiente. Por exemplo: no Windows utilizamos run.bat, no Unix/Linux, run.sh (para simplificar, omitiremos a extenso a partir deste ponto). O processo de instalao bsica do JBoss AS extremamente simples: basta descompact-lo em algum diretrio de sua escolha. Todo o JBoss AS e sua configurao esto contidos em uma nica estrutura de diretrio. Ento para desinstalar o JBoss AS basta removermos todo o diretrio.

Inicializando o servidor Aps a descompactao do arquivo, iremos iniciar o Application Server. Os scripts de inicializao esto localizados no diretrio /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.

Figura 4: Prompt de inicializao do AS5


Com isso, seu AS5 est pronto para ser utilizado. Os arquivos de inicializao utilizaro por padro o profile default. Veja o quadro Explorando a nova estrutura de diretrios para entender melhor os profiles existentes no AS5. Com o parmetro -c, possvel inicializar diferentes profiles: # ./run -c allP Por questes de segurana, o JBoss AS, quando executado, atende s requisies apenas na interface local (127.0.0.1). Esse comportamento faz com que o servidor no seja acessvel remotamente. Para habilitar o acesso remoto ao servidor de aplicaes, basta utilizarmos a opo -b no script de inicializao do servidor. O comando abaixo far o JBoss AS executar os servios 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 configurao de segurana do servidor conforme a poltica de segurana local.

Explorando a nova estrutura de diretrios A estrutura de diretrios do AS5 muito semelhante dos seus antecessores (Figura 5). Iremos detalhar as principais diferenas entre a estrutura de diretrios de uma verso da srie 4.x para a verso 5. Ao instalar o AS5, percebe-se o novo diretrio common na raiz da instalao. Nas verses anteriores, o diretrio lib de cada profile (configurao) possua 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 so obrigatrias para o funcionamento de todos os profiles foram movidas para o diretrio $JBOSS_HOME/common/lib. Esse diretrio funciona como uma extenso do diretrio $JBOSS_HOME/server/$PROFILE/lib, deixando-o mais limpo e de fcil manuteno, especialmente para gerenciar seus drivers jdbc ou bibliotecas especficas das aplicaes. Os outros diretrios da raiz da instalao permanecem com as mesmas funes: bin - possui todos os scripts e arquivos binrios necessrios para iniciar e parar o AS; client - contm bibliotecas necessrias comunicao de uma aplicao cliente com o JBoss AS. Essas bibliotecas no so carregadas pelo JBoss AS diretamente, mas por aplicaes clientes rodando em JVMs diferentes; docs - diretrio com exemplos de configurao de Datasources, DTDs e XML schemas, licenas de bibliotecas e resultados de testes unitrios. Para documentao completa do JBoss AS, acesse o site da comunidade JBoss www.jboss.org; lib - possui as bibliotecas necessrias para executar o core do AS; server - um dos diretrios mais importantes e contm os profiles e as configuraes para a execuo de aplicaes Java EE. Alm dos profiles clssicos das verses anteriores (minimum, default, all), dois novos profiles foram adicionados ao diretrio server: web e standard. O profile web foi criado com o objetivo de executar apenas aplicaes web, ou Figura 5: Estrutura de diretrios da raiz do AS5 seja, JSPs e Servlets (sem a utilizao de EJBs). Alm disso, tambm esto disponveis JTA, JCA e JPA; porm a maioria dos outros servios no est disponvel, como os servios de e-mail, mensageria, Quartz, gerador de chaves, etc. Esses servios s esto disponveis a partir do profiler default. O profile standard foi criado para a execuo dos testes de compatibilidade com Java EE 5. O profile default um superset do standard e possui algumas poucas configuraes e aplicaes adicionais. Muitos usurios se perguntam qual profile devem utilizar para executar suas aplicaes. A Tabela 2 mostra as principais diferenas entre os cinco profiles.

Tabela 2: Servios disponveis em cada profile.


Os profiles mais utilizados nas verses anteriores eram o default e o all. No AS5, alm destes, o profile web dever ser utilizado em grande escala, substituindo a utilizao do Tomcat e jboss-web stand-alone. Se a aplicao necessita de alta-disponibilidade (HA), utiliza-se o profile all. A maioria dos outros casos ser atendida com o profile default. Cada profile possui um diretrio conf. Assim como nas verses anteriores do JBoss AS, possui as configuraes gerais do servidor de aplicao, como controle transacional, log4j, diretrios de deploy, etc. O diretrio deploy o local utilizado para publicar aplicaes e disponibilizar servios no JBoss AS. No AS5, houve a separao dos servios deployveis com a criao do diretrio deployers (Figura 6).

Figura 6: Servios disponveis em cada profile.


Assim, no ficam mais misturados no diretrio deploy, sendo armazenados no diretrio deployers(a exemplo do jbossweb.deployer). O diretrio lib contm bibliotecas que sero compartilhadas por todos os servios e aplicaes disponveis para o profile. Caso queira compartilhar um driver JDBC entre vrias aplicaes no mesmo profile, adicione a biblioteca do drive no diretrio lib. Para o profile all, foi criado o diretrio cluster, o qual armazena uma total reestruturao dos arquivos de configurao de cluster. O arquivo cluster-service.xml no existe mais, e seu equivalente o $PROFILE/deploy/cluster/jgroups-channelfactory.sar/META-INF/jgroups-channelfactory-stacks.xml.

JBoss AS de cara nova O design do JMX Console e Web Console tambm foi atualizado para facilitar a busca de servios. Agora, h um menu lateral esquerdo com filtro para facilitar a identificao dos servios. Ao clicar no link, apenas os servios relacionados sero exibidos (Figura 7).

Figura 7: Novo design do JMX Console


O Web Console tambm foi modificado, incorporando o design do JMX Console (Figura 8).

Figura 8: Novo design do Web Console

Mitos Acabando com o mito: O JBoss AS no tem um console unificado de administrao, monitorao e controle, tudo tem de ser feito mo. No basta ser um servidor moderno, robusto e performtico se a administrao no for algo simples e intuitivo. Pensando nisso, foi criado o projeto Jopr (Figura 9). O nome Jopr (pronuncia-se jopper) foi escolhido baseado no filme Jogos de Guerra (WarGames), em que havia um super computador chamado WOPR (Whopper) - War Operation Plan Response - o qual era responsvel por responder a todo e qualquer ataque nuclear inimigo.

Figura 9: Jopr
O propsito desse projeto disponibilizar ao administrador uma interface Web integrada e intuitiva para a administrao, monitorao, configurao e controle da Plataforma JBoss. Atravs do Jopr possvel, entre vrias outras coisas: Saber o consumo de CPU, memria, disco e rede do servidor; Saber o consumo de memria da JVM utilizada pelo servidor de aplicaes; Visualizar e monitorar mtricas do servidor de aplicaes e das aplicaes. (Ex: saber quantas sesses esto abertas em uma determinada aplicao); Realizar start/stop/restart do servidor de aplicaes; Monitorar mtricas e criar/deletar/configurar datasources, connection factories, JMS topics; Gerar alertas atravs de e-mail e/ou traps SNMP quando da ocorrncia de uma condio prconfigurada (Ex: utilizao de CPU ultrapassar 80%; memria da JVM ultrapassar 90%).

Alm do Jopr Server - com foco em vrias instncias de JBoss AS, existe tambm uma verso com foco em apenas uma instncia de JBoss AS chamado Embedded Jopr, o qual disponibilizado no prprio servidor. Com o Embedded Jopr (Figura 10), possvel realizar deploys de EARs e WARs, criar novos Datasources, criar novas filas JMS, monitorar o pool de conexes, executar scripts, etc. Tudo isso utilizando uma interface Web intuitiva.

Figura 10: Embedded Jopr.


Para completar seu estudo sobre o JBoss AS 5, veja a Apresentao Mergulhando fundo no JBoss AS 5 e Jopr. Concluso Aps trs anos de pesquisas e desenvolvimento, o JBoss Application Server 5 est pronto para sua grande estria. Com um novo kernel construdo a partir do zero, substitui a utilizao de MBeans por POJOs, utiliza extensamente AOP, unifica a manipulao de metadados, altera o mecanismo de classloading, aspectiza os deployers, tudo isso mantendo a compatibilidade com a maioria dos servios existentes. Essas so algumas das novidades dessa nova verso. O lanamento do AS5 apenas o comeo de uma nova era para os projetos JBoss. A flexibilidade proporcionada pelo Microcontainer permitir Red Hat/JBoss, alm de inovar, estar up-todate com as especificaes do JCP. O objetivo da Red Hat/ JBoss ter o mais inovador, robusto e performtico servidor de aplicaes do mercado. As possibilidades so infinitas e a Red Hat/JBoss precisa da participao da comunidade para ajudar na definio do futuro e no desenvolvimento do JBoss AS e de todos os outros projetos. Essa contribuio essencial para manter os projetos JBoss como os mais populares, queridos e utilizados do planeta. A comunidade o poder do open source. No seja apenas usurio: participe, teste, reclame, sugira, contribua.

Links www.jboss.org Pgina principal da JBoss http://www.jboss.org/community/docs/DOC-9938 Como contribuir com a comunidade JBoss http://java.sun.com/javaee/overview/compatibility.jsp Listagem de Servidores de Aplicao compatveis com Java EE 5.0 http://jcp.org/en/jsr/detail?id=244 Pgina da especificao Java EE 5.0 http://www.jboss.com/products/platforms/application/standards Pgina de padres suportados pelo JBoss AS http://www.jboss.org/jbossas/downloads/ Pgina de download do JBoss AS http://www.jboss.org/jopr/ Pgina principal do Jopr http://felix.apache.org Pgina principal do Apache Felix http://magazine.redhat.com/2008/10/31/interview-chris-morgan-on-jopr/ Entrevista com Chris Morgan sobre Jopr Livros JBoss in Action, Javid Jamae e Peter Johnson, Manning Publications, 2009 Nova verso do livro JBoss in Action a qual foca nas principais configuraes do JBoss Application Server 5 Saiba Mais www.devmedia.com.br/articles/viewcomp.asp?comp=10118 Java Magazine 46 - JBoss: Instalao, Arquitetura , Configurao, Tuning e Administrao www.devmedia.com.br/articles/viewcomp.asp?comp=8453 Java Magazine 51 - Portlets com JBoss Portal www.devmedia.com.br/articles/viewcomp.asp?comp=8495 Java Bagazine 53 - Drools: Regras na Prtica www.devmedia.com.br/articles/viewcomp.asp?comp=9488 Java Magazine 58 - JBoss Seam www.devmedia.com.br/articles/viewcomp.asp?comp=10202 Java Magazine 59 - JBoss ESB

Spring Security

Michel Zanini Formado em Cincias da Computao pela Universidade Federal de Santa Catarina (UFSC) e possui as certificaes SCJP, SCWCD, SCBCD e SCDJWS. De que se trata o artigo: O artigo apresenta o projeto Spring Security como uma alternativa na rea de segurana tradicional especificao Java EE, atravs de um exemplo prtico e realista. Para que serve: Com o Spring Security possvel criar um mecanismo de autenticao e autorizao para sua aplicao web em questo de minutos. O framework foca em facilitar a implementao dos casos de uso mais freqentes, porm oferece valiosos pontos de extenso para requisitos mais complexos. Por fim, disponibiliza suporte a inmeros diferentes tipos de autenticao e integrao com as mais usadas tecnologias na rea de segurana. Em que situao o tema til: Para qualquer aplicao web que necessite restringir seus recursos para diferentes tipos de usurio, bem como assegurar que se autentiquem de forma prtica e segura. Spring Security: O Spring Security surgiu da necessidade de melhorar o suporte segurana oferecido pela especificao Java EE. O framework centraliza a configurao em um nico XML, dispensando configuraes do container e tornando a aplicao web um arquivo WAR auto contido. Para comear 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 configurao). O XML centraliza todas as configuraes de autenticao e autorizao. As tags definem quais roles podem acessar cada grupo de URLs. A tag define a fonte de dados para as informaes de usurios (banco de dados, arquivo de propriedades, LDAP, etc.). Quando necessrio, possvel utilizar os eventos publicados pelo framework a cada sucesso ou falha na autenticao ou autorizao. Ouvir os eventos permite criar complexos casos de gerenciamento de usurios. O Spring Security ainda oferece integraes com a API de Servlets, taglibs para facilitar a codificao de JSPs, suporte HTTPS, segurana em mtodos com uso de anotaes e suporte a autenticao com LDAP ou certificados X509. Segurana um requisito importante presente na grande maioria dos sistemas desenvolvidos. Na plataforma Java EE temos uma soluo oferecida pela especificao que determina como uma aplicao pode definir regras de controle de acesso e autenticao. Entretanto, ainda comum nos depararmos com solues caseiras para cumprir tal requisito. Em parte, tais solues so criadas pela falta de experincia dos desenvolvedores, ou por outro lado, porque a especificao no flexvel o suficiente para comportar os requisitos. Com o objetivo de preencher a lacuna deixada pela especificao, em 2003 surgiu o Acegi Security System for Spring. O Acegi Security conhecido por ser extremamente configurvel e poderoso, porm difcil de utilizar devido enorme quantidade de configurao XML necessria. Em 2007 o projeto Acegi foi incorporado dentro do guarda-chuva de projetos do Spring Framework Portifolio, e ento, renomeado como Spring Security.

Em abril de 2008 a verso 2.0.0 do Spring Security foi lanada tomando como proveito a configurao baseada em namespaces do Spring 2.0. Hoje, o Spring Security extremamente fcil de configurar, sem perder a flexibilidade e o poder do antigo Acegi. O Spring Security depende de alguns JARs do Spring Framework core. Entretanto, no necessrio que sua aplicao seja construda com o modelo de programao do Spring Framework. Ou seja, uma aplicao pr-existente que no usa Spring pode passar a utilizar o Spring Security sem grandes modificaes. Para aprender mais sobre o Spring Framework consulte o artigo de capa da Edio 65. Assim como o Java EE o Spring Security possui uma abordagem declarativa para segurana, baseada em roles (papis). A abordagem declarativa, pois a aplicao no precisa chamar nenhum mtodo para realizar autenticao ou autorizao, tudo feito atravs de configurao XML. Para configurar o Spring Security de forma declarativa, assim como no Java EE, necessrio declarar quais sero os roles envolvidos, quais os recursos que sero protegidos, e quais roles podem acessar cada recurso. Alm disso, declara-se como a autenticao ser feita (basic, digest, form login, LDAP, etc.). Este artigo apresenta as caractersticas do Spring Security, mostrando alguns recursos importantes no presentes na especificao Java EE. Exemplos prticos sero construdos, abordando cenrios frequentes que so requisitos de grande parte das aplicaes web. Os conceitos bsicos sobre segurana no so abordados no artigo. Entretanto, o artigo de capa da Edio 22 descreve tais conceitos e demonstra exemplos prticos utilizando a especificao Java EE. Primeiro exemplo Como primeiro exemplo vamos criar uma aplicao web simples com duas reas de acesso restrito: uma permitida para qualquer usurio autenticado (/usuarios/index.jsp) e outra apenas para usurios administradores (/admin/index.jsp). As pginas restritas apenas exibem uma mensagem e possuem um link de retorno pgina principal. Espera-se que um login seja solicitado ao acessar qualquer uma destas reas. A pgina inicial da aplicao (/index.jsp), ilustrada na Figura 1, tem acesso livre e possui links para as duas reas restritas.

Figura 1: Pgina inicial da aplicao.


O cdigo fonte dos trs JSPs so HTML simples e portanto no sero exibidos nas listagens (esto disponveis para download no site da Java Magazine). 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 permisses de acesso. Por isso, o filtro aplicado com o url-pattern barra asterisco. No Java EE tal filtro no necessrio, pois o controle de acesso realizado pelo prprio container. importante notar que o nome do filtro springSecurityFilterChain e no deve ser alterado, pois o Spring Security j espera que o filtro esteja com este nome, por conveno. No Java EE as configuraes de autenticao e autorizao so feitas no web.xml. No Spring Security so

feitas em um application context padro do Spring Framework. Dessa forma, precisamos do listener ContextLoaderListener declarado no web.xml para carregar o application context na inicializao da aplicao web. O atributo contextConfigLocation do listener indica a localizao do application context, neste caso, na raiz do classpath com o nome spring-security-config.xml. O web.xml da Listagem 1 aplica essas configuraes. Listagem 1. web.xml - Configurao 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> Application context o nome dado aos XMLs de configurao do Spring Framework. Esses arquivos so genricos o suficiente para configurar qualquer tipo de aplicao. Em casos especficos, como do Spring Security, namespaces so utilizados para reduzir a quantidade de XML necessria. Controle de acesso e autenticao no spring-security-config.xml Agora necessrio 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.springframework.org/schema/security) para declarar regras de autenticao e autorizao. Declaramos este namespace como default para o XML (sem prefixo) e o prefixo beans para o namespace normal do Spring Framework. Listagem 2. spring-security-config.xml - Arquivo de configurao 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> Se o leitor utiliza a IDE Eclipse, aconselhamos a instalao do plugin Spring IDE (veja seo de links) para facilidades na edio de application contexts. Outras IDEs como NetBeans e IntelliJ IDEA tambm possuem excelentes plugins de integrao com o Spring, vale pena conferir. O controle de acesso definido pela tag interna tag . No atributo pattern definimos uma expresso que atender as URLs acessadas e no atributo access definimos os roles de usurios que podero acessar as URLs, separados por vrgulas. Definimos que todas as URLs com prefixo /usuarios sero acessadas por usurios normais e administradores e URLs com prefixo /admin apenas por administradores. Por default a sintaxe das expresses utilizadas no atributo pattern a mesma utilizada no Ant. Porm, se desejado, pode-se alter-la para seguir a sintaxe de expresses regulares. Para tal, basta adicionar o atributo path-type="regex" na tag . Dessa forma possvel criar expresses to complexas quanto necessrio para atender s URLs, de acordo com os requisitos do desenvolvedor. As tags sero interpretadas em ordem de definio e a primeira a atender ser usada. Dessa forma, os patterns mais especficos devem vir primeiro. Por exemplo, a expresso /usuarios/vip/** deve ser declarada acima da expresso /usuarios/**, caso contrrio a expresso vip nunca ser avaliada, pois a expresso /usuarios/** tambm atende a URLs do tipo /usuarios/vip/**. O atributo auto-config=true da tag configura automaticamente a aplicao para utilizar login baseado em formulrio. O JSP do formulrio nem mesmo precisa ser codificado, o Spring Security ir ger-lo dinamicamente conforme a Figura 2. Para mais informaes sobre o auto-config=true veja o quadro Entendendo o auto-config.

Figura 2: Login gerado automaticamente pelo Spring Security.

Entendendo o auto-config O atributo auto-config da tag na configurao do Spring Security ativa as opes mais usadas do framework, ajudando a diminuir a quantidade de XML necessrio. 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 autenticao por formulrio e http-basic, bem como tratamento de usurios annimos e previamente autenticados (remember-me). Cada uma das tags possui atributos. Para modific-los necessrio apenas escrever a tag especfica, e o auto-config=true substituir esta parte da configurao. As tags omitidas continuam sendo consideradas. Por exemplo, o cdigo abaixo muda o JSP do formulrio de login e o restante das configuraes automticas continuam aplicadas. Isso configura o framework para utilizar autenticao por formulrio e http-basic, bem como tratamento de usurios annimos e previamente autenticados (remember-me). Cada uma das tags possui atributos. Para modific-los necessrio apenas escrever a tag especfica, e o auto-config=true substituir esta parte da configurao. As tags omitidas continuam sendo consideradas. Por exemplo, o cdigo abaixo muda o JSP do formulrio de login e o restante das configuraes automticas continuam aplicadas. <http auto-config=true> <form-login login-page=/login.jsp/> </http> Desta forma, a ltima coisa que nos resta definir os usurios possveis e seus papis. No primeiro exemplo, para facilitar, iremos utilizar a tag que permite definir usurios, senhas e roles no prprio arquivo XML (tambm possvel referenciar um arquivo de propriedades). Normalmente, em uma aplicao real, no vivel definir os usurios em arquivo. Nos prximos exemplos iremos apresentar alternativas. ltimos passos O esqueleto do projeto, juntamente com os JARs necessrios para rodar os exemplos, podem ser vistos da Figura 3. Para ajudar na depurao da aplicao, atravs 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 utilizado em breve, nos prximos exemplos. O resto das bibliotecas so dependncias do Spring Security. Os JARs esto disponveis no download dessa edio no site da Java Magazine.

Com os trs JSPs, o web.xml, o spring-security-config.xml e os JARs necessrios, podemos executar a aplicao. O deploy pode ser realizado em qualquer servidor da preferncia do leitor, pois o Spring Security no requer configuraes adicionais dependentes de container. Executando o exemplo Ao acessar o index da aplicao (Figura 1) dois links sero apresentados. Ao clicar em algum deles, por exemplo /usuarios/index.jsp, o filtro do Spring Security ir detectar como uma pgina protegida e ir gerar automaticamente o HTML para o login (Figura 2). Um usurio normal, ao logar-se, ter acesso pgina de usurios, mas no de administradores. J o administrador tem acesso a ambas as pginas. Note que o servio de remeber-me para o login j est funcionando. O exemplo bastante simples, mas j cobre alguns dos principais conceitos e casos de uso. Utilizando algoritmos de hash para senhas

Figura 3: Arquivos do primeiro exemplo.

No primeiro exemplo as senhas dos usurios esto visveis aos administradores da aplicao. Isto apresenta um risco de segurana. Um algoritmo de hash normalmente usado em uma aplicao real, impossibilitando o acesso senha original. Para tal, o Spring Security oferece a tag . So oferecidos os principais algoritmos de hash e tambm possvel criar uma implementao customizada. A Listagem 3 aplica o algoritmo md5 como password-encoder. 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> <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> 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). Formulrio personalizado A gerao automtica de formulrio til apenas para testes. Uma aplicao real necessita de uma pgina de formulrio customizada. Iremos criar um JSP (/login.jsp) com um formulrio para o nosso exemplo. Para isso acrescentamos este trecho dentro da tag no spring-security-config.xml: <form-login login-page="/login.jsp" authentication-failure-url= "/login.jsp?login_error=true" /> O atributo authentication-failure-url configura o JSP que ser apresentado caso o login falhe. Neste caso configuramos o mesmo JSP do formulrio de login com um parmetro login_error=true. Esse parmetro utilizado pelo JSP de login da Listagem 4. Listagem 4. login.jsp - Pgina 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">

No foi possvel 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 informaes 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> Os exemplos demonstrados utilizam Scriplets (cdigo Java no JSP) apenas por questes didticas. Uma aplicao real estaria utilizando a taglib JSTL. No topo do JSP, abaixo do ttulo, testamos se o parmetro login_error igual a true. Caso verdade (o login falhou) ento mostramos uma mensagem de erro. A expresso $ {SPRING_SECURITY_LAST_EXCEPTION.message} recupera a ltima mensagem de erro gerada pelo framework. Essa mensagem por default est em ingls, mas pode ser internacionalizada. Em seguida codificamos o formulrio. Por default a action do formulrio de login deve ser j_spring_security_check e o name dos inputs de usurio e senha j_username e j_password, respectivamente. 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.

Figura 4: Pgina de login customizada


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 necessrio, possvel modificar a URL acrescentado a tag <logout> dentro da tag <http>: Quando um usurio normal acessa a pgina protegida dos administradores o container apresenta uma

mensagem padro para o erro 403 (access denied). Essa pgina pode ser personalizada pelo Spring Security acrescentando o atributo access-denied-page tag : <http access-denied-page="/accessDenied.jsp" (...) > E ento, criamos o accessDenied.jsp conforme a Listagem 5. Listagem 5. accessDenied.jsp - Pgina de erro <html> <body> <h1>Spring Security</h1><hr/> <p><font color="red">Acesso negado. O usurio no tem permisso para acessar essa pgina.</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> Formulrio de login embutido em outras pginas Quem tem experincia com a segurana tradicional Java EE sabe que no possvel acessar o JSP de login diretamente pela aplicao. O container deve apresentar este JSP quando uma pgina protegida acessada. Essa limitao cria outros problemas, por exemplo, quando um portal deseja que o formulrio de login esteja contido em todas as reas do site. Nesse caso, os desenvolvedores se obrigam a criar algum mecanismo utilizando JavaScript para contornar a situao. No Spring Security tais limitaes simplesmente no existem. Quando o usurio acessa diretamente o JSP de login, ou quando um formulrio de login embutido utilizado, o Spring Security utiliza uma URL default para redirecionar o usurio. A tag <form-login> possui um atributo default-target-url que indica esta URL (se no informada o default a raiz da aplicao). Por exemplo, se o formulrio for configurado desta forma: <form-login default-target-url="/index.jsp" (...) /> Sempre que o formulrio de login for acessado diretamente, aps logar-se, o /index.jsp ser carregado. Caso o usurio acessar uma pgina protegida, aps logar-se, esta ser a pgina exibida e no o /index.jsp. Se o atributo always-use-default-target for true o usurio sempre ser redirecionado para o /index.jsp. Autenticao utilizando banco de dados A ltima modificao necessria para tornar o exemplo realstico adicionar um banco de dados, substituindo a configurao dos usurios e roles do XML. Um modelo de dados tpico para uma aplicao web, de maneira simplificada, algo parecido com as tabelas da Figura 5.

Figura 5: Modelo de dados para armazenar os usurios, senhas e perfis.

Apesar de no ser necessrio no nosso exemplo, criamos uma tabela de juno entre as tabelas de usurio e perfil para termos uma relao NxN. Este cenrio muito comum em aplicaes enterprise. O campo chamado ativo na tabela de usurios serve para impedir que usurios bloqueados autentiquemse. Caso este campo for false o usurio est com o acesso bloqueado. O campo tentativas_login armazena o nmero de vezes que o usurio errou a senha consecutivamente. Esse campo ser utilizado apenas em exemplos posteriores. O download do artigo traz dois scripts para serem executados no banco de dados HSQL. Um script cria as tabelas e outro cria alguns usurios para teste. Para rodar o HSQL basta executar este comando no prompt do sistema operacional (considerando que o jar do HSQL est no diretrio corrente): java -cp hsqldb-1.8.0.7.jar org.hsqldb.Server Logo aps, abra outro prompt e execute o comando para abrir o console SQL com interface grfica: java -cp hsqldb-1.8.0.7.jar org.hsqldb.util.DatabaseManagerSwing Selecione a opo HSQL Database Engine 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 configurao do Spring Security para considerar as tabelas algo muito simples, pressupondo que o banco de dados est corretamente configurado. Duas modificaes so necessrias: substituir a tag por uma tag e acrescentar um spring bean para a configurao do banco de dados (data-source). A Listagem 6 demonstra o novo spring-security-config.xml. Listagem 6. spring-security-config.xml - Adicionando autenticao 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>

Precisamos de trs atributos para configurar a tag . O primeiro atributo uma referncia para a configurao do banco de dados que ser utilizado (data-source-ref). O segundo a query que ser utilizada para buscar os usurios dado um username (users-by-username-query). Essa query necessita retornar trs 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 usurio, dado um username (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 informaes retornadas para autenticao. No final do arquivo de configurao adicionamos um bean dataSource e o configuramos para acesso ao banco de dados HSQL. Repare que utilizamos a classe DriverManagerDataSource que serve apenas para propsitos de teste. Em uma aplicao real configuraramos um pool de conexes como data-source, normalmente oferecido pelo container atravs de um nome JNDI. Eventos de autenticao e autorizao O Spring Security utiliza a infra-estrutura do application context do Spring para publicar eventos referentes a momentos importantes em seu fluxo de execuo. Existem duas categorias de eventos: eventos de autenticao e eventos de autorizao. Para cada situao existe um evento correspondente. Por exemplo, quando uma autenticao ocorre com sucesso, um evento AuthenticationSuccessEvent publicado; quando a autenticao falha porque a senha est errada, um evento AuthenticationFailureBadCredentialsEvent publicado; se a autenticao falha porque o usurio est inativo, um evento AuthenticationFailureDisabledEvent ocorre; e assim por diante. O Spring Security utiliza a infra-estrutura do application context do Spring para publicar eventos referentes a momentos importantes em seu fluxo de execuo. Existem duas categorias de eventos: eventos de autenticao e eventos de autorizao. Para cada situao existe um evento correspondente. Por exemplo, quando uma autenticao ocorre com sucesso, um evento AuthenticationSuccessEvent publicado; quando a autenticao falha porque a senha est errada, um evento AuthenticationFailureBadCredentialsEvent publicado; se a autenticao falha porque o usurio est inativo, um evento AuthenticationFailureDisabledEvent ocorre; e assim por diante. Quando uma URL acessada e o filtro do Spring Security verifica se o usurio tem autorizao para acessar a URL, eventos de sucesso ou falha tambm so publicados. Veja na Figura 6 uma hierarquia de eventos de autenticao e autorizao. Consulte o Javadoc de cada classe para entender o momento em que cada evento publicado.

Figura 6: Eventos de autenticao e autorizao publicados pelo Spring Security.


Para ouvirmos aos eventos acima necessrio implementar a interface ApplicationListener e registrar a classe no application context. A Listagem 7 demonstra um exemplo simples de como ouvir a eventos de sucesso ou falha na autenticao. Listagem 7. TestEventListener.java - Ouve eventos de autenticao publicados pelo Spring Security public class TestEventListener implements

ApplicationListener { public void onApplicationEvent (ApplicationEvent event) { if (event instanceof AuthenticationSuccessEvent) { System.out.println ("Usurio autenticado com sucesso"); } if (event instanceof AbstractAuthenticationFailureEvent) { System.out.println ("Usurio no autenticado"); } } Lembre-se de adicionar o novo bean no application context: <beans:bean class="br.com.jm.security. TestEventListener" /> Essa funcionalidade permite implementar complexos casos de uso, com baixo acoplamento entre a aplicao e o Spring Security, como veremos em um exemplo adiante. Para facilitar o aprendizado de quando os eventos ocorrem, registre dois listeners que vm juntos com a distribuio 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 autenticao e autorizao. Uma tima forma de aprender o funcionamento do framework a anlise do log gerado por estes listeners. Explorando os pontos de extenso Escolhemos um caso de uso para demonstrar como os eventos de autenticao so teis e como fcil customizar o framework. Cada vez que um usurio errar a senha por trs vezes consecutivas, a sua conta ser bloqueada. Essa funcionalidade muito comum em sites que exigem altos padres de segurana, como bancos por exemplo. A cada erro de autenticao por informar a senha incorreta (evento AuthenticationFailureBadCredentialsEvent) a coluna tentativas_login ser incrementada. A cada autenticao com sucesso (evento AuthenticationSuccessEvent) a coluna tentativas_login ser zerada. A cada tentativa de login, caso a coluna tentativas_login for igual ou maior que trs, a autenticao ser bloqueada. Veja na Listagem 8 o listener que atualiza a coluna tentativas_login. Escolhemos um caso de uso para demonstrar como os eventos de autenticao so teis e como fcil customizar o framework. Cada vez que um usurio errar a senha por trs vezes consecutivas, a sua conta ser bloqueada. Essa funcionalidade muito comum em sites que exigem altos padres de segurana, como bancos por exemplo. A cada erro de autenticao por informar a senha incorreta (evento AuthenticationFailureBadCredentialsEvent) a coluna tentativas_login ser incrementada. A cada autenticao com sucesso (evento AuthenticationSuccessEvent) a coluna tentativas_login ser zerada. A cada tentativa de login, caso a coluna tentativas_login for igual ou maior que trs, a autenticao ser bloqueada. Veja na Listagem 8 o listener que atualiza a coluna tentativas_login. Listagem 8. IncorrectPasswordEventListener.java - Listener tentativas_login de acordo com o resultado da autenticao public class IncorrectPasswordEventListener extends JdbcDaoSupport implements ApplicationListener { public void onApplicationEvent (ApplicationEvent event) { if (event instanceof AuthenticationFailureBadCredentialsEvent) { AuthenticationFailureBadCredentialsEvent badCredentialsEvent = (AuthenticationFailureBadCredentialsEvent) event; que atualiza a coluna

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

} 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().getName()}); } } Para completar o exemplo ainda necessrio bloquear o login caso a coluna seja maior ou igual a trs. Para isso iremos explorar um ponto de extenso comumente utilizado no Spring Security, a interface UserDetailsService. Essa interface possui o mtodo loadUserByUsername() que recupera os dados de um usurio dado seu username. Veja a Listagem 9. Listagem 9. Interface implementado UserDetailsService e o mtodo loadUserByUsername() a ser

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

public class CustomUserDetailsService implements UserDetailsService { public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { //retorna um objeto representado o usurio a ser autenticado

return null; } } Uma implementao dessa interface substitui as tags (usurios em XML ou arquivo de propriedades) ou (usurios em banco de dados) que vimos at agora. Sendo assim, atravs dessa implementao, o usurio do framework tem liberdade para buscar as informaes de onde necessitar e da forma que quiser. Entretanto, o motivo mais comum para implementar a interface no a escolha de uma nova fonte de dados e sim, a personalizao do objeto UserDetails de retorno. A interface UserDetails implementada por objetos que representam o usurio no seu modelo de domnio. Ela possui mtodos para retornar o username, o password, as authorities e quatro booleans representando diferentes motivos para bloqueio do login: enabled, accountNonLocked, accountNonExpired e credentialsNonExpired. Sendo assim, criamos uma classe Usuario para implementar a interface, veja a Listagem 10. Listagem 10. Usuario.java - Objeto do modelo de domnio 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 --} Caso qualquer um dos mtodos que retornam boolean retornar false o login ser bloqueado e uma mensagem adequada ser apresentada. Nesse caso no iremos utilizar as propriedades de conta ou senha expirada, ento retornarmos sempre true nos mtodos isAccountNonExpired() e isCredentialsNonExpired(). Para o mtodo isEnable() utilizamos o valor da coluna ativo no banco de dados e para o mtodo isAccountNonLocked() utilizamos nossa regra de negcios: bloquear o login caso trs ou mais tentativas de login tenham sido feitas com a senha incorreta. Para conectar as implementaes precisamos de uma classe que implemente a interface UserDetailsService. Entretanto, queremos continuar utilizando um banco de dados para armazenar os usurios e apenas retornar um objeto Usuario com informaes adicionais, as colunas email e tentativas_login. Para no duplicarmos cdigo sem necessidade, iremos estender uma classe do Spring Security que j nos oferece um ponto de extenso justamente para estes casos. A classe JdbcDaoImpl a classe por trs da tag . Essa classe j implementa o mtodo loadUserByUsername() e nos deixa uma extenso valiosa, o mtodo createUserDetails(). Esse mtodo um gancho para retornar um UserDetails customizado. Veja a Listagem 11. 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 RowMapper() { public Object mapRow(ResultSet rs, int rowNum)

} }

throws SQLException { usuario.setEmail(rs.getString("email")); usuario.setTentativasLogin(rs.getInt ("tentativas_login")); return null; } });

O mtodo createUserDetails() apenas copia propriedades que j esto disponveis e chama o mtodo carregarInformacoesAdicionais() que faz uma query para preencher as propriedades restantes: email e tentativas_login. A implementao do caso de uso est completa. A classe CustomUserDetailsService utilizada para buscar as informaes de um usurio e retornar um UserDetails do nosso domnio. Aps a execuo do mtodo loadUserByUsername() as propriedades booleanas do Usuario so testadas. Nesse caso, o getter da propriedade accountNonLocked testa se a coluna tentativas_login igual ou maior que trs. Por fim, para controlar o incremento da coluna, os eventos de sucesso e falha na autenticao so tratados pela classe IncorrectPasswordEventListener. O novo spring-security-config.xml demonstrado na Listagem 12. Listagem 12. spring-security-config.xml - Verso final do XML de configurao 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.LoggerListener" /> <beans:bean class= "org.springframework.security. event.authentication.LoggerListener" /> </beans:beans> A principal diferena do novo XML a tag . Retiramos o e fizemos uma referncia para o bean customUserService. Como a classe CustomUserServiceDetails estende JdbcDaoImpl as propriedades das queries continuam existindo. Sendo assim, copiamos as propriedades da antiga para o novo bean. Outra diferena importante a adio do IncorrectPasswordEventListener no final do arquivo. Integrao com a API de servlets O filtro do Spring Security substitui a implementao original da interface ServletRequest por um wrapper (extenso da classe ServletRequestWrapper). Este wrapper implementa os mtodos relacionados a segurana na interface ServletRequest: getRemoteUser(), isUserInRole() e getUserPrincipal(). Dessa forma, possvel utilizar os mtodos tradicionais do Java EE como de costume, sem diferenas. Por exemplo, veja o trecho de cdigo a seguir: String role = request.getRemoteUser(); System.out.println("Role: " + role); System.out.println (request.isUserInRole ("ROLE_USUARIO")); System.out.println (request.isUserInRole ("ROLE_ADMIN")); Este cdigo funciona perfeitamente com o Spring Security. Se o usurio admin (com perfil de administrador) estiver logado, ento a seqncia a ser impressa no console ser: Role: admin false true O mtodo getUserPrincipal() retorna um objeto que implementa a interface org.springframework. security.Authentication. Atravs desse objeto possvel retornar o usurio 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 usurio logado, porm sem necessitar do HttpServletRequest, atravs da classe SecurityContextHolder. Essa classe mantm o objeto Authentication em uma varivel thread-local. O mtodo a seguir pode ser implementado em uma classe de utilidade e pode ser chamado em qualquer ponto da aplicao: public static Usuario getUsuarioLogado() { Authentication authentication = (Authentication) SecurityContextHolder.getContext().getAuthentication();

if (authentication instanceof Usuario) { return (Usuario) authentication.getPrincipal(); } return null; } Utilizando as taglibs O Spring Security fornece duas tags teis para codificao de JSPs: e . Ambas podem ser importadas com a declarao a seguir: <%@ taglib prefix="sec" uri="http://www.spring framework.org/security/tags" %> A tag <authorize> utilizada para mostrar/esconder informaes de acordo com as permisses (roles) do usurio. Veja o cdigo a seguir: <sec:authorize ifAllGranted="ROLE_ADMIN"> <p>Voc um administrador href="../admin/index.jsp">pgina</a>.<p> </sec:authorize> e tambm pode acessar esta <a

A tag possui trs atributos exclusivos: ifAllGranted, ifAnyGranted e ifNotGranted. Todos os atributos suportam um ou mais roles separados por vrgula. O atributo ifAllGranted informa que o usurio tem que <Authentication>permite acessar as propriedades do objeto Authentication do usurio logado no JSP. Por exemplo, o trecho de cdigo a seguir, codificado no index.jsp, ir exibir as informaes do usurio utilizando a tag <Authentication>: <sec:authorize ifAnyGranted="ROLE_ADMIN,ROLE_USUARIO"> <b>Informaes do usurio 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> O vdeo Spring Security apresenta como realizar o controle de sesses, trabalhar com HTTPS e autenticao atravs de certificados digitais. Concluses Com os exemplos demonstrados podemos ver alguns dos principais casos de uso de segurana em uma aplicao web. O Spring Security centraliza as configuraes em apenas um arquivo que ser empacotado juntamente com o war da aplicao, dispensando configuraes externas do container. A aplicao no fica apenas mais enxuta, como tambm mais extensvel, como vimos atravs da interface UserDetailsService e dos eventos de autenticao e autorizao. Dessa forma possvel implementar casos complexos de gerenciamento de usurios, de forma desacoplada do domnio de negcios da aplicao. Alguns assuntos no foram abordados no artigo por motivo de espao, porm o leitor pode consultar a documentao no site do framework. Algumas funcionalidades oferecidas pelo Spring Security e no apresentadas so: segurana a nvel de mtodos (utilizando anotaes e AOP), suporte a HTTPS, controle de sesses concorrentes e diferentes formas de autenticao, como certificados X509, LDAP, etc. Para mais informaes sobre single sign on consulte o quadro Single sign on com CAS e OpenID. Single sign on com CAS e OpenID Autenticao single sign on significa logar-se em uma aplicao e permanecer logado ao acessar outra aplicao do mesmo grupo. Essa funcionalidade comumente oferecida por containers para as aplicaes as quais ele gerencia. O Spring Security oferece suporte a single sign on para aplicaes intranet atravs do Central Authentication Service (CAS) e aplicaes internet atravs do OpenID. O CAS uma aplicao web (arquivo WAR) que responsvel por apresentar as telas de login das aplicaes do mesmo grupo. Basicamente, todas as aplicaes do grupo iro redirecionar o browser para a aplicao central na hora da autenticao, e aps o login, o CAS ir retornar a URL para a aplicao que

solicitou o login. Dessa forma, as configuraes de autenticao ficam no WAR do CAS e nos demais WARs o Spring Security usado para realizar a integrao. Uma vantagem do CAS o fato de existirem clientes para diversas linguagens como Java, .Net, PHP, Perl, etc. permitindo integrao entre aplicaes heterogneas. O OpenID, por sua vez, elimina a necessidade de ter vrios logins em diferentes sites na internet. Ao criar um login em um dos providers de OpenID (veja Links) possvel utilizar o username e senha para acessar todos os sites que o suportam, sem necessitar logar-se mltiplas vezes. Grandes empresas j suportam o padro como Sun, Google, IBM, Microsoft, etc. O Spring Security facilita o processo de habilitar sua aplicao para suportar logins provenientes de providers OpenID. Nota Devman - Wrapper Um objeto wrapper uma implementao do padro de projeto Decorator. O objetivo deste desing pattern adicionar ou substituir o comportamento de classes existentes de forma dinmica. Isto feito criando uma classe base, normalmente com o sufixo Wrapper ou Decorator, que implementa a interface a ser decorada e tambm recebe como parmetro no construtor um objeto da mesma interface. Em seguida, todos os mtodos da classe so 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 mtodos desejados. Links 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 Saiba Mais www.devmedia.com.br/cursos/listcurso.asp?curso=46 Curso Online - Trabalhando com Struts 2 em conjunto com Sitemesh, Spring e JPA www.devmedia.com.br/cursos/listcurso.asp?curso=113 Curso Online - Java Web: Saiba como Desenvolver Aplicaes utilizando Spring, Hibernate e JSF na Prtica www.devmedia.com.br/articles/viewcomp.asp?comp=10225 Java Magazine 40 - Comeando com Spring www.devmedia.com.br/articles/viewcomp.asp?comp=8573 Java Magazine 45 - Indo alm com Spring www.devmedia.com.br/articles/viewcomp.asp?comp=10170 Java Magazine 46 - Integrando Spring com JSF e JDBC www.devmedia.com.br/articles/viewcomp.asp?comp=8369 Java Magazine 50 - Spring com Struts e JPA www.devmedia.com.br/articles/viewcomp.asp?comp=8647 Java Magazine 53 - Spring Remoting

www.devmedia.com.br/articles/viewcomp.asp?comp=10210 Java Magazine 60 - Enviando e-mails com Spring 2.5 www.devmedia.com.br/articles/viewcomp.asp?comp=11678 Java Magazine 65 - Spring e Java EE 6 esto na mesma direo? www.devmedia.com.br/articles/viewcomp.asp?comp=11677 Java Magazine 65 - Criando uma aplicao web com Spring Framework

JavaFX Script

Osvaldo Pinali Doederlein Mestre em Engenharia de Software Orientado a Objetos e Arquiteto de Tecnologia da Visionnaire Informtica, trabalhando em projetos de software e prospeco tecnolgica. De que se trata o artigo: Apresentamos uma referncia da linguagem JavaFX Script, que faz parte da plataforma JavaFX. Para que serve: JavaFX a nova plataforma RIA da Sun, compatvel com Java SE e Java ME, j apresentadas em artigos anteriores desta srie. Alguns leitores podem encarar a exigncia de aprender uma nova linguagem de programao como um obstculo, mas este aprendizado facilitado pela semelhana entre JavaFX Script e Java - tiramos proveito desta semelhana para explicar a nova linguagem de forma concisa. Mesmo para quem j aprendeu JavaFX Script, o artigo serve como uma referncia bem organizada e pragmtica (ao contrrio da referncia oficial, que tem uma estrutura mais formal, certamente mais detalhada, mas no adequada facilidade de consulta e sem pretenses didticas). Em que situao o tema til: A linguagem JavaFX Script um pr-requisito para desenvolver para a plataforma JavaFX, a qual promete grande produtividade, mas (com qualquer plataforma) somente aps vencer uma curva inicial de aprendizado. Mesmo para quem no tiver grande interesse na JavaFX, o artigo apresenta muitas inovaes da JavaFX Script que so um aprendizado valioso para qualquer interessado em linguagens de programao. Na Edio 67 apresentamos a plataforma JavaFX, introduzindo-a de forma conceitual e dando alguns aperitivos das suas funcionalidades e programao. Na Edio anterior (68), seguimos com um primeiro tutorial de programao JavaFX, ensinando o bsico da linguagem e framework de uma forma prtica, mas bastante informal. Agora, encerrando esta cobertura inicial da JavaFX, vamos nos focar apenas na linguagem JavaFX Script, cobrindo-a de uma forma mais formal e abrangente. (Para o leitor ainda pouco motivado a aprender JavaFX Script, seria boa idia comear pelo quadro Por que uma nova linguagem?.) No meu objetivo repetir o documento de Referncia da Linguagem de Programao JavaFX Script que est disponvel em openjfx.dev.java.net/langref. Ao invs disso, a idia explicar a linguagem de uma forma concisa e pragmtica, tendo como alvo no algum 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 ento ter uma referncia de fcil consulta. Ainda mais especificamente, escrevo pensando no programador que j conhece bem a linguagem Java, o que permitir resumir ou omitir explicaes dos pontos onde ambas as linguagens forem iguais ou muito parecidas (e so muitos pontos). Assim, podemos concentrar nosso tempo e neurnios nas partes que so diferentes. O artigo organizado como uma referncia da linguagem, agrupando suas funcionalidades em sees como Valores, Operadores, Classes etc., de forma similar a uma referncia formal. No entanto, fiz este agrupamento de uma forma relaxada segundo critrios conceituais e no de gramtica formal. Por exemplo, a seo de Operadores no possui todos os operadores, pois alguns deles so cobertos em outras sees (ex.: os diversos operadores especficos para sequences so mostrados na seo

Sequences). Tambm no me preocupei em documentar minimamente alguns aspectos mais elementares da linguagem que so exatamente idnticos a Java, por exemplo a sintaxe para nmeros literais. A inteno ter um texto o mais compacto e didtico possvel, mas ainda assim, suficientemente organizado e formal para servir como referncia da linguagem. No decorrer do artigo, uso o termo JavaFX no lugar de JavaFX Script, por simplicidade. Tipos e Valores O sistema de tipos da JavaFX inspirado no Java, mas com melhorias importantes. Na Tabela 1, classifiquei os tipos da JavaFX em cinco categorias e comparei-os aos tipos equivalentes em Java. Vamos comentar apenas as novidades desta tabela.

Tabela 1: Classificaes de tipos da JavaFX, comparativamente com Java.


Valores A maior novidade que o typesystem de JavaFX OO-puro: no existem tipos primitivos. Por outro lado, existem tipos de valor, que so aqueles cuja igualdade de referncia equivalente igualdade de valor (em outras palavras: x == y se e somente se x.equals(y)). Os tipos primitivos do Java, como int, so tipos de valor, por isso no h dois valores 17 distintos, por exemplo. O mesmo vale para o Integer da JavaFX. Alm disso, os valores so imutveis, e no admitem null. A diferena entre esses tipos da JavaFX e os tipos primitivos do Java que os tipos de valor so objetos. Em JavaFX, todos os tipos, sem exceo, so derivados de Object. Em termos de implementao, os valores de JavaFX so equivalentes aos primitivos de Java, evitando o custo de desempenho de usar objetos. Por exemplo, se voc olhar o arquivo .class gerado pelo javafxc para uma funo que recebe um parmetro Integer, ver que o bytecode compilado ir conter um mtodo que recebe um int primitivo. Somente quando um valor utilizado em alguma operao que

exige sua faceta OO, a JavaFX faz uma converso automtica para um objeto. Voc pode considerar isso uma verso melhorada do autoboxing de Java 5. As melhorias incluem a simplificao (no h tipos paralelos como int/Integer) e desempenho (o compilador, runtime e frameworks usam vrias tcnicas para representar valores na forma primitiva, e reduzir ao mnimo as converses de/para a forma OO). Strings Meno honrosa vai para o tipo String da JavaFX Script, que ao contrrio de Java, definido como um value type. Alm disso, carrega um lote de funcionalidades extra: O valor default de uma String no inicializada "" (string vazia). impossvel ter uma string null; se voc fizer esta atribuio, fica com "". Nunca acontecer uma NullPointerException envolvendo strings (ou qualquer value type); O operador == equivale a equals(), no h distino entre igualdade e identidade (novamente, como todos value types); Pode-se mesclar strings com expresses, por exemplo: "Al, {nome}!" ser expandido conforme o valor dinmico da varivel nome. Ou ento, "Temperatura: {%2.2f temp}", a varivel 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; Internacionalizao simples: def msg = ##"ERRO" ir atribuir a msg o valor da string associada chave ERRO no resource bundle da aplicao; se no existir este resource, o valor da string ser "ERRO" mesmo. Para separar a chave do valor default, use ##[ERRO]"Deu zebra!"; o nico tipo de JavaFX Script para manipular caracteres. No existe um tipo especfico para um caractere nico, como o char do Java. Converses automticas so 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 no passa de um acar sinttico para um long contendo o tempo normalizado para milissegundos, mas ao usar o framework de animao 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 seo Controle. Referncia Os reference types da JavaFX tambm so familiares. Ver sees sobre funes e sequences. Funes JavaFX Script possui funes de primeira ordem. Exemplo: var validador: function (o:Object): Boolean O tipo da varivel validador uma funo que possui um parmetro do tipo Object e retorna um Boolean. Portanto, funes podem ser atribudas a variveis, passadas como parmetro, etc. como quaisquer outros tipos. A linguagem Java possui uma aproximao desta facilidade, combinando interfaces com inner classes - mas o resultado uma sintaxe confusa. Com a verso muito melhorada de JavaFX, podemos escrever por exemplo um tratador de eventos assim: Stage { onClose: function() { FX.exit() } } Funes suportam os seguintes modificadores (antes do function): Visibilidade (public, protected, package, e por default script-private); abstract, igual a Java; override, igual ao @Override do Java 5 (mas mandatrio); bound, que examinaremos em Binding;

No h nada equivalente ao final dos mtodos Java.

Sequences As sequences da JavaFX Script possuem sintaxe similar, mas significado e capacidades diferentes dos arrays do Java. Em comum com os arrays, as sequences so colees de objetos de um tipo homogneo e com tamanho fixo, indexadas a partir da base 0. As diferenas comeam com algumas sintaxes facilitadas (syntax sugar), mas vo alm. A Tabela 2 exemplifica todas as capacidades e sintaxes especficas para sequences. Algumas coisas so 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 sequence sero manipulados (como em delete dias[1 .. 2]), quanto para criar uma sequence contendo todos os nmeros inteiros do range (como em [1 .. 100]).

Tabela 2: Sintaxes de uso de sequences.


Uma caracterstica importante das sequences que elas no 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"] ] no [ "Dom", "Seg", "Ter", ["Qua, "Qui"] ], e sim [ "Dom", "Seg", "Ter", "Qua, "Qui" ]. Esta transformao conhecida como flattening (achatamento), e embora possa parecer uma limitao, uma caracterstica importante do estilo de programao da linguagem. Este estilo incentiva o uso de expresses fluentes - onde o output de cada expresso usado como input da seguinte, algo similar ao uso de pipes em shell scripts. Para isso funcionar, preciso que todas as operaes utilizem uma estrutura 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 famlia LISP,

sabe que tais linguagens permitem o uso de estruturas aninhadas. Mas JavaFX Script no pretende ser uma linguagem de programao funcional sofisticada, para quem curte tcnicas do tipo map/reduce; ao invs disso, foi feita a opo por sequences com flattening automtico, o que simplifica os cenrios de uso mais importantes para JavaFX, por exemplo a inicializao de estruturas complexas como o Scene Graph. Observe a tentativa da JavaFX Script de usar uma sintaxe SQL-like para a manipulao de dados: sintaxes como insert..into, delete..from, o in e o where do for. Num detalhe importante, o leitor pode estar confuso com minha afirmao que as sequences so imutveis, seguida por uma tabela que indica vrias sintaxes para sua alterao. 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, aps a atribuio diasUteis = dias, ambas variveis apontam para a mesma sequence. Mas em seguida, o delete cria uma nova sequence e a atribui varivel diasUteis; a sequence original continua existindo pois ainda referenciada por dias. Este truque sinttico - operadores como delete e insert, que executam uma atribuio escondida - mantm a sintaxe familiar para quem no est acostumado ao estilo funcional (no qual nunca, ou raramente, se altera o valor de variveis preexistentes). Para mais detalhes, veja o quadro Imperativo ou Funcional?. Declaraes Nesta seo veremos como JavaFX Script permite declarar variveis e funes. Na Tabela 3, podemos ver que as variveis de JavaFX podem ser declaradas com var ou def. A diferena que o def usado para constantes (similar s variveis final do Java), enquanto var indica variveis propriamente ditas (i.e., cujo valor pode variar).

Tabela 3: Declaraes de variveis e funes.


As declaraes estticas de tipo so opcionais, mas isso no significa que JavaFX Script seja uma linguagem dinamicamente tipada. Ao contrrio, JavaFX to estaticamente tipada quanto Java; a diferena que contamos com inferncia 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 5 com o qual a varivel inicializada. No caso especfico das declaraes def, como o valor inicial mandatrio, a declarao de tipo jamais necessria. Tambm salta aos olhos que JavaFX Script utiliza o estilo Pascal de declaraes de tipos, ou seja nome :

Tipo ao invs de Tipo nome como em Java. Apesar de parecer uma diferena gratuita e desagradvel de Java, voc se acostumar e ver que existem bons motivos para isso (o mesmo vale para Scala, que no coincidentemente - tambm usa inferncia de tipos). A mesma sintaxe de declaraes pode ser utilizada em trs escopos distintos: var x = 5; function x1 () { return x; } // Retorna 5 class 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 variveis e funes locais, de instncia, e globais. Esta ltima opo parece ser uma novidade, mas de fato no , pois ocupa o lugar dos static do Java. Se num arquivo Y.fx voc tiver um elemento global x, este ser acessvel externamente com a sintaxe Y.x, ou seja, igual s statics. Em termos de compilao e desempenho, a equivalncia tambm permanece: variveis e funes globais so transformadas pelo javafxc em variveis e mtodos static. A inferncia de tipos tambm funciona para funes, especialmente o tipo de retorno: raramente preciso especific-lo explicitamente, pois ao encontrar por exemplo uma operao return a + b no corpo da funo, o javafxc determina que o tipo desta expresso o tipo esttico de retorno a funo. Mas alguns programadores podem preferir especificar o tipo de retorno, para ter certeza que este ser um tipo especfico (neste caso, um return e onde e no possui exatamente o mesmo tipo declarado para retorno, sofrer uma converso implcita se possvel). O compilador javafxc ir transformar as funes em mtodos idnticos aos do Java, com uma assinatura no bytecode que inclui os tipos dos parmetros e do retorno, sendo que esta assinatura influi na compilao e na compatibilidade binria de outras classes compiladas com invocaes ao mtodo (funo) em questo. Assim, as funes de JavaFX Script podem ser tambm invocadas a partir de classes Java, de maneira direta e tipicamente sem nenhum overhead. Os tipos dos parmetros, surpreendentemente, tambm podem ser inferidos. Isso possvel se houver pelo menos uma invocao funo no mesmo script, ou em atribuies ou inicializaes para uma propriedade tipada como funo: 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 determina que os parmetros a e b de teste() so do tipo Number, devido presena da invocao teste(10, 15). No segundo exemplo, ao compilar a ltima linha onde instanciamos um objeto do tipo A, a function (x) {...} no exige declarar que x uma String pois esta funo est sendo atribuda propriedade A.b, e para esta atribuio ser vlida, a funo 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 relao completa na Tabela 4. Mais explicaes (sobre a necessidade dos novos nveis) na prxima seo. Mas antes de chegar l, podemos destacar um fato interessante: JavaFX no possui um nvel de visibilidade private. Voc logo entender o motivo.

Propriedades JavaFX Script utiliza o termo propriedade ao invs de atributo. Propriedades so atributos de classes, mas com alguns recursos adicionais em comparao com os atributos do Java.

Tabela 4: Nveis de visibilidade.


A Tabela 5 resume a sintaxe, que complementamos com as seguintes explicaes: No se usa getters ou setters. Propriedades so declaradas com visibilidade pblica. Para propriedades que voc no deseja que possam ser modificadas arbitrariamente, basta usar os nveis public-init (equivalente a um atributo do Java que s pode ser inicializado por um construtor) ou publicread (equivalente a um atributo do Java que possui getter, mas no setter); No h construtores. Objetos so instanciados com uma sintaxe de objetos literais; Triggers. As propriedades podem possuir triggers, que so funes invocadas automaticamente quando o valor da funo for modificado. Isso substitui a necessidade de setters para alteraes no-triviais de propriedades; Binding. O recurso de binding (ver seo Binding) permite manter diversas propriedades associadas entre si de forma automtica. Para quem vem de uma linguagem OO tradicional como C++ ou Java, podero parecer herticas idias como no encapsular atributos com getters e setters, ou no dispor de um nvel de visibilidade private. Mas analisando a linguagem como um todo, podemos entender seu design. A soma de recursos como visibilidade mais refinada (especialmente public-init e public-read), instanciao estilo JSON, triggers e binding, substitui 99% das necessidades de getters, setters e construtores. Ou seja, seus atributos (opa, propriedades!) continuaro to bem encapsulados quanto antes, s que com um cdigo bem mais simples - e, de quebra, algumas novas facilidades. Quanto visibilidade private, esta no 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 JavaFX a lgica igual: todo o cdigo contido por um script .fx fortemente acoplado (se no for, divida-o em vrios scripts). JavaFX s torna explcito e homogneo um design que, em Java, acidental e imperfeito. Acidental, pois no era assim no Java 1.0 - mudou no 1.1 quando as classes aninhadas/inner foram criadas. Imperfeito, pois Java permite definir vrias classes no mesmo arquivo .java (desde que s uma seja pblica), mas no h privilgios de acesso a membros privados entre estas classes - embora o mesmo argumento de alto acoplamento seja vlido. Ilustrando de forma mais aplicada as sintaxes de propriedades e construo de objetos, apresento novamente o Al Mundo da JavaFX:

Stage { title: "Aplicao 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 cdigo acima constri a aplicao completa (ok, faltando s as declaraes package e import). Este cdigo instancia (e retorna - ver seo Controle) um objeto Stage. Este objeto inicializado com o valor 250 para a propriedade 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 inicializada com uma funo deste tipo. Teoricamente, voc poderia fazer o mesmo em Java, com expresses new aninhadas. Mas h trs problemas. Primeiro, os construtores do Java so rgidos - se um objeto com os atributos a, b, ca,b), inicializar apenas a exige passar explicitamente o valor default de b, e inicializar c exige invocar setC() aps a construo (saindo alm da inicializao hierrquica). O segundo problema que os frameworks Java no costumam trabalhar com atributos funcionais como onClose, preferindo design patterns como Template Method (um mtodo onClose() que pode ser redefinido) ou Observer (um mtodo como addCloseListener()); ambos suportam uma expresso nica de inicializao, mas ao custo de cdigo bem mais confuso devido horrvel sintaxe das inner classes. Terceiro, a invocao de construtores no indica o nome dos argumentos, de forma que expresses de construo longas e/ou aninhadas tendem a ficar difceis de ler se voc no souber de cor qual argumento que vai em cada posio (ou se isso no for evidente pelos valores passados). Alguns frameworks Java modernos adotam o pattern de APIs fluentes no qual mtodos terminam com um return this, o que permite encadear expresses como: new X(a).setB(b).setC(c), etc. Um mtodo addXxxListener() tambm poderia seguir este design. Mas o resultado, mais uma vez, bem pouco elegante. Na minha opinio, uma tentativa pobre de imitar a linguagem Smalltak, na qual o estilo fluente natural devido sua sintaxe de mensagens (no h parmetros posicionais) e ao fato de todos os mtodos retornarem this por default (no existe o tipo void). E como, na definio 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 - no muito oba-oba em cima de uma economia de algumas linhas de cdigo para inicializar objetos complexos? Acontece que esta facilidade sinttica possui outros efeitos colaterais positivos. Por exemplo, voc pode usar a sintaxe de notao de objetos literais do JavaFX para muitas tarefas onde tipicamente usaria XML, resultando num cdigo que mais enxuto e legvel, fcil de emitir e interpretar (como sabe qualquer programador JavaScript que prefere JSON a XML). Um exemplo concreto disso o formato grfico FXD (ver Edio 67), nada mais que cdigo JavaFX com inicializaes de classes grficas. Outro exemplo a construo da rvore de componentes e eventos da GUI, ilustrada acima: este cdigo, alm de enxuto e legvel, ideal para manipulao de ferramentas. Por tudo isso, JavaFX dispensa a necessidade de linguagens de descrio de GUI como XAML (Silverlight), MXML (Flex), XUL (Mozilla), layouts do Android, etc. A falta de algo equivalente (uma DSL para GUI & grficos) no uma lacuna de JavaFX, pelo contrrio, sua presena em plataformas competidoras revela inadequaes das linguagens de programao principais destas plataformas. Na JavaFX, o FXD inclusive bom o suficiente para substituir o formato

SVG de grficos vetoriais. Binding Binding uma das caractersticas mais famosas de JavaFX Script, pois alm de ser um poderoso recurso de programao em geral, uma pea essencial para os frameworks e o estilo de programao da plataforma JavaFX. Se voc (como eu) comeou aprendendo sobre binding examinando os fontes de diversos demos que s utilizam as duas variantes mais simples deste recurso (bind x = y e criao de objetos com binding igualmente simples em propriedades), poder se surpreender com a Tabela 6, que mostra uma sofisticao extraordinria. 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 cdigo acima, o output ser o seguinte: -> DomSegTer -> DST SegTer -> TERQUA DST -> DTT DTT -> DTQ As duas primeiras linhas so efeito das atribuies dos valores iniciais a dias, e por conseqncia do binding, a iniciaisDias - pois a trigger disparada inclusive para a atribuio inicial. (Note que ao exibir sequences com o recurso de mesclagem de strings, os elementos so concatenados.) Na terceira linha, que o que mais nos interessa, SegTer -> TERQUA vemos que o binding de iniciaisDias foi acionado pela atribuio a dias; sendo que esta atribuio modificou apenas dois dos seus elementos. Na quarta e quinta linhas, vemos que o for (d in dias) reexecutado somente para estes elementos (dias[1..2]), e as alteraes de iniciaisDias tambm so feitas de maneira incremental: repare que so geradas duas alteraes independentes para os elementos de ndice 1 ("S""T") e 2 ("T""Q"), ao invs de uma alterao nica que causaria um log "DST -> DTQ". Podemos concluir vrias coisas. Primeiro, como j disse, o binding do Java vai bem alm daqueles casos simplrios que voc viu em javafx.com/samples; um recurso que pode ser explorado de inmeras formas. Segundo, as capacidades das sequences do Java so ainda mais incrementadas pelo tratamento especial de outros recursos da linguagem, como triggers e binding - de uma forma geral, a linguagem tenta otimizar o esforo destas operaes tornando-as o mais incrementais possveis (se voc tem uma sequence de 1000 elementos e altera apenas um elemento, isso no ir gerar execues de triggers ou bindings considerando todos os 1000 elementos). Como nada perfeito, um alerta: binding pesado, especialmente devido s capacidades de avaliao incremental de sequences e expresses complexas. Para cada varivel sujeita a binding e cada expresso bind, o runtime obrigado a manter na memria estruturas de dados relativamente grandes. por isso que voc pode encontrar na internet algumas pessoas comentando que ficaram horrorizadas ao ver que uma varivel Boolean ocupava 100 bytes ou mais. Use este recurso apenas quando necessrio (especialmente na JavaFX Mobile). Operadores J apresentamos alguns operadores da JavaFX especializados em sequences; veremos agora os operadores mais convencionais para manipulao de valores em geral. A Tabela 7 revela algumas das minhas poucas discordncias do design de JavaFX Script. Alguns operadores desviam de Java, a meu ver gratuitamente: por que, por exemplo, and ao invs de &&? O argumento que operadores nomeados so mais simples que smbolos misteriosos como &&, mas no

engulo isso, lembrando que linguagens RIA competidoras, como JavaScript e ActionScript, utilizam os operadores simblicos tradicionais da famlia C. Os operadores simblicos so mais legveis pois se destacam de nomes de variveis e funes; ao ler um cdigo como aa || bb && cc, a distino entre operadores/operandos imediatamente clara, o que no 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 variveis. Pior que isso, vejo algumas inconsistncias: a exclamao ! foi substituda por not como operador de negao, mas no operador diferente-de !=, continuamos vendo a exclamao indicando negao. Mais: o | de [a | a > 5] e o where de for (a in b where a > 5) tm exatamente o mesmo significado... nada perfeito, e na minha opinio, a sintaxe de operadores no-simblicos um lugar onde o design de JavaFX Script derrapou. Outras divergncias me parecem OK. O operador de typecast as mais elegante que o do Java, pois sendo posfixado, coerente com a ordem de avaliao, ex.: dVar * 2.0 as Integer, temos primeiro uma multiplicao entre variveis Double, depois sua converso para Integer, e observe tambm que no precisamos usar parnteses - (dVar * 2.0) as Integer - pois a precedncia 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 expresses de JavaFX Script. JavaFX no possui operadores de manipulao de bits, como |, &, ^, ~, <<, >> e >>> do Java. O veterano de C/C++/Java dentro de mim tambm no gostou disso primeira vista, mas acabei entendendo, pois estes operadores so de uso muito raro na enorme maioria das aplicaes, e JavaFX Script uma linguagem dedicada camada de aplicao - no se supe que algum v us-la para escovaes de bits como algoritmos de compresso ou criptografia. Principalmente lembrando que JavaFX uma linguagem parceira de Java: trivial invocar mtodos de casses Java a partir de JavaFX e vice-versa, misturar ambas classes no mesmo projeto/IDE etc. Alm disso, JavaFX reserva os tokens << e >> para outro propsito: escape de literais externas. Por exemplo, se voc tiver que invocar um mtodo bind() de uma classe Java, pode faz-lo com obj.<>(argumentos). Sem o escape isso seria ilegal por que bind uma palavra-chave em JavaFX. Java 7 tambm ter um mecanismo de escape similar.

Controle JavaFX Script, como qualquer linguagem de programao, precisa de estruturas de controle como decises e loops. Voc poderia imaginar que pelo menos nesta rea, a linguagem seria praticamente igual a Java. Engano, tambm aqui JavaFX apresenta inovaes poderosas, muito embora mantenha uma boa similaridade sinttica com Java. Veja a Tabela 8.

Tabela 5: Estruturas de controle.

Comearemos pela novidade conceitual: JavaFX Script uma linguagem orientada a expresses. No existe a dualidade entre statements (que no geram nenhum valor, como o if do Java) e expresses (que retornam um valor, como x + y). Porm, nos casos onde no h nenhum valor que faa sentido associar a determinada expresso, seu tipo definido como Void. Isso pode parecer malandragem, qual a diferena entre um statement e uma expresso Void? A maior diferena tcnica: a gramtica da linguagem fica mais simples e unificada, o nico efeito do Void no permitir o uso de determinada expresso no lado direito de lugares que exijam um valor, como uma atribuio. Porm, podemos ver que a linguagem faz um grande esforo para que quase tudo seja uma expresso normal (no-Void). Notavelmente, as estruturas de controle if e for so expresses que retornam valores. Vemos tambm que num bloco de cdigo, o return geralmente desnecessrio 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 expresso que possui valor, o qual pode ter tipo Void (se termina por um return sem valor ou outra expresso de tipo Void) ou outro tipo qualquer. E no, a Tabela 8 no est incompleta: Veja o quadro Cad o switch?. Cad o switch? Se o leitor viu a Tabela 8 com as estruturas de controle de JavaFX e estiver perguntando onde est o switch?, a resposta simples : no 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 substituda por polimorfismo ou outras tcnicas. Em JavaFX, tiveram a coragem 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 no sentirmos falta do switch, precisamos de outros mecanismos (o polimorfismo nem sempre adequado). JavaFX j possui parte da soluo (funes de primeira ordem) - melhor ilustrar com um exemplo prtico: [ function() function() function() function() ][valor](); { { { { println("Case println("Case println("Case println("Case 0"); 1"); 2"); 3"); } } } }

Ao invs de case, usamos uma sequence contendo uma funo com o cdigo correspondente para o case do seu ndice. Ao invs de switch(valor), usamos o valor para indexar a sequence, obtendo e executando a funo que contm o cdigo deste caso. Note que os casos poderiam ter parmetros e retornar valores (desde que todos tenham a mesma assinatura: isso ser verificado pelo compilador!), o que j tornaria esta tcnica mais poderosa que o switch/case do Java. Observe mais uma vez a inferncia de tipos de JavaFX: no exemplo, o tipo da sequence function() [].Digamos que voc edite apenas um dos casos e coloque um parmetro Integer na funo; ento o tipo inferido ser o tipo mais elementar compatvel com todos os casos - no caso, um tipo Function genrico (herdado por todos os tipos de funo). Mas se voc utilizar a sequence como no exemplo, indexando-a e executando a invocao com (), o compilador exige que todas as funes possuam assinatura compatvel com a da invocao - no caso, nenhum parmetro - e reclamar de qualquer caso que seja diferente disso. O maior problema que nem todos os switch/case possuem um domnio de valores como 0, 1, 2..., que se prestem ao mapeamento para ndices de sequence. O ideal seria ento usar mapas (sequences associativas), o que permitiria criar uma estrutura como [ "Ouros": function() { println("Ouros"} ], etc.; isso tambm permitiria o uso de objetos arbitrrios, no s nmeros, como chave. Infelizmente JavaFX ainda no possui nenhum suporte nativo a estruturas de dado deste tipo - pode-se usar as do Java como java.util.HashMap, mas isso no teria facilidades como uma sintaxe especializada de inicializao e indexao. Uma verso futura da linguagem possuir este suporte a mapas, provavelmente a JavaFX 2.0 (ver JFXC642 no JIRA). Mas tambm seria bom permitir a declarao de funes 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 hiptese voc pode simplesmente usar ifs em cascata, o que em JavaFX talvez no seja ruim, lembrando que if uma expresso e voc pode escrever cdigo como: def sobrenome = if (nome == "Osvaldo") "Doederlein" else if (nome == "Eduardo") "Spnola" else "Silva"; o que mais enxuto que, com um switch, ter que fazer uma atribuio separada para sobrenome em cada case. (Para um exemplo to trivial o Java permitiria usar o ternrio ?:, mas no se os cases tivessem que executar algum statement antes do valor retornado.) Mas esta soluo ainda incomoda um pouco: esteticamente, o primeiro caso (if) no tem um cabealho idntico aos demais (else if); e a repetio de "nome ==" tambm me incomoda um pouco, ainda que seja mais legvel e genrica que os cases. Eficincia no um problema pois o compilador poderia reconhecer uma cascata de ifs com estrutura similar a um switch, e gerar cdigo idntico (com bytecodes tableswitch ou lookupswitch). Generators Uma vantagem do design orientado a expresses de JavaFX, e seu uso de tipos de dados de alto nvel como sequences e estruturas de controle avanadas como generators (for), que o javafxc tem oportunidade para fazer otimizaes 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 iterao do loop. Mas no exatamente assim; o compilador s faz isso se necessrio. Assim, no cdigo 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 atribuda a y. Porm, neste outro cdigo: def x = [1, 2, 3] for (n in x) n * 2 o for s ir avaliar a expresso n * 2 para cada n in x, mas nenhuma sequence ser criada, pois o valor de retorno do for no est sendo utilizado de qualquer forma (como termo de outra expresso, ladodireito de atribuio, etc.). Classes JavaFX uma linguagem OO baseada em classes, com sintaxe bsica parecida com Java, mas com pelo menos um grande desvio do design de Java. 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 compilao, isso permite integrar o paradigma de herana mltipla generalizada da JavaFX Script ao modelo OO do bytecode / JVM, que suporta herana mltipla apenas para interfaces com mtodos abstratos. Para saber mais sobre a linguagem acesse a Apresentao JavaFX Script - Referncia Rpida. A Tabela 9 resume a sintaxe das classes de JavaFX. No existem interfaces, apenas classes, e a herana mltipla suportada para tudo (funes abstratas e concretas, e at mesmo propriedades). Classes da JavaFX podem inclusive herdar qualquer coisa de Java (tanto classes quanto interfaces). Ou seja, JavaFX Script unifica nossas class e interface numa nica entidade, tambm no exigindo distinguir entre extends e implements.

Tabela 6: Classes
Por que uma nova linguagem? Ao serem apresentados JavaFX, muitos desenvolvedores tm a seguinte reao: aprovam as funcionalidades, o framework, mas... isso precisava de uma nova linguagem? No daria para suportar todos os recursos da JavaFX com APIs orientadas linguagem Java, ou talvez, uma sintaxe Java estendida (mantendo compatibilidade retroativa) ao invs de inventar outra linguagem separada? A resposta curta: Sim, seria possvel fazer tudo com Java ou com uma extenso de Java... porm, no seria uma boa idia. Vamos explicar os porqus - a resposta longa. Produtividade Competitiva Todas as plataformas RIA competidoras utilizam alguma linguagem de programao considerada de alta produtividade - pelo menos segundo alguns critrios, como alta densidade de cdigo (mais funcionalidade com menos linhas de cdigo) e facilidade de prototipao. 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 caractersticas de alta produtividade, como: inferncia de tipos, binding, sequences, inicializao declarativa de estruturas hierrquicas de objetos, sintaxes de alto nvel para diversas necessidades de programao geral (desde o simples relaxamento na pontuao at o for turbinado), e sintaxes especiais para algumas APIs. Agilidade Quando se fala em evoluo da linguagem Java, no podemos nos esquecer que a Sun no dona do Java. A especificao 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 influncia no JCP, isso no inclui carta branca para fazer o que quiser com a plataforma. Em especial, a evoluo de especificaes preexistentes sempre torturante pois precisa levar em conta os interesses de diversos players com voz no JCP, e possivelmente grande investimento na tecnologia em questo. A quebra de compatibilidade retroativa virtualmente impossvel. A Sun chegou atrasada briga do RIA. Se fosse seguir o caminho de estender a linguagem Java (mesmo que isso fosse tecnicamente uma boa idia), ou criar a JavaFX sob os auspcios do JCP, o lanamento da JavaFX 1.0 levaria pelo menos o dobro do tempo, e a sua evoluo at a JavaFX 2.0 levaria 3-4 anos ao invs de um ano. Isso liquidaria qualquer chance da JavaFX de competir. rgos de padres como o JCP so excelentes para tecnologias j razoavelmente maduras, mas so quase sempre pssimos para criar coisas completamente novas - a inovao raramente acontece em comits. Imperativo ou Funcional? Na minha mania de aprender novas linguagens mexendo em cdigo dos outros, cheguei ao seguinte 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, invocando os mtodos update() e isdead(), e deletando da sequence aqueles que esto mortos. Mas achei esse cdigo feio, confuso, ento 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 verso faz uma substituio nica da sequence antiga pela nova, a qual criada da seguinte forma: primeiro temos um forisdead() a update()), e depois temos a nova Particle. O [...] mais externo serve concatena a sequence gerada pelo for com o objeto final, sendo que graas ao flattening automtico, o resultado ser uma sequence simples com todos estes elementos. A nova verso caracterstica do estilo funcional, evitando alteraes repetitivas como insert e delete. Sobrou uma alterao de varivel (parts = ...), mas uma s, e mesmo esta atribuio s restou por que eu no quis reescrever o programa todo. um cdigo bem mais limpo, menor (10 linhas ao invs de 14) e mais simples (sua complexidade ciclomtica - quantidade e aninhamento de estruturas de controle - menor.) Mais importante, a verso funcional idntica a uma descrio formal / matemtica do algoritmo, que podemos enunciar como: o novo conjunto de partculas formado pelas partculas preexistentes que aps o update() continuem vivas, mais uma partcula nova. por isso que tanta gente gosta de programao funcional: o estilo de programao que permite traduzir, de forma direta, algoritmos especificados de forma matematicamente rigorosa (que quase sempre a descrio mais enxuta e elegante possvel). Bem, agora as ms notcias. Testando meu novo cdigo, este funcionou, mas com um desempenho muito pior. O problema que a sequence parts amarrada, via binding, ao scene graph da animao do programa; porm, o binding de sequences no otimizado para o cenrio de substituio total de uma sequence (com uma atribuio explcita), apesar de ser otimizado para manipulaes pontuais como insert e delete A otimizao em questo evita que o scene graph inteiro seja reconstrudo em cada frame da animao, o que resulta em pssimo desempenho. Ou seja, no se trata de um bug/limitao de desempenho das sequences propriamente ditas, mas somente da combinao entre sequences e binding, ou talvez, do runtime do scene graph. Registrei um novo bug descrevendo o problema (javafxjira.kenai.com/browse/JFXC-2911). o tipo de coisa que, infelizmente, podemos esperar de um software complexo como a JavaFX que ainda praticamente recm-lanado no momento em que escrevo. Mas no tira o mrito do estilo de programao 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 no terminou). Concluses Este artigo encerra uma primeira trilogia de JavaFX, na qual cobrimos os aspectos principais desta nova plataforma: tecnologia RIA, mobilidade, linguagem de programao, pontos principais do framework. A partir deste ponto, minha expectativa que um leitor que sabe programar Java e tem interesse pela plataforma JavaFX possa andar com seus prprios ps, chegando ao ponto de desenvolver aplicaes RIA sofisticadas para desktop e dispositivos mveis. H duas partes da JavaFX que cobrimos de forma superficial: os recursos de mdia (ver Edio 67) e as APIs javafx.* (ver Edio 68). Estes temas renderiam, seguramente, pelo menos mais dois captulos da srie. Mesmo na linguagem JavaFX Script, coberta neste artigo, existem tpicos especficos que poderamos explorar, como a integrao com Java, ou o desempenho. Mas preferi parar por aqui, por trs motivos. Primeiro, a plataforma JavaFX ainda muito recente e ainda difcil avaliar o interesse dos leitores por uma cobertura to contnua e abrangente. Segundo, o mundo no parou por causa da JavaFX, e h outros temas que pretendo cobrir nas prximas edies. Terceiro, a JavaFX ainda est em rpida evoluo: no caso especfico dos frameworks, no vou gastar nosso tempo (meu e dos leitores) com um artigo sobre os frameworks da JavaFX 1.1, quando sei que j em junho deste ano (quando nossa prxima Edio j estaria nas bancas) a Sun ter lanado a JavaFX 1.5, com muitas novidades especialmente nas APIs. Resumindo, espero que o leitor tenha apreciado estes primeiros artigos, tanto quanto eu apreciei escrev-los... chegou a hora de fazer uma pausa, mas com planos de voltar JavaFX daqui a algumas edies, com as baterias recarregadas.

Saiba Mais http://www.devmedia.com.br/resumo/default.asp?idrev=123#1515 Java Magazine 67 - JavaFX: RIA a todo vapor http://www.devmedia.com.br/resumo/default.asp?idrev=130#1590 Java Magazine 68 - JavaFX: Tutorial

Novos tempos: javax.time

Daniel Cicero Amadei Bacharel em Sistemas de Informao pelo Mackenzie e ps-graduado pela Fundao Vanzolini. Trabalha com Java desde 1999 e possui as certificaes SCJP, SCWCD, SCBCD, SCDJWS, SCEA, BEA Certified Developer: Integration Solutions e BEA Certified SOA Architect. J atuou como Desenvolvedor, Analista e Arquiteto de Sistemas e atualmente Consultor em Arquitetura Oracle | BEA. Blog: http://www.amadei.com.br

Michael Nascimento Santos 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. 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 so discutidas e exemplificadas. Alm disso, so abordadas as lacunas presentes nas classes atuais (Date e Calendar) e como a javax.time enderea tais problemas. Para que serve: Apresentar a nova API de datas e horas que ser incorporada na plataforma Java, provendo discusses sobre a sua arquitetura e exemplos de uso da API, alm de comparaes com as classes atuais. Em que situao o tema til: O tema importante para qualquer um que deseje estar atualizado sobre as novas tendncias da plataforma Java. A manipulao de datas e horas pea-chave em qualquer implementao e a criao de uma nova API tende a facilitar muito a vida do desenvolvedor. Novos tempos: javax.time: O artigo aborda a nova API para representao de datas e horas da plataforma Java e como ela facilita a vida do desenvolvedor Java, corrigindo bugs e endereando problemas das classes atuais Date e Calendar. A nova API possui representaes distintas para datas que sero utilizadas para clculos computacionais e datas que sero utilizadas por seres humanos. Alm disso, temos representaes padro para tipos de dados que atualmente precisamos criar como duraes, perodos e intervalos. 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 vrios 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 questionvel. Veremos algumas dessas decises arquiteturais dbias, alm 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, perodos, instantes, duraes, entre outros. Sem classes que representem essas unidades do mundo real, necessria a criao de solues paliativas por conta e risco dos desenvolvedores. Isso resulta em mais codificao e cdigo legado para manuteno. Esses pontos claramente abrem espao 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 inconsistncia. A classe java.util.Date no representa uma data, mas sim um instante na linha do tempo. Desta forma, no temos como representar somente uma data ou somente o tempo. Outro exemplo de inconsistncia o fato da classe Date utilizar anos com base em 1900, enquanto a Calendar requerer os anos completos, incluindo o sculo. O cdigo apresentado a seguir, apesar do uso de um construtor descontinuado (deprecated), ilustra a criao de uma data cujo ano ser 3909, ao contrrio do que parece ao ler o cdigo. Date date = new Date(2009, 2, 1); O incio dos meses em 0 (Zero) na classe Calendar tambm algo que tem atrapalhado a vida dos desenvolvedores Java de forma considervel. Por exemplo, para criar uma instncia de Calendar que represente a data 01/01/2009, temos que escrever o seguinte cdigo: Calendar calendar = new GregorianCalendar(2009, 0, 1); Alm disso, temos uma srie de outros problemas arquiteturais ou de implementao: Os objetos so mutveis, inseguros em ambiente multi-thread, requerendo sincronizao; No h como formatar uma instncia de Calendar usando as classes do pacote java.text; No existe opo para representar perodos ou duraes de forma padronizada; As APIs atuais exigem muito cdigo para tarefas rotineiras de manipulao de datas e horas. Sem mencionar ainda que muitas dessas tarefas rotineiras constituem casos de uso comuns e poderiam ser implementados pelas prprias APIs. Esses so apenas alguns dos problemas que a JSR 310 ir resolver. Os j velhos conhecidos problemas devido s alteraes no horrio de vero tambm esto sendo endereados. Alm de tudo isso, voc ver que a API muito mais intuitiva e ir lhe poupar muitas e muitas linhas de codificao. Princpios de Design da JSR 310 A JSR 310 tem sido elaborada com alguns princpios para facilitar seu uso e entendimento e tornar seu cdigo mais robusto e de fcil leitura. Baseada em padres A nova API est sendo construda totalmente alinhada com o ISO-8601, um padro internacional para representao de datas e horas. Imutvel Os principais objetos da nova API sero imutveis. No ser possvel alter-los aps a construo. Tambm sero thread-safe, podendo at mesmo ser singletons. A seguir, um primeiro exemplo, da criao 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 classe representa uma data sem fuso horrio (time zone) no padro ISO-8601, resultando em 2009-01-01. Caso desejemos

alterar o ano dessa data, por exemplo, para 2010 no iremos utilizar um mtodo set(). Neste caso, devemos utilizar um mtodo with(), que cria uma nova instncia da classe com o ano desejado. O cdigo ficaria conforme apresentado a seguir: date = date.withYear(2010); Repare na atribuio ao objeto date com o resultado da invocao do mtodo. Isso necessrio, pois criado um novo objeto, mantendo o original inalterado, pois os objetos envolvidos so imutveis. Interfaces Fluentes As classes e interfaces seguem o padro de fluncia para permitir uma melhor legibilidade do cdigo. Isso transforma as invocaes a mais do que um mtodo em sentenas de fcil leitura. O cdigo apresentado a seguir, alm do ano, altera o ms e o dia. date = date.withYear(2010). withMonthOfYear(3).withDayOfMonth(2); Clareza Os mtodos so bem definidos e indicam claramente seu propsito. Por exemplo, para subtrair dois anos de uma data qualquer, utilizamos o seguinte cdigo: date = date.withYear(2010). withMonthOfYear(3). withDayOfMonth(2); date = date.minusYears(2); Isso ir resultar na data 2008-03-02. Muito mais claro do que o mtodo roll(int field, int amount) da classe Calendar. Extensvel Atravs de pontos de extenso, utilizando conceitos do design pattern Strategy, possvel controlar e customizar como a API se comporta em relao s datas e horas. Mesmo assim, no necessrio ser um especialista para usar a API. So fornecidas implementaes padro para a maioria dos cenrios. Um exemplo desses ganchos para extensibilidade 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. Alm disso, a javax.time traz consigo uma classe utilitria, a javax.time.calendar.DateAdjusters, contendo implementaes dos casos de uso mais comuns para o ajuste de datas. Essas implementaes devem satisfazer a maioria das necessidades de desenvolvimento. O cdigo apresentado a seguir ilustra o ajuste sendo realizado em uma data: LocalDate date = Clock.systemDefaultZone().today(); date = date.with(DateAdjusters. next(DayOfWeek.MONDAY)); O cdigo que apresentamos, alm do ajuste da data, apresenta uma nova classe: javax.time.calendar.Clock. Essa classe um faade para o acesso data e hora correntes. O mtodo today(), que invocamos na classe Clock, retorna a data corrente como uma instncia de LocalDate. Voltando a falar sobre o ajuste da data, ele ocorre na invocao ao mtodo with(). Informamos DateAdjusters.next(DayOfWeek.MONDAY) como parmetro do mtodo. O objeto retornado pelo mtodo next() responsvel por ajustar a data para a segunda-feira subsequente data informada. Avaliando as datas, caso executemos tal cdigo no dia 05/02/2009, aps 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 aplicabilidade seria o ajuste das datas para dias teis. Voc pode, ainda, implementar seu prprio adjuster - digamos, para saltar feriados obtidos de um cadastro de feriados do seu sistema. Duas escalas para lidar com tempo A javax.time apresenta duas formas distintas para lidar com o tempo. Uma escala voltada para mquinas, denominada Continuous e a outra com foco em datas para seres humanos, denominada Human. Continuous Essa abordagem da javax.time voltada para mquinas e representa o tempo na forma de um nmero incremental, sem muito significado para seres humanos, porm com grande valor para uso em processamentos que requerem clculos envolvendo timestamps. Instant A classe javax.time.Instant representa um ponto instantneo na linha do tempo, um instante de tempo, conhecido tambm como timestamp. Possui preciso de nanossegundos e 96 bits para armazenamento. Atravs dessa abordagem, possvel armazenar at algumas centenas de vezes uma data equivalente ao tempo de existncia do universo. (Para os curiosos, o universo tem em torno de 13,8 bilhes de anos.) A seguir, um exemplo onde validamos se um instante superior a outro utilizando o mtodo isAfter(). Instant instante1 = Clock.systemDefaultZone().instant(); //qualquer cdigo aqui Instant instante2 = Clock.systemDefaultZone().instant(); boolean avaliacao = instante1.isAfter(instante2); Duration A classe javax.time.Duration representa uma durao de tempo. Dentro da javax.time, ela representa a durao entre dois instantes. O instante inicial que forma uma instncia 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 cdigo 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 cdigo apresentado, vemos primeiramente a criao de dois instantes. O primeiro representa o momento exato da execuo, enquanto que o segundo derivamos a partir do primeiro com a soma de 60 segundos. Repare no mtodo plusSeconds(). Ele conciso, bem definido e indica exatamente seu propsito e a unidade manipulada. Aps a criao dos instantes, criamos uma durao entre eles, que dever conter exatamente 60 segundos. Ao imprimir a durao no console, temos a impresso da durao utilizando o padro ISO-8601. InstantInterval A classe javax.time.InstantInterval representa um intervalo de instantes na linha do tempo. A classe pode possuir intervalos inclusivos, exclusivos ou algum dos intervalos pode no estar associado, isso quer dizer que podemos criar o intervalo com apenas o instante de incio e posteriormente associar o instante final. O cdigo apresentado a seguir ilustra a criao de um intervalo a partir de dois instantes e a posterior verificao 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 mtodo padro, o intervalo inicial inclusivo e o final exclusivo. Existe outro mtodo que recebe valores booleanos indicando se desejamos que cada um dos intervalos seja inclusivo (true) ou exclusivo (false). Alm disso, podemos construir a instncia de InstantInterval a partir dos mtodos builder: intervalFrom() e intervalTo(). Human Essa abordagem da javax.time voltada para seres humanos. Ela representa os valores de datas e horas utilizando campos com classes especficas para representar cada um dos dados do calendrio: ano, ms, dia, hora, minuto e segundo. Alm desses campos mais comuns, temos algumas outras classes ou enumeraes para representar, por exemplo, o dia do ano, a semana do ano, os nanossegundos de cada segundo, entre outras. Atravs da abordagem para seres humanos, temos formas (classes!) para representar datas e horas, datas sem hora, horas sem data, offsets e time zones. Datas e Horas locais (sem time zone ou offset) Os tipos mais simples presentes dentro da javax.time so os tipos chamados de locais. Esses tipos podem representar data ou hora de forma isolada ou as duas em conjunto. So chamadas de locais por no estarem associados a um offset ou time zone. LocalDate A primeira classe que mereceria nossa ateno seria a javax.time. calendar.LocalDate. Como j estamos cansados de ver exemplos envolvendo essa classe, pois a que estamos acompanhando no decorrer do artigo, veremos algo a mais. A representao dos campos de datas e horas dentro das classes efetuada atravs de classes com este propsito. Com isso, essas classes contm mtodos implementando aes comuns, requeridas de cada um desses campos que compem nossas datas e horas. A javax.time utiliza como padro os mtodos get() retornando valores numricos para tais campos, por exemplo, getYear() retorna o ano como um inteiro e os mtodos to() retornam as classes especficas, no caso do ano, seria a classe javax.time.calendar.field.Year. O exemplo apresentado a seguir ilustra o uso do mtodo 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). Teramos que fazer esse clculo manualmente, cada um em seu projeto, testar esse cdigo e mant-lo. No exemplo apresentado a seguir, temos a obteno do ms, representado pela enumerao javax.time.calendar.field.MonthOfYear e, a partir dela, obtemos o ltimo dia do ms 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 tambm, com a obteno do ltimo dia do ms, o grande valor no uso de classes especficas em comparao com tipos primitivos. O clculo do ltimo dia do ms resolvido automaticamente pela API, poupando voc, desenvolvedor, desse (grande) trabalho. LocalTime A classe javax.time.calendar.LocalTime representa uma hora sem time zone ou offset. O trecho de cdigo apresentado a seguir imprime a hora corrente e, posteriormente, 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 representa uma data e hora sem time zone ou offset. O trecho de exemplo apresentado a seguir imprime a hora corrente e posteriormente 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, aps a subtrao de 36 horas, teramos 2009-02-05T23:50:08.093. Repare que o clculo ocorreu corretamente e alterou at mesmo a data. Datas e Horas com offset As datas e horas com offset representam um valor relativo ao UTC (Coordinated Universal Time ou Tempo Universal Coordenado). Esses valores relativos, ou offsets, esto geralmente casados com as reas de fuso horrio (time zones), porm a javax.time separa os dois conceitos: offsets e time zones em classes distintas. O objetivo dessa separao tratar trocas de offset por uma mesma time zone devido a horrios de inverno ou vero. OffsetDate A classe javax.time.calendar.OffsetDate representa uma data com um offset em relao ao UTC. Por exemplo, ao criar um objeto OffsetDate aqui no Brasil, na regio que segue o horrio de Braslia, temos como offset o valor -03h00min, ou seja, se em Braslia so 16h, o horrio UTC estar marcando 13h. O trecho de cdigo apresentado a seguir ilustra a obteno da data atual considerando o offset: OffsetDate hoje = Clock.systemDefaultZone().offsetDateTime().toOffsetDate(); Caso esteja sob o offset de Braslia, ao imprimir o objeto, a string 2009-02-07-03:00 teria sido impressa no console, seguindo o padro ISO-8601 para datas e horas com offset.

Nota Devman - Thread-safe Thread-safe ou, melhor dizendo, thread-safety o conceito que usamos para nomear a situao em que o acesso de mltiplas threads a um elemento no mesmo momento no apresenta resultados inconsistentes, sem que uma thread tenha interferncia sobre os dados manipulados por outra thread. A classe javax.time.calendar.OffsetTime representa um horrio com um offset em relao ao UTC, seguindo o mesmo padro da classe OffsetDate. O trecho de cdigo apresentado a seguir ilustra a obteno do horrio atual considerando o offset. Aps isso, a criao de uma nova instncia de OffsetTime contendo o mesmo horrio, porm com o offset encontrado no Japo, que +09h00min. Aps isso, fazemos uma comparao dos dois horrios com o intuito de ilustrar que a comparao levar em conta o offset. OffsetTime hojeBrasil = Clock.systemDefaultZone().offsetDateTime().toOffsetTime(); OffsetTime hojeJapao = hojeBrasil.withOffset(ZoneOffset.zoneOffset(9)); boolean horarioJapaoPosterior = hojeJapao.isAfter(hojeBrasil); Aps a execuo do cdigo apresentado, a varivel horarioJapaoPosterior ir armazenar o valor true indicando que a hora no Japo posterior. OffsetDateTime A classe javax.time.calendar.OffsetDateTime representa uma data e um horrio com um offset em relao ao UTC, seguindo o padro dos dois exemplos vistos at o momento. O cdigo a seguir ilustra a obteno de uma OffsetDateTime. OffsetDateTime hojeBrasil = Clock.systemDefaultZone().offsetDateTime(); Ao imprimir essa varivel no console, temos uma string representando a data, horrio e o offset seguindo o padro ISO: 2009-02-09T23:20:54.171-03:00. Time Zones Alm de objetos capazes de armazenar o offset, temos a classe javax.time.calendar.ZonedDateTime que armazena tambm o time zone. O time zone representado pela classe javax.time.calendar.TimeZone que tem o propsito de tratar regras e excees das alteraes nos offsets das regies mundiais. Essas alteraes geralmente se devem a mudanas no horrio de vero ou inverno. Dentro da javax.time, possvel instanciar a classe TimeZone a partir de um identificador da base de time zones zoneinfo ou a partir do offset em relao UTC. O cdigo apresentado a seguir ilustra a obteno de duas instncias de ZonedDateTime, a primeira com o time zone padro da JVM, configurado como Amrica/Sao_Paulo e o segundo forando 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 cdigo apresentado, as datas e horas correspondentes ao time zone informado so impressas no console:

2009-02-09T23:37:18.968-03:00 UTC-03:00 2009-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 no h um identificador correspondente para este time zone, ao contrrio do que ocorreu com o time zone de Paris, que criamos a partir do identificador, que apresentado na impresso do objeto. Uma forma equivalente de obter a instncia de ZonedDateTime que utilizamos a apresentada a seguir, uma vez que o time zone de Paris corresponde ao offset de uma hora em relao 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 Resolvers Como 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 realizao de ajustes em datas e horas de forma bastante flexvel. Alm dos Adjusters, a javax.time nos prov o conceito de Matchers e Resolvers, que veremos agora. Matchers Os Matchers possuem a responsabilidade de realizar consultas em datas e horas de forma muito simples e flexvel. Eles reduzem drasticamente a quantidade de cdigo e a lgica empregada neste tipo de operao. O cdigo apresentado a seguir ilustra a consulta data (e hora) atual. Nesse caso consultamos se o ano 2009, valorizando uma varivel booleana denominada ano2009. Como estamos realmente em 2009, essa varivel ser valorizada com true. LocalDateTime agora = Clock.systemDefaultZone().dateTime(); boolean ano2009 = agora.matches(Year.isoYear(2009)); A consulta envolvendo o horrio praticamente idntica, conforme pode ser visto a seguir: LocalDateTime agora = Clock.systemDefaultZone().dateTime(); boolean vinteUmaHoras = agora.matches(HourOfDay.hourOfDay(21)); possvel realizar tais operaes, pois cada uma dessas classes (Year, HourOfDay e as outras classes representando os elementos do calendrio) implementa as interfaces necessrias para executar o mtodo matches(). A interface que representa o Matcher para a consulta em datas a javax.time.calendar.DateMatcher, que possui um nico mtodo boolean matchesDate(LocalDate input). J a interface para a consulta em horrios a javax.time.calendar.TimeMatcher e ela segue o mesmo padro da outra que vimos, possuindo um nico mtodo boolean matchesTime(LocalTime time). A Listagem 1 apresenta um exemplo de implementao de DateMatcher para verificar se a data possui um dia mpar ou no. 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; } } } A classe javax.time.calendar.DateMatchers possui alguns matchers pr-configurados para voc utilizar. Entre os matchers que j vm por padro temos, por exemplo, um para verificar se estamos durante a semana ou em um final de semana, se o primeiro ou ltimo dia do ms, alm de alguns outros. O cdigo apresentado a seguir ilustra o uso da classe DateMatchers para a verificao 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 verificao de datas e nos auxiliar muito em tarefas do mundo real como, por exemplo, verificar se determinada data est dentro do domingo de pscoa ou na sexta-feira santa. Resolvers Assim como os matchers, os Resolvers so pontos de extensibilidade disponveis na javax.time. Atravs deles voc pode indicar como deseja que uma data invlida seja tratada, por exemplo, ao criar uma data no dia 29 de fevereiro em um ano que no seja bissexto. A classe javax.time.calendar.DateResolvers possui algumas implementaes dos casos de uso mais comuns onde possa vir a ser necessrio o uso de um Resolver.

O exemplo apresentado a seguir ilustra a criao de uma data utilizando um resolver provido pela classe DateResolvers que resolve uma data invlida como a prxima data vlida. LocalDate data = DateResolvers.nextValid().resolveDate(Year.isoYear(2009), MonthOfYear.monthOfYear(2),DayOfMonth.dayOfMonth(29)); Ao imprimir tal data no console, temos como data apresentada 2009-03-01. Caso voc tenha achado o cdigo verboso demais, possvel utilizar o recurso de static imports para reduzir a verbosidade. A Listagem 2 apresenta tal opo. Listagem 2. Uso de static imports para minimizar a verbosidade do cdigo 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); } } Perodos Os perodos, dentro da javax.time, so cidados de primeira-classe. Isso quer dizer que existem classes capazes de represent-los, ao contrrio do que voc encontra nas APIs atuais, onde no h forma padro para representar perodos. Atravs da representao dos perodos, podemos expressar duraes de tempo da maneira tratada pelos seres humanos como, por exemplo, a durao de uma reunio ou de suas frias. Como dito, existe uma classe para cada parte do perodo: javax.time.period.field.Days javax.time.period.field.Hours javax.time.period.field.Minutes

javax.time.period.field.Months javax.time.period.field.Seconds javax.time.period.field.Weeks javax.time.period.field.Years E uma classe para representar o perodo como um todo: javax.time.period.Period. O cdigo apresentado a seguir representa a criao de um perodo de duas horas: Period period = Period.hours(2); A partir desse momento, o objeto representa o determinado perodo para o qual foi criado. Ao imprimir tal perodo no console, impressa sua representao de acordo com o padro ISO-8106. Essa representao para o perodo de duas horas PT2H. Uma das grandes vantagens no uso de objetos especializados para os perodos permitir que voc execute operaes nesse objeto. Isso resultar na criao de outro objeto para representar o novo perodo resultante da operao. O objeto que representa o perodo tambm imutvel. A seguir, uma subtrao de quarenta minutos de nosso perodo de duas horas: period = period.minusMinutes(40); Ao executar tal operao, o perodo ainda permanece com duas horas e menos quarenta minutos e necessita ser normalizado para representar o perodo real, que seria de uma hora e vinte minutos. Normalizao O mtodo normalize() retorna uma cpia do perodo normalizado para os limites padro dos campos de data e hora, levando 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 perodo de 13 meses normalizado para um ano e um ms e a criao de um perodo de 5000 minutos com o cdigo Period.minutes(5000) resulta em um perodo normalizado de 83 horas e 20 minutos. Caso voc necessite ainda realizar a normalizao por dias, quebrando cada 24 horas em um dia, voc deve utilizar o mtodo normalizedWith24HourDays(), que neste nosso exemplo resultaria em um perodo de trs dias, onze horas e vinte minutos. Para revisar o que foi visto e por em prtica o contedo apresentado, veja a Apresentao Javax.time.

Concluso Voc conheceu um pouco sobre a nova especificao para representar datas e horas dentro da plataforma Java. Essa nova API tenta trazer vrias facilidades e corrigir problemas conhecidos das opes atuais, buscando transformar seu cdigo em algo mais legvel 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 desenvolvimento. Acesse o site da JSR (veja seo de Links) e faa parte da definio do futuro da linguagem. O cdigo apresentado neste artigo est disponvel para download no site da revista, contando com um JAR da javax.time compilado durante a escrita do artigo. Como a API ainda est sendo concebida, possvel que quando o artigo chegar a voc, leitor, algo possa ter sido alterado. Devido a isso, deixamos aqui a sugesto de baixar os fontes da ltima verso da API e adequar os exemplos s possveis alteraes. Acesse tambm a lista de discusses para entender o rumo que est sendo dado API. Links jsr-310.dev.java.net Site de desenvolvimento da JSR 310, onde voc pode obter acesso a todos os artefatos relacionados nova API, alm de participar de seu desenvolvimento, cadastrando-se nas listas de discusso. 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.

Java ME Platform SDK 3

Ernandes Mouro Jnior Bacharel em Informtica pela Universidade de Fortaleza e desenvolvedor certificado Java (SCWCD, SCBCD e SCMAD). Atualmente exerce o cargo de Analista de Sistemas e Lder Tcnico Java ME no Instituto Atlntico. De que se trata o artigo: Apresentao 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 so apresentadas de uma forma clara e objetiva para o leitor. Para que serve: Proporcionar uma apresentao objetiva das principais funcionalidades da nova ferramenta de desenvolvimento da plataforma Java ME. Esta apresentao concede ao leitor uma viso geral, mas completa, do que de novo ele pode vir a utilizar daqui para frente no desenvolvimento de suas aplicaes. Em que situao o tema til: No momento em que uma ferramenta que usamos com frequncia surge com uma verso nova, sempre vlido dar uma olhada nas principais novidades que ela vem trazendo. Estas novidades, geralmente, vm para melhorar nossa produtividade, alm de nos proporcionar mais subsdios, a fim de desenvolvermos aplicaes ainda melhores. Java ME Platform SDK 3: Assim como os seres vivos, os softwares de computador tambm evoluem a partir do momento em que se inicia um novo ciclo. No caso da principal ferramenta de desenvolvimento da plataforma Java ME, o Wireless Toolkit, este seu novo ciclo trouxe-lhe evolues bastante expressivas. Mudanas que vo 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 cdigo, emuladores, nova mquina virtual e APIs so somente algumas das muitas novidades trazidas por esta nova ferramenta. Sem falar que at o seu nome novidade, pois agora a ferramenta chamada de Java ME Platform SDK 3. Com todas essas novidades possvel constatar o grande passo que a plataforma Java ME d em direo a uma maior popularizao da plataforma. Pois com o ambiente de desenvolvimento integrado baseado no NetBeans, novos desenvolvedores tero mais facilidades de criar as suas primeiras aplicaes, o que garante uma maior chance de crescimento da comunidade Java ME. Segundo a Biologia, o processo permanente de mudana que vem transformando a vida na Terra, desde o seu princpio mais simples at a sua atual diversidade, conhecido como Evoluo. A evoluo ocorre quando um ser vivo se reproduz, e pequenas mudanas aleatrias nos seus genes fazem com que o seu descendente seja diferente dele prprio. Essas mudanas, se benficas, fazem com que o indivduo sobreviva o tempo necessrio para se reproduzir, dando incio a um novo ciclo de transformaes, o que resulta no surgimento de novas espcies. Num paralelo entre o processo de evoluo dos seres vivos com o de um software de computador, verificamos como ambos so 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 aguando a criatividade dos usurios, que solicitam novas verses mais aperfeioadas e com mais funcionalidades. Estas solicitaes induzem o software a entrar no clico de evolues, resultando em novos releases.

Neste artigo, falaremos sobre como este processo evolutivo dos softwares atingiu o Wireless Toolkit (WTK). Apresentaremos algumas das principais novidades que a Sun Microsystems preparou, justificando a mudana do seu nome para Java ME Platform SDK 3. De Toolkit para SDK O fato de a Sun ter mudando o nome do WTK no deve causar muito espanto aos desenvolvedores, tendo em vista que esta no 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 substitudo em 2007, devido nova verso 1.5 (ou 5) da plataforma Java. Desde ento, 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 tambm acabou refletindo na primeira mudana de nome do WTK para Sun Java Wireless Toolkit. A mudana do nome na nova verso, que agora insere o termo SDK (Standard Development Kit), se deve ao fato da ferramenta proporcionar um ambiente de desenvolvimento completo, e no somente os emuladores, ferramentas de monitorao (e.g. monitor de memria), cdigos de exemplo, documentao, etc. O pacote agora tambm vem com editor de cdigo com assistncia de codificao (veja a seo Netbeans Lite). Alm disso, a plataforma Java ME suportada de forma muito mais completa (o antigo WTK suportava apenas a configurao CLDC, exigindo toolkits separados para CDC e outras variantes). Um arsenal completo que eleva a categoria da ferramenta, justificando o acrscimo do termo SDK. O nome original, Java 2 Platform Micro Edition Wireless Toolkit, foi substitudo em 2007, devido nova verso 1.5 (ou 5) da plataforma Java. Desde ento, 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 tambm acabou refletindo na primeira mudana de nome do WTK para Sun Java Wireless Toolkit. A mudana do nome na nova verso, que agora insere o termo SDK (Standard Development Kit), se deve ao fato da ferramenta proporcionar um ambiente de desenvolvimento completo, e no somente os emuladores, ferramentas de monitorao (e.g. monitor de memria), cdigos de exemplo, documentao, etc. O pacote agora tambm vem com editor de cdigo com assistncia de codificao (veja a seo Netbeans Lite). Alm disso, a plataforma Java ME suportada de forma muito mais completa (o antigo WTK suportava apenas a configurao CLDC, exigindo toolkits separados para CDC e outras variantes). Um arsenal completo que eleva a categoria da ferramenta, justificando o acrscimo do termo SDK. NetBeans Lite De longe a mais importante e impactante novidade do Java ME Platform SDK 3 o ambiente de desenvolvimento integrado (veja Figura 1), baseado na plataforma NetBeans. Nas verses anteriores da ferramenta, todo o desenvolvimento das aplicaes (e.g. escrita de cdigo) tinha que ser feito numa ferramenta (IDE) parte, como por exemplo, Eclipse, NetBeans, VistaMax, etc. O trabalho do WTK era executar os emuladores, alterar configuraes de ambiente da plataforma, monitoramento de memria, dentre outras funcionalidades auxiliares. IDEs como Eclipse e NetBeans, por exemplo, permitiam que o WTK pudesse ser integrado, possibilitando ao desenvolvedor uma transparncia do seu uso. As principais ferramentas deste ambiente de desenvolvimento integrado so o editor de cdigo, gerenciador de projetos e arquivos, integrao com o Ant, configuraes do projeto (e.g. propriedades do arquivo JAD), ofuscador de cdigo, alm de outras de cunho mais geral, encontradas em qualquer distribuio do NetBeans. Quem j trabalha com o Netbeans Mobility Pack vai se sentir em casa neste novo ambiente, pois ambos so praticamente o mesmo. Alm disso, aqueles que, porventura, decidirem migrar para o NetBeans Mobility Pack futuramente, j que este dispe de mais funcionalidades, no encontraro barreiras. Pois o arquivo de projeto do Java ME Platform SDK 3 totalmente compatvel com o Mobility Pack, o que facilita muito a migrao entre as ferramentas.

Figura 1: Ambiente integrado de desenvolvimento do Java ME Platform SDK 3 baseado no NetBeans.


A KVM se Despede Aps quase dez anos desde sua chegada, a mquina 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 no estava mais presente nos dispositivos mveis disponveis no mercado, sendo esta substituda pela CLDC HotSpot Virtual 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 verso 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 tambm para os seus emuladores, inclusive para a configurao CDC. Com esta mudana, o comportamento das aplicaes no emulador ficou mais parecido ao encontrado nos dispositivos reais. Dentre as principais vantagens da CLDC HotSpot Virtual Machine, comparada KVM, esto a compilao dinmica das instrues de bytecode em instrues nativas (veja o quadro Compilao Just-in-time (JIT)), menor consumo e fragmentao de memria, maior economia da bateria, dentre outras. Em termos de nmeros, a execuo de uma instruo compilada dinamicamente, chega a ser cinquenta vezes mais rpida do que uma instruo interpretada. Para conhecer um pouco mais sobre a CLDC HotSpot Virtual Machine e a sua chegada aos dispositivos mveis, veja a seo Links, alm do artigo Java: Uma perspectiva, da Edio 65. Descobrindo as Diferenas Existe na Internet uma iniciativa chamada de Wireless Universal Resource File (WURFL), aonde desenvolvedores e entusiastas vm tentando catalogar todos os dispositivos mveis disponveis no mercado, assim como suas caractersticas. O objetivo fornecer uma base de dados centralizada para os desenvolvedores. Neste caso, um arquivo XML, afim de que eles possam conhecer, antecipadamente, as principais diferenas que existem de um dispositivo para outro, alm de ter uma idia da fatia de

mercado que suas aplicaes esto abrangendo. Com o objetivo de facilitar o acesso s informaes providas pelo WURFL (para saber mais sobre esta iniciativa, veja a seo Links), a Sun desenvolveu uma nova funcionalidade, no Java ME Platform SDK 3, chamada Device Database Search, que acessa essa base de dados de uma forma fcil e rpida. O usurio pode tanto solicitar para ver a lista completa de todos os dispositivos disponveis, como ele tambm 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 modelo e fabricante so identificados. Para ver os detalhes de um determinado dispositivo, basta selecion-lo na lista, que todas as suas informaes sero exibidas numa outra lista ao lado (veja Figura 2). LWUIT Ganha Fora A equipe do projeto Lightweight User Interface Toolkit (LWUIT) deve estar orgulhosa com esta conquista. Tendo em vista a grande popularizao deste projeto entre os desenvolvedores Java ME, a Sun no perdeu tempo em tentar transformar este projeto numa espcie de padro dentro da comunidade de desenvolvedores. Os engenheiros da Sun devem ter percebido a quantidade de projetos que existem na Internet, que visam melhorar a vida dos desenvolvedores, no tocante do desenvolvimento de interfaces grficas mais sofisticadas. Com isso, a Sun no hesitou e incorporou o LWUIT como uma de suas bibliotecas padro, disponibilizou uma aplicao exemplo e integrou uma de suas ferramentas utilitrias, o Resource Manager, dentro do Java ME Platform SDK 3. Alavancando de vez o nome LWUIT dentro da comunidade Java ME.

Figura 2: Ferramenta evice Database Search D retornando todos os dispositivos da Nokia que suportam MIDP 2.0.
O LWUIT, para quem ainda no conhece, um framework de componentes grficos inspirado no Swing da plataforma Java Standard Edition (Java SE), especificamente modelado e construdo para ambientes

restritos em poder de processamento e memria, como o dos dispositivos mveis. O LWUIT traz para o mundo mvel, algumas das funcionalidades para o desenvolvimento de interfaces grficas j conhecidas no desktop e que so bem caractersticas 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 integrao, para um desenvolvedor acrescentar o suporte ao LWUIT sua aplicao dentro do Java ME Platform SDK 3, basta somente alguns passos: acessar as propriedades do projeto, selecionar Libraries & Resources, clicar no boto Add Library e selecionar a biblioteca LWUIT, que j aparece na lista, junto com as demais bibliotecas disponveis na ferramenta. Alm disso, a aplicao exemplo bem completa, o que serve como uma boa referncia inicial para os desenvolvedores que esto comeando no LWUIT (para saber mais sobre LWUIT, veja a Edio 60 e a seo Links). Ela apresenta diversos exemplos de vrias partes do framework. Encontrando o argalo G Como se os problema de lgica no fossem o bastante, os problemas de desempenho tambm tem sido uma constante nas aplicaes atuais, principalmente nas mveis, devido s exigentes demandas por mais funcionalidades, sem falar das restries de processamento, inerentes aos dispositivos mveis. A fim de tambm facilitar mais esta tarefa dos desenvolvedores, j que por muito tempo esta tambm foi executada com o auxilio de APIs como System.out.println() e System.currentTimeMillis(), foram criados os monitores de processamento (profiler). So ferramentas que monitoram toda a execuo da aplicao, registrando os tempos de execuo e a quantidade de vezes que cada mtodo foi executado. Informaes muito valiosas quando se est procura do gargalo de um determinado processo. No Java ME Platform SDK 3, esta ferramenta de monitorao a mesma encontrada em outras distribuies do NetBeans, tambm usada para testes em aplicaes Java SE e Java EE. Para ativar o profiler para determinada aplicao no Java ME Platform SDK 3, basta habilitar a opo Enable profiler nas propriedades do emulador utilizado. Durante a execuo, o profiler registra num arquivo (e.g. data.prof), todas as informaes sobre o cdigo que est sendo executado. Ao final da execuo, preciso informar ao SDK, atravs da opo Profile>Import Java ME SDK Snapshot, o caminho do arquivo gerado pelo profiler, a fim de que a informao coletada seja apresentada. Nesta nova tela que mostrada (veja Figura 3), o desenvolvedor pode ver o tempo gasto para executar cada mtodo e a quantidade de vezes em que ele foi executado, alm de ainda poder agrupar todas estas informaes por classe ou por pacote. Dando uma viso mais macro dos tempos de execuo de cada componente da aplicao.

Figura 3: Tela do profiler que mostra os tempos de execuo dos mtodos da aplicao.

E mais JSRs A cada dia novas APIs so finalmente especificadas, tornando-se aptas a serem implementadas por algum fabricante, que suporte a plataforma Java ME em seus dispositivos mveis. O que normalmente acontece a implementao dessas APIs chegarem primeiro s ferramentas de desenvolvimento, tendo em vista uma maior facilidade de implement-las em plataformas Windows ou Linux, por exemplo, para depois chegarem aos dispositivos. No Java ME Platform SDK 3, trs novas APIs esto finalmente disponveis para os desenvolvedores: Mobile Sensor API (JSR 256) (veja o artigo da Edio 55), XML API for Java ME (JSR 280) e a Java Binding for the OpenGL ES API (JSR 239). A primeira responsvel por fornecer acesso a alguns sensores (e.g. acelermetro) disponveis em certos dispositivos mveis (veja o quadro Trabalhando com Sensores no Emulador). A JSR 280, por sua vez, define uma API exclusiva para manipular arquivos XML com parsers SAX2 e DOM. A idia acabar com a fragmentao que existe atualmente, onde cada API que precisa manipular XML define o seu prprio mecanismo para desempenhar este trabalho (e.g. Web Services Specification (JSR 172)). E finalmente, a JSR 239 vem para prover o suporte ao desenvolvimento de grficos 3D atravs 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 tambm disponibiliza aplicaes exemplo para cada nova API suportada, inclusive as que j eram suportadas. Um timo pontap inicial para quem est comeando a trabalhar com as APIs mais recentes. Quanto mais Emuladores, Melhor inquestionvel a qualidade dos emuladores disponibilizados pelo Java ME Platform SDK 3, assim como os de suas verses anteriores. Todos eles seguem risca cada ponto das especificaes das APIs, dando maior segurana ao desenvolvedor sobre a corretude do seu cdigo. Se nenhuma exceo for lanada, alertando sobre alguma operao indevida, porque ele est no caminho certo. No entanto, por mais que as especificaes sirvam para definir uma base comum, alm de diminuir as chances de incompatibilidade entre as diferentes implementaes, no mundo real as coisas no so to perfeitas assim. comum encontrar problemas de incompatibilidade entre uma implementao feita para o Windows, que no funciona no Linux, e vice-versa. No mundo mvel ento, ainda pior. Aplicaes feitas para rodar num dispositivo da Nokia podem precisar de ajustes para rodar perfeitamente num Motorola ou Sony Ericsson, por exemplo. Por mais que sigam a risca o que est na especificao, sempre possvel ter algo na implementao (inclusive bugs) que gera um comportamento diferente. A complexidade e as restries dessas plataformas mveis potencializam ainda mais este problema. Tendo em vista essas possveis diferenas, os testes em outras plataformas se tornam muito importantes para uma aplicao Java ME, que deseja rodar em dispositivos de mais de um fabricante. Nesta verso do Java ME Platform SDK 3 possvel importar outros emuladores desenvolvidos, por exemplo, pela Nokia, Samsung, Motorola, Sony Ericsson, dentre outros, para dentro da ferramenta e us-los para testar suas aplicaes. Uma funcionalidade j encontrada 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 Platform Emulador e informar os caminhos solicitados pelo restante do wizard. Aps ter configurado a nova plataforma, basta acessar as propriedades do projeto e selecionar a nova plataforma e o emulador a ser utilizado. Testes em emuladores realmente uma mo na roda, pois facilitam muito o desenvolvimento, tendo em vista a rapidez que por em execuo a aplicao no emulador. Entretanto, eles nunca vo substituir o teste no dispositivo real, pois, se de um emulador para outro j existem diferenas, imagine do emulador para o hardware. Suporte Oficial Com exceo do sistema operacional Symbian, outros sistemas como Palm OS e Windows Mobile, tambm bem populares no mercado, nunca foram referncia pelo seu suporte plataforma Java ME, pelo contrrio. Esta questo, acredito, deve-se ao fato que ambos possuem, desde muito cedo, suas prprias plataformas nativas (baseadas em C) de desenvolvimento de aplicaes. Ambas muito bem difundidas e poderosas, e que acabou gerando uma comunidade de desenvolvedores duradoura.

Com relao ao Palm OS, a Sun at que se esforou na poca do lanamento da primeira verso do Wireless Toolkit (ainda MIDP 1.0), disponibilizando uma mquina virtual que podia ser instalada nos dispositivos da empresa Palm. No entanto, a investida no vingou, talvez pelo desinteresse da prpria Palm, e o projeto ficou pelo caminho. A IBM tambm tentou, lanando uma mquina virtual chamada Websphere Everyplace Micro Environment (WME), com suporte ao MIDP 2.0. A Palm dessa vez at esboou um incentivo, publicando a VM da IBM no seu site como um produto homologado. Porm, em 2008, o incentivo acabou e a Palm retirou o apoio. Hoje este projeto est parado no tempo, assim como o prprio Palm OS, que vem sumindo do mercado aos poucos. A histria da plataforma Java ME no sistema operacional da Microsoft no muito diferente da vivida pela Palm. Esta tambm marcada pela dificuldade de encontrar uma mquina virtual robusta e slida, 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 relao a Java ME. Nas verses para smartphones do Windows Mobile, por exemplo, at existe uma mquina virtual que j acompanha o dispositivo. Por mais que seja restrito em recursos, ainda serve para rodar aplicaes mais simples. A IBM tambm investiu na Java ME para o Windows Mobile, disponibilizando uma verso paga da sua mquina virtual, WME, voltada para verses anteriores deste sistema. Mas agora, as coisas parecem que vo melhorar para os desenvolvedores Java ME que querem rodar suas aplicaes no Windows Mobile. A Sun est disponibilizando, no Java ME Platform SDK 3, uma mquina virtual para o Windows Mobile 6, que pode tanto ser instalado em um emulador do prprio sistema operacional no PC, quanto num dispositivo real. Tudo o que o desenvolvedor precisa fazer instalar a maquina virtual (veja Figura 4), atravs do arquivo sun-java-cldc-emu.cab, que se encontra disponvel no SDK na pasta JavaMESdkHome\ondevice\winmobile-arm, no emulador ou no dispositivo. Alm de executar as aplicaes, o desenvolvedor ainda tem a possibilidade de depurar suas aplicaes tanto no emulador quanto no dispositivo real. Com mais esta plataforma dando suporte Java ME, agora com a assinatura da Sun, a plataforma Java d mais um passo muito importante na consolidao do seu nome nas principais plataformas mveis do mercado. Concluso A Sun, com certeza, acertou com o Java ME Platform SDK, pois a falta do ambiente de codificao do Wireless Toolkit atrapalhava, de certa forma, os novos desenvolvedores. O problema era que estes no conseguiam, rapidamente, codificar um Hello, World!. Haja vista que precisavam usar um editor de cdigo 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 so caractersticas muito importantes, que todo iniciante, em qualquer plataforma, gosta de ter. Entretanto, o Java ME Platform SDK indicado somente para aplicaes de teste ou pequenas, pois algumas funcionalidades importantes no desenvolvimento de aplicaes mais complexas, como depurao e controle de verso, no esto disponveis. Nesses casos, o recomendado mesmo o NetBeans Mobility Pack, que oferece o ambiente completo do NetBeans mais uma srie de ferramentas especficas para Java ME QUADRO INFORMATIVO Compilao Just-in-time (JIT) A caracterstica da plataforma Java que permite que suas aplicaes sejam possveis de serem executadas em diferentes plataformas (e.g. Windows e Linux), sem necessidade de recompilao, o fato do seu cdigo-fonte ser compilado para uma representao intermediria, conhecida como bytecode. Mas sua execuo depende de outra aplicao, esta sim dependente de plataforma: a mquina virtual, que interpreta o bytecode. Os ganhos em portabilidade com este cdigo intermedirio, por outro lado, gera problemas de

desempenho, pois a interpretao bem menos eficiente que a execuo de cdigo nativo. Entretanto, o problema pode ser resolvido com ajuda da tcnica de compilao Just-in-time (JIT), que consiste na compilao do bytecode para cdigo nativo durante a execuo da aplicao. No momento em que um mtodo vai ser executado, este convertido numa representao de cdigo de mquina. Por isso o termo Just-in-time que, em portugus, significa no momento exato. Este cdigo compilado fica salvo na memria, pronto para execues futuras. Alm da plataforma Java, a .NET tambm utiliza esta tcnica. Neste caso, o cdigo intermedirio convertido pela mquina virtual .NET o Microsoft Intermediate Language (MIL). Para saber mais sobre a JIT, veja a seo Links. Trabalhando com Sensores no Emulador Existem algumas APIs Java ME que interagem com alguns tipos de hardware ou servio, que vem integrado a algumas linhas de dispositivos mveis. Por exemplo, a Mobile Sensor API (JSR 256), que interage com sensores (e.g. acelermetro); a Location API (JSR 179), que captura os dados de um GPS; e a Payment API (JSR 229), que fornece servio de pagamentos em geral. Imaginar como se testa uma aplicao desenvolvida com estas APIs, no dispositivo real, no difcil. Pois neste caso, o hardware ou servio est presente no dispositivo e a API vai acess-lo para poder retornar suas informaes. Mas o que acontece quando no se tem o dispositivo real em mos, para testar a aplicao? A resposta simples: para cada API que interage com um hardware ou servio, os emuladores do Java ME Platform SDK executam tais papis, simulando-os. No caso da JSR 256, para a qual a emulao de sensores mais uma novidade do Java ME Platform SDK, o desenvolvedor pode alterar as informaes que o acelermetro 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 simulao dos emuladores, o desenvolvedor precisa acessar a opo View>External Events Generator, disponvel no prprio emulador. Depois disto, uma nova tela ser apresentada, com uma srie abas nela. Cada aba, por sua vez, representa um tipo de hardware ou servio que pode ser simulado. No caso do acelermetro, a aba Sensors a que fornece os meios para simul-lo. Nesta mesma aba, o Java ME Platform SDK ainda fornece a simulao de um sensor de temperatura. Links http://java.sun.com/javame/downloads/sdk30ea.jsp Pgina 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 Saiba Mais www.devmedia.com.br/articles/viewcomp.asp?comp=10574 Auditrio Virtual DevMedia - Empreendedorismo na era dos Celulares www.devmedia.com.br/cursos/listcurso.asp?curso=17 Curso Online - Introduo ao desenvolvimento para celulares com Java ME www.devmedia.com.br/cursos/listcurso.asp?curso=96 Curso Online - Introduo ao uso de Web Services em Java ME www.devmedia.com.br/cursos/listcurso.asp?curso=95

Curso Online - Criao de Interfaces Grficas em Java ME www.devmedia.com.br/cursos/listcurso.asp?curso=94 Curso Online - Java ME e Banco de Dados www.devmedia.com.br/cursos/listcurso.asp?curso=93 Curso Online - Trabalhando com SMS e MMS em JavaME www.devmedia.com.br/cursos/listcurso.asp?curso=92 Curso Online - Conectividade em Java ME www.devmedia.com.br/cursos/listcurso.asp?curso=59 Curso Online - Desenvolvendo um Software Acadmico para Celular www.devmedia.com.br/articles/viewcomp.asp?comp=8585 Java Magazine 44 - A Plataforma Java ME: Parte 1 www.devmedia.com.br/articles/viewcomp.asp?comp=8569 Java Magazine 45 - Mini-curso: programao Java ME: Parte 2 www.devmedia.com.br/articles/viewcomp.asp?comp=10119 Java Magazine 46 - Programao Java ME: Parte 3 www.devmedia.com.br/articles/viewcomp.asp?comp=8547 Java Magazine 47 - Programao Java ME: Parte 4 www.devmedia.com.br/articles/viewcomp.asp?comp=8523 Java Magazine 48 - Programao Java ME: Parte 5 www.devmedia.com.br/articles/viewcomp.asp?comp=8303 Java Magazine 49 - Mini-curso de java ME: Parte 6 www.devmedia.com.br/articles/viewcomp.asp?comp=8379 Java Magazine 56 - Opinio: Android versus Java ME www.devmedia.com.br/articles/viewcomp.asp?comp=8459 Java Magazine 56 - JSR 257: Contactless Communication API www.devmedia.com.br/resumo/default.asp?idrev=123#1517 Java Magazine 57 - Web Feed Reader ME www.devmedia.com.br/articles/viewcomp.asp?comp=10214 Java Magazine 60 - LWUIT: Swing para Java ME www.devmedia.com.br/articles/viewcomp.asp?comp=11396 Java Magazine 64 - Google Maps em aplicaes mvies www.devmedia.com.br/articles/viewcomp.asp?comp=4895 WebMobile 11 - JavaME usando GPS www.devmedia.com.br/articles/viewcomp.asp?comp=8057 WebMobile 15 - J2ME Polish - Desenvolvendo interfaces grficas para aplicaes JavaME www.devmedia.com.br/articles/viewcomp.asp?comp=8275 webmobile 17 - Desenvolvimento ponta-a-ponta: cliente JavaME com servidor JavaEE www.devmedia.com.br/articles/viewcomp.asp?comp=8274 WebMobile 17 - Criando jogos de ao em 2D com a API de jogos em JavaME www.devmedia.com.br/articles/viewcomp.asp?comp=9353 WebMobile 18 - Desenvolvimento ponta-a-ponta: Cliente JavaME com servidor JavaEE www.devmedia.com.br/articles/viewcomp.asp?comp=10333 WebMobile 20 - Escrevendo Jogos para Celular em JavaME www.devmedia.com.br/articles/viewcomp.asp?comp=11440

WebMobile 22 - Construindo Interfaces Grficas na Prtica www.devmedia.com.br/articles/viewcomp.asp?comp=9509 Vdeo - Introduo do Desenvolvimento de Jogos em Java ME - Parte 1 www.devmedia.com.br/articles/viewcomp.asp?comp=9749 Vdeo - Introduo do Desenvolvimento de Jogos em Java ME - Parte 2 www.devmedia.com.br/articles/viewcomp.asp?comp=9750 Vdeo - Introduo do Desenvolvimento de Jogos em Java ME - Parte 3

Estratgias de Integrao de Aplicaes Java EE

Marco Aurlio de Souza Mendes consultor independente de Arquitetura de Software e Engenharia de Software com mais de 16 anos de experincia em projetos de TI. tambm professor de ps-graduao dos cursos de Estratgias de Arquitetura de Sistemas do IGTI e Engenharia de Software do IEC/PUC-Minas. Ele mantm artigos diversos sobre Arquitetura, Java e Engenharia de Software no seu blog http://blog.marcomendes.com De que se trata o artigo: O artigo apresenta tcnicas e prticas provadas de integrao de aplicaes Java com outras aplicaes, sistemas e bancos de dados. Projetos de integrao apresentam muitas complexidades tcnicas e muitas possibilidades tcnicas em Java tais como JMS, JCA, JDBC, RMI, HTTP e SOAP. O artigo mostra como escolher estas tecnologias e como utiliz-las adequadamente atravs de padres de integrao de aplicaes (EIP). Para que serve: O artigo til para que desenvolvedores possam conhecer os riscos associados integrao de sistemas Java com outros sistemas e aplicar as melhores prticas de mercado e padres de integrao para mitigar e eliminar estes riscos. Projetos com riscos tcnicos reduzidos possuem maior garantia de sucesso, maior qualidade, estabilidade e manutenes mais simples e facilitadas. Em que situao o tema til: Em projetos de TI que requerem integraes de todo tipo, como bancos de dados relacionais, bases de dados em outros formatos, sistemas de filas de mensagens, aplicaes legadas em plataformas baixas e altas ou aplicativos como CRM (Customer Relationship Management) e ERP (Enteprise Resource Planning). Estratgias de Integrao de Aplicaes Java EE: Integrar aplicaes Java com outros sistemas no uma tarefa trivial. Para reduzir riscos e manter projetos sob controle, devemos usar prticas provadas de integrao de sistemas. As melhores prticas de integrao so denominadas padres EAI (EAI Patterns) e foram popularizadas por Gregor Hohpe atravs do seu livro Enterprise Integration Patterns. Estas prticas permitem que um arquiteto ou desenvolvedor escolha as estratgias mais eficientes de integrao de sistemas Java com outros sistemas e produza solues mais perenes e econmicas. Estas prticas de integrao tambm so fundamentais para empresas que estejam buscando iniciativas SOA e BPM, pois permitem gerir adequadamente a criao e evoluo de servios (ativos) em repositrios de servios (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 solues independentes de tecnologia para cada requisito arquitetural coletado; (3) Estudar os exemplos disponibilizados na referncia [1]; (4) Estudar as tecnologias Java mais adequadas para cada requisito (ex: WebServices ou RMI); (5) Implementar os cenrios com as tecnologias Java escolhidas; (6) Testar as solues em ambiente de homologao. Em alguma empresa do Brasil, uma histria comum... Integrar aplicaes no uma tarefa trivial. Protocolos diversos, APIs exticas, tecnologias e ambientes complexos e cronogramas agressivos so alguns aspectos que desafiam diariamente analistas desenvolvedores Java EE.

Conto aqui uma histria que resume estes desafios. Uma equipe necessitava enviar emails de sua aplicao Java. Uma tarefa aparentemente trivial, que muitos desenvolvedores vivem todos os dias. A equipe no possua experincia com a API JavaMail, mas com a ajuda de um recurso externo a equipe se capacitou e desenvolveu o cdigo necessrio para suportar a integrao, que neste caso ocorreria com o servidor Microsoft Exchange. Cdigo implementado, testes internos realizados com sucesso e aprovao gerencial. Aparentemente o problema foi resolvido. A vida real, entretanto, guarda surpresas. Na vspera da semana de implementao, o cdigo foi implantado na empresa do cliente (vamos cham-la de empresa ACME), mas os casos de uso que requeriam a integrao com o Microsoft Exchange no funcionavam. Todos os olhos e atenes (e culpas) foram lanados para o servidor de email da Microsoft. Aps a descoberta que o servidor de email do cliente (v2007) estava em uma diferente verso do ambiente interno da desenvolvedora (v2003), modificaes no ambiente de desenvolvimento foram realizadas para adequar o servidor. Nenhum resultado positivo foi alcanado. O pnico se instalou! Mais investigaes foram realizadas e a equipe descobriu que o servidor de email de produo no residia na mesma rede do servidor de aplicao 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 no foi questionado o bastante para informar este fato. Para encurtar a histria, a equipe descobriu 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 atraso de algumas semanas no cronograma, um cliente relativamente estressado e o desafio foi finalmente vencido. Que lies podemos aprender com esta histria? Enumero algumas abaixo: Certificar que as verses dos ambientes a serem integrados sejam exatamente iguais; Analisar cuidadosamente a topologia, isto , a organizao fsica do ambiente de produo do cliente.

Diagramas UML de implantao so uma ferramenta til neste aspecto; Analisar os protocolos e requisitos no-funcionais que possam interferir na interoperabilidade; Antecipar testes realizados na plataforma real do cliente.

O leitor mais experiente pode questionar as lies aprendidas neste exemplo. Estas lies so bvias. Mas devemos lembrar que senso comum no prtica comum. Dica: Seja um Indiana Jones de aplicaes Java na sua empresa. Faa uma arqueologia de software nas aplicaes Java da sua empresa e colete os erros e lies aprendidas. Os erros do passado so uma excelente fonte de aprendizado para projetos futuros. O objetivo deste artigo mostrar a voc como tornar senso comum em prtica comum, isto , evitar erros comuns de integraes de sistemas em projetos e evitar estresses desnecessrios. Vamos abordar estratgias e tcnicas para organizar o seu trabalho, organizados da seguinte forma nas sees seguintes deste artigo: Estilos, Nveis e Topologias de Integrao. Iremos conhecer aqui fundamentos da integrao de sistemas; Tecnologias para Interoperabilidade Java. Aqui iremos citar as principais tecnologias e padres Java para a integrao de aplicaes; Padres de Integrao (EIP). Iremos conhecer aqui as melhores prticas de mercado para integrar aplicaes; Processo para Integrar Aplicaes. Vamos abordar aqui as principais tarefas necessrias durante um projeto para garantir uma boa interoperabilidade de suas aplicaes Java.

Estilos, Nveis e Topologias de Integrao Se voc se conhece, mas no o inimigo, para cada vitria sofrer uma derrota, Sun Tzu, A Arte da Guerra. Como conhecer o inimigo? Primeiramente devemos compreender que interoperabilidade um mecanismo arquitetural, ou seja, uma preocupao importante de um projeto e que, portanto, requer a ateno tcnica ainda no comeo do projeto. Devemos investigar as interoperabilidades requeridas no nosso projeto atravs do estilo, nvel e topologia associados, pois para cada um haver uma abordagem tcnica diferenciada e tecnologias distintas em Java.

Dica: Colete os requisitos arquiteturais diretamente com representantes do seu cliente em reunies conjuntas com o analista de requisitos. Normalmente analistas de requisitos tm dificuldade de capturar e expressar informaes tcnicas, o que implica em informaes truncadas e novas descobertas indesejadas no final do projeto. A interoperabilidade de aplicaes pode se apresentar em quatro estilos, conforme Gregor Hohpe [1]. 1. 2. 3. O primeiro estilo a transferncia de arquivos, onde duas aplicaes compartilham as informaes atravs de um arquivo texto ou binrio. O protocolo FTP um exemplo popular de tecnologia que suporta este estilo; O segundo estilo, talvez o mais popular, atravs de dados compartilhados em bancos de dados; O prximo estilo atravs de procedimentos remotos (RPC), onde um programa cliente invoca uma funcionalidade em outra mquina. As tecnologias de WebServices so exemplos normalmente associados a RPC; O ltimo estilo atravs de passagem de mensagens. Programas com suporte a filas de mensagens, como a especificao Java JMS, so exemplo deste estilo.

4.

Pare um minuto e responda: Qual o estilo requerido no exemplo citado de interoperabilidade com o Microsoft Exchange? (Resposta no final deste artigo). Alm dos estilos, podemos classificar a interoperabilidade em nveis, listados a seguir:

1. 2. 3. 4.

Nvel de dados. Como integrar fontes de dados relacionais ou em outros formatos e como reduzir a sua redundncia? A integrao em nvel de dados foca na movimentao de dados entre aplicaes com o objetivo de compartilhar o mesmo dado entre aplicaes diferentes; Nvel de Interfaces de Aplicao (API). Como integrar APIs de aplicao em outras tecnologias que no sejam Java? A integrao via APIs passa pela chamada de funes atravs de protocolos sncronos (RPC) ou assncronos (mensagens); Nvel de Processos de Negcio. Domnio do mundo BPM/SOA, a integrao em nvel de processos de negcio foca no desenvolvimento de componentes de alto nvel que iro fornecer interfaces de alto nvel que podem ser considerados servios; Nvel de Apresentao. Popularmente conhecidos como mash-ups, integram aplicaes atravs de um conjunto de vrios portlets (janelas visuais independentes) que residem em um determinado portal. A Figura 1 mostra um exemplo de integrao neste nvel.

Figura 1: Mashup do internet google


Nota Devman - Requisitos Funcionais e Requisitos No-Funcionais Requisitos funcionais expressam os desejos dos interessados do projeto na perspectiva da funcionalidade. Exemplos incluem cadastros, relatrios e fluxos de trabalho. Requisitos no-funcionais expressam atributos de qualidade de um sistema tais como desempenho, usabilidade, disponibilidade ou

portabilidade. Requisitos funcionais e no-funcionais importantes para o negcio (prioritrios) e complexos formam o conjunto de requisitos arquiteturais que devem ser foco inicial de qualquer projeto de TI. Requisitos funcionais e no-funcionais coletados podem responder a perguntas sobre escolhas de estratgias e tecnologias sobre interoperabilidade. Por exemplo, restries sobre desempenho podem eventualmente influenciar na escolha de uma integrao com soquetes ao invs de XML e Web Services. Um novo teste: Qual o nvel associado ao exemplo citado de interoperabilidade com o Microsoft Exchange? (Resposta no final deste artigo). Finalmente, devemos considerar tambm a questo da topologia da aplicao. Dois modelos clssicos existem: 1. 2. Comunicao Ponto a Ponto. A integrao ponto a ponto tambm chamada de integrao oportunista e ocorre diretamente entre dois sistemas que queiram conversar. Quando conectamos uma TV diretamente a um DVD, usamos intuitivamente esta topologia de integrao; Comunicao Hub and Spoke. Topologia popularizada pelos ESB (um tipo particular de Hub and Spoke), esta topologia usa um mediador central para comunicar cada aplicao (Spoke) que deseje conversar. Nenhuma aplicao conversa diretamente com outra aplicao. Isto pode parecer confuso e complexo, mas considere (na sua sala de TV dos sonhos) como voc poderia integrar adequadamente uma televiso digital, um computador, um sistema de som 7.1, um DVD, um vdeo-cassete (para as fitas de formatura da sua famlia), um projetor e um vdeo-game de ltima gerao. claro neste exemplo que usar um aparelho central para gerir todas as conexes mais vantajoso. O Home-Theater um hub na sua sala de TV dos sonhos e pode ligar todos os fios dos aparelhos (Figura 2).

Figura 2: A topologia de comunicao ponto a ponto liga duas aplicaes diretamente. A topologia Hub and Spoke usa um barramento central (Hub) para ligar mltiplos clientes.
Mais um desafio: Qual a topologia associada ao exemplo citado de interoperabilidade com o Microsoft Exchange? (Resposta no final deste artigo). Dica: Colete os requisitos arquiteturais de interoperabilidade na sua aplicao. Para cada requisito arquitetural, defina o estilo, nvel e topologia associada. Tecnologias de Interoperabilidade Java Um chefe deve empregar tticas variadas de acordo com os tipos de terreno, Sun Tzu. A plataforma Java foi desenhada e evoluda nos ltimos anos com um grande suporte para

interoperabilidade. Considere como exemplo simples a especificao JDBC. Projetada de forma elegante para suportar a portabilidade de sistemas operacionais e bancos de dados, ela um exemplo que suporta a integrao do estilo (ver Tabela 1) banco de dados compartilhados, em nvel (ver Tabela 2) de dados. Diversas outras tecnologias foram projetadas para suportar outros estilos e nveis. Apresentamos alguns exemplos nas Tabelas 1, 2 e 3, sem nos ater aos detalhes da API, que podem ser encontrados em artigos anteriores da revista Java Magazine. As Tabelas 1, 2 e 3 mostram que fundamental escolher adequadamente a ttica (tecnologia) conforme o tipo de terreno (estilo, nvel ou topologia).

Tabela 1: Tecnologias Java para suportar estilos de interoperabilidade

Tabela 2: Tecnologias Java para suportar nveis de interoperabilidade

Tabela 3: Tecnologias Java para suportar topologias de interoperabilidade


Dica: No use as tecnologias Java no primeiro combate a um problema de interoperabilidade. A tecnologia secundria e deve ser considerada apenas aps a correta coleta e desenvolvimento dos requisitos arquiteturais e definio dos estilos, nveis e topologia. Padres de Integrao de Aplicaes (EIP) Um soberano iluminado estuda deliberadamente a situao e um bom general lida cuidadosamente com ela. Se no vantajoso, nunca envie suas tropas; se no lhe rende ganhos, nunca utilize seus homens; se no uma situao perigosa, nunca lute uma batalha precipitada., Sun Tzu. Conhecemos o inimigo. Conhecemos as ferramentas. Entretanto, a grande chave na interoperabilidade de aplicaes saber como aplicar as tecnologias Java a nosso favor. Neste aspecto, introduzimos o conceito de um padro de integrao de aplicaes. Um padro EIP uma soluo provada aplicvel ao contexto de integrao de aplicaes corporativas. O livro Enterprise Integration Patterns [1] apresenta 65 padres de integrao de sistemas. Cada padro resolve um problema particular no contexto de integrao de aplicaes corporativas e pode ser usado junto com outros padres EIP para solucionar um problema do mundo real.

Consideremos, para ilustrar o conceito, um problema similar ao citado no comeo deste artigo. Poderamos formalizar os requisitos arquiteturais da seguinte forma: R1. A aplicao ACME deve interoperar com o servidor Microsoft Exchange 2007 atravs de protocolos SMTP para envio de emails. R2. O transporte para interoperabilidade com o servidor de emails deve garantir confidencialidade e integridade das informaes enviadas atravs do uso do protocolo SMTP sobre SSL. Ao lermos o livro EAI Patterns, capturamos alguns padres candidatos para o problema acima. Estes padres so documentados na Tabela 4.

Tabela 4: Padres EAI usados para resolver a interoperabilidade com o Microsoft Exchange
O primeiro padro da Tabela 4 nos diz que a soluo provavelmente ser resolvida com um mecanismo assncrono. Dadas as restries de protocolos no requisito R1, vemos que a especificao Java nos sugere a especificao JavaMail. O segundo e terceiro padres nos diz que teremos um canal para o envio e recebimento de informaes e este canal deve se conectar a um sistema de email como o Microsoft Exchange. Ao examinarmos a classe Transport, da API do JavaMail, veremos que ela possui esta funo. Naturalmente, um Message Endpoint requer uma implementao da especificao JavaMail. Assumamos neste exemplo que usamos o JBoss AS para esta soluo.

O quarto padro nos diz que devemos enviar um documento textual. Ao observamos novamente a classe Transport, notamos que ela possui um mtodo send() que espera como argumento um objeto do tipo Message, que modela um Document Message. O quinto padro enderea os requisitos de segurana. Um enriquecedor de contedo permite adicionar mensagem original informaes adicionais. No nosso caso, estas informaes adicionais sero de segurana, que nos permite que a mensagem seja entregue em servidores que operem sobre protocolo SSL. Ao examinarmos a hierarquia da classe Transport, vemos a classe SMTPSSLTransport. Esta classe fornece a funcionalidade de envio de emails sobre canal seguro (confidencialidade e integridade). O ltimo padro est fora do escopo Java, mas ele indica que algum deve configurar o servidor Exchange para no aceitar mensagens SMTP, mas somente mensagens SMTP sobre SSL. O padro Consumidor Seletivo representa este mecanismo. Se conectarmos os padres EIP teremos o desenho da nossa soluo apresentado na Figura 3.

Figura 3: Esquema da soluo de integrao com o MS Exchange Server

Nota Devman - Diagramas de Casos de Uso Diagramas de casos de uso so visualizaes de negcio usadas por analistas de requisitos para o auxlio 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, poderamos representar a interoperabilidade do envio do e-mail com o seguinte diagrama. Note que neste diagrama o Microsoft Exchange suporta a operao de envio de email e por isso chamado de Ator Secundrio.

O trecho de cdigo abaixo mostra estas peas conectadas. Listagem 1. Fragmento de Cdigo 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 email props.put("mail.smtp.auth", "true"); // Requer autenticacao props.put("mail.debug", "true"); props.put("mail.smtp.port", SMTP_PORT); // Porto do servidor de email props.put("mail.smtp.socketFactory.port", SMTP_PORT); props.put("mail.smtp.socketFactory.class", // Enriquecedor da mensagem com SSL "javax.net.ssl.SSLSocketFactory" );

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(Padres EIP organizam e comunicam as solues Java!); Transport.send(message); ... Este fragmento de cdigo pode ser entendido como a realizao do esquemtico da Figura 3. Para um problema simples, naturalmente, podemos at ir intuitivamente para uma tecnologia ou um cdigo, mas isso como comear a correr uma maratona sem preparao fsica adequada. Os padres representam esta preparao fsica. Eles permitem que voc pense nos aspectos da soluo sem se ater aos detalhes da tecnologia. Ao escolheremos uma tecnologia Java determinada, ela ser a conseqncia dos padres, que naturalmente devem suportar os requisitos arquiteturais especificados. Para problemas complexos de integrao do mundo real, entretanto, devemos conhecer e aplicar os padres EIP. Outra excelente fonte de padres o livro POSA [2], que contm mais de uma centena de padres arquiteturais, entre eles diversos padres EIP. Como exemplo de padres EIP usados para modelar aplicaes com integrao complexa, dita aplicaes EAI, poderamos citar os padres descritos na Tabela 5.

Tabela 5: Padres EAI tipicamente usados em aplicaes BPM/SOA/ESB. .


Um Processo para Interoperar Aplicativos Se um general sabe o lugar e a hora de uma batalha, ele pode conduzir as suas tropas para at mil milhas, mesmo para uma batalha decisiva. Se ele no sabe nem o lugar nem a hora de uma batalha, ento o seu lado esquerdo no pode ajudar a sua direita e a ala direita no pode salvar a esquerda; a tropa da frente no pode auxiliar a tropa da retaguarda, nem a tropa da retaguarda pode ajudar a tropa da frente., Sun Tzu

1.

2.

3. 4.

5. 6.

7.

Colete os requisitos arquiteturais de interoperabilidade. Uma boa fonte para isso so atores secundrios em diagramas de casos de uso. Eles normalmente revelam sistemas e aplicaes que devem ser integrados. Especifique detalhadamente estes requisitos para que no existam dvidas sobre as verses de servidores, topologias e protocolos exatos a serem utilizados; Desenvolva solues independentes de tecnologia para cada requisito arquitetural de interoperabilidade. Para isso, identifique os estilos, nveis e topologias de cada requisito arquitetural de interoperabilidade. Expresse ento a sua soluo atravs dos padres EIP encontrados em [1] e [2]; Estude os exemplos (mais complexos e alm do escopo deste artigo) disponveis em [1]; Para cada soluo independente de tecnologia, escolha as tecnologias Java mais adequadas para resolver o seu problema. Use as Tabelas 1, 2 e 3 como ponto de partida e ento estude as especificaes de cada tecnologia apresentada e produtos Java que suportem estas especificaes; Prove a sua soluo. Talvez a dica mais valiosa, a sua soluo deve ser provada com um cdigo real e que possa capturar um cenrio de utilizao do seu sistema; Teste a sua soluo em ambiente idntico ao de produo. Envolva o usurio e faa testes reais e significativos, pois este o passo mais complexo. Aplicaes no testadas adiam riscos e podem levar a problemas graves no fim do projeto. Em cenrios mais complexos onde voc no tem acesso ao aplicativo sendo interoperado, considere o uso de ferramentas como o jMOCK ou EasyMock. Recomendo, neste particular, o excelente artigo Mocks Arent Stubs, de Martin Fowler, e o artigo Testando com Mocks de forma fcil, Edio 62; Garanta que voc realizou os passos 1-5 no comeo do projeto. Requisitos de interoperabilidade so complexos e devem ser endereados no INCIO do projeto. Se voc usa um processo derivado do UP (Unified Process), os itens 1-5 para todos os requisitos arquiteturais devem estar finalizados at o 3/10 temporal do seu projeto. Se voc usa processos geis, enderece estes requisitos nos primeiros sprints/iteraes.

Concluses Este artigo apresentou, de forma introdutria, princpios que devem nortear aplicaes que requerem integraes de sistemas. Coloco abaixo um guia de estudo para os mais interessados no assunto. 1. 2. 3. Certifique-se de conhecer os fundamentos de integrao de sistemas. Estilos, topologias e especificaes so fundamentais e livros como [1] e [2] so fontes fundamentais; Estude antecipadamente as ferramentas e APIs Java para suportar os estilos e topologias acima; Nunca acredite em tecnologias que no foram provadas no seu projeto. Negocie tempo do seu gerente de projeto para provar conceitos e realizar testes de integrao. Se voc no realizar esta negociao no comeo do projeto, espere estresses, noites mal dormidas e problemas na entrega do seu cdigo; Lembre-se que o mundo no centrado em Java. Voc precisar conhecer peas e protocolos alm da linguagem Java para se tornar um bom arquiteto de integraes; Teste o seu cdigo de integrao. J observei diversos problemas em projetos devido a processos de testes de integrao falhos e que aconteceram literalmente na entrega do projeto.

4. 5.

O leitor curioso deve ter notado o uso de cones diferenciados para representar padres EIP. Estes cones esto disponveis gratuitamente em formato Visio no prprio 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 soluo: o estilo Passagem de Mensagens, integrao em Nvel de Aplicao e topologia Ponto a Ponto. Boas integraes! Links martinfowler.com/articles/mocksArentStubs.html Descreve o conceito de Mocks e que ele pode ser usado para simular aplicaes externas no contexto de projetos de integrao de aplicaes. eaipatterns.com/ Site central dos padres EIP e que resume muito material interessante sobre integrao de aplicaes. 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. Livros [1] Enterprise Integration Patterns, Gregor Hohpe, Addison Wesley, 2003 Referncia primria sobre a integrao de aplicaes corporativas, escrito por Gregor Hohpe, arquiteto de solues do Google. [2] Pattern Oriented Software Architecture - vol 05, Buschmann e al., Wiley and sons, 2007 Continuao do clssico livro POSA - vol 01, de 1996. O primeiro livro sobre padres arquiteturais de IT e referncia obrigatria para sistemas que requeiram integraes complexas. [3] A Arte da Guerra - Sun Tzu, Sculo IV A.C. Clssico livro sobre estratgias e tticas de guerra. Ganhou popularidade recentemente no mundo dos negcios ao ser adaptado por vrios autores para situaes militares vividas em projetos de TI por gerentes, analistas e desenvolvedores. Saiba Mais www.devmedia.com.br/articles/viewcomp.asp?comp=8984 Java Magazine 32 - Integrao com JBI www.devmedia.com.br/articles/viewcomp.asp?comp=8375 Java Magazine 50 - Integrao Simples com XML-RPC www.devmedia.com.br/articles/viewcomp.asp?comp=8380 Java Magazine 56 - Web Service REST www.devmedia.com.br/articles/viewcomp.asp?comp=9422 Java Magazine 57 - Oracle BPEL: orquestra afinada de sistemas www.devmedia.com.br/articles/viewcomp.asp?comp=10203 Java Magazine 59 - EAI na prtica www.devmedia.com.br/articles/viewcomp.asp?comp=10202 Java Magazine 59 - JBoss ESB www.devmedia.com.br/articles/viewcomp.asp?comp=10816 Java Magazine 62 - SOA na prtica - Parte 1 www.devmedia.com.br/articles/viewcomp.asp?comp=11057 Java Magazine 63 - SOA na prtica - Parte 2

Aplicaes Concorrentes em Java

RONALDO BLANC ROCHA Consultor Java EE pela Summa Technologies do Brasil, atuando h 9 anos com Java/Java EE. De que se trata o artigo: Desenvolvimento de software com processamento concorrente usando a API java.util.concurrent. E a comparao entre o esforo utilizado para desenvolver um software concorrente utilizando as primitivas de concorrncia e utilizando a API. Para que serve: Aumentar a qualidade, o desempenho e a escalabilidade de software com processamento concorrente. As classes da API so bem testadas e confiveis, e tornam o cdigo mais compreensivo, facilitando atividades de manuteno. Em que situao o tema til: Com a evoluo dos computadores de mltiplos ncleos, e a crescente demanda por processamento, desenvolver softwares concorrentes com eficincia, facilidade, escalabilidade e boa manutenibilidade so alguns dos objetivos mais comuns para empresas de desenvolvimento de software. Aplicaes concorrentes em Java: O Java, assim como outras linguagens, escolheu o modelo de threads para tratar tarefas que podem ser executadas simultaneamente. Esse modelo tem suas vantagens e desvantagens (assim como qualquer modelo). O Java sempre trouxe a concorrncia como um recurso da linguagem, no algo externo. Mesmo assim, desenvolver aplicaes concorrentes sempre foi uma tarefa muito complexa. Com a introduo da java.util.concurrent, a complexidade para desenvolver tais aplicaes diminuiu muito. Utilizando essa ferramenta, mesmo programadores menos experientes podem escrever aplicaes concorrentes com qualidade e segurana, obtendo timos resultados. A evoluo dos processadores com um nico ncleo baseada em clocks com maior freqncia atingiu o limite do aquecimento suportado e um custo/beneficio invivel. Esses processadores enfrentavam ainda outros problemas, como alto consumo de energia e gargalo no acesso memria. Portanto, novas alternativas para a melhoria de desempenho e consumo ganharam destaque, entre elas o paralelismo de threads e cores. Os processadores de mltiplos ncleos (MC) e a tecnologia SMT (Simultaneous Multithreading) permitem que tarefas sejam executadas em paralelo melhorando o aproveitamento dos recursos. Para tirar-se maior proveito desses avanos, necessrio mudar o modo de pensar e escrever aplicaes, substituindo-se o paradigma seqencial pelo concorrente. Dentre os desafios que esse paradigma apresenta, alguns merecem destaque: identificar o que pode ser executado em paralelo (vamos chamar de thread cada parte do cdigo com essa caracterstica) e a sincronizao dos threads. O que so Threads? Os sistemas operacionais, em sua maioria, suportam processos, isto , programas independentes que rodam com algum grau de isolamento. Thread um recurso que permite mltiplas atividades ocorrendo ao mesmo tempo em um mesmo processo. O Java foi uma das primeiras linguagens, com boa aceitao no mercado, que trouxe as threads como parte da linguagem, no as tratando apenas como um recurso controlado pelo sistema operacional. As threads assim como os processos, so independentes e concorrentes, tendo variveis locais e pilha (stack) prprias, mas compartilham a memria e estado do processo em que participam. Dessa forma, elas tm acesso aos mesmos objetos alocados no heap. Apesar de facilitar a troca de dados, deve-se tomar cuidado para garantir que isto no resulte em erros de concorrncia (data races). Todos os programas escritos em Java rodam threads, pelo menos uma (main). A JVM cria outras threads que geralmente no so percebidas, como: Garbage Collection (GC), threads da AWT/Swing; em

servidores de aplicao conectores de HTTP, EJB etc. A API do Java para threads muito simples. Entretanto, escrever programas que as utilizem com eficincia um trabalho complexo. Ento, porque utiliz-las se so to complicadas? Algumas das principais razes so: Aproveitar as vantagens dos computadores multiprocessados; Executar tarefas assncronas ou em background; Tornar a interface com o usurio mais fluida; Simplificar a modelagem. Antes da API java.util.concurrent, trabalhar com threads em Java exigia um grande esforo, pois os recursos disponveis so muito simples e de baixo nvel. No exemplo da (Listagens 1 a 4), apresenta-se a implementao de um problema clssico de produtor e consumidor, utilizando os recursos primitivos de concorrncia. Listagem 1. Produtor/Consumidor com Semforo package br.com.jm.concurrent; public class Queue { private static final Integer MAX_ITENS = 5000; private Integer itens = new Integer(0); private boolean firstThousand = false; private synchronized boolean isFull() { if (this.itens >= MAX_ITENS) { if (!this.firstThousand) this.firstThousand = true; return true; } else { return false; }

} private synchronized boolean isEmpty() { if (this.itens <= 0) { return true; } else { return false;

} } public synchronized void add() { while (isFull()) { try { synchronized (this) { wait(); System.out.println(Thread.currentThread() .getName() + " waiting"); } } catch (InterruptedException e) { e.printStackTrace(); } } itens++; System.out.println(Thread.currentThread() .getName() + " produziu um valor. Total [" + this.itens + "] "); synchronized (this) { notifyAll(); } }

public synchronized void remove() { while (isEmpty()) { try { synchronized (this) { wait(); System.out.println(Thread.currentThread(). getName() + " waiting"); } }

catch (InterruptedException e) { e.printStackTrace(); } }

itens--; System.out.println(Thread.currentThread(). getName() + " consumiu um valor. Total [" + this.itens + "]"); synchronized (this) { notifyAll(); } }

public synchronized boolean isRemovable() { return this.firstThousand; } } Listagem 2. Produtor/Consumidor com Semforo package br.com.jm.concurrent;

public class Producer extends Thread {

private Queue queue;

public Producer(Queue queue, String string) { this.queue = queue; this.setName(string); }

public void run() { while (true) {

try { sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } queue.add(); } } } Listagem 3. Produtor/Consumidor com Semforo package br.com.jm.concurrent;

public class Consumer extends Thread { private Queue queue;

public Consumer(Queue queue, String string) { this.queue = queue; this.setName(string); }

public void run() { while (true) { try { sleep(random()); } catch (InterruptedException e) { e.printStackTrace(); } if (queue.isRemovable()) queue.remove(); } }

private long random() { Double random = Math.random() * 100; return (long) (random.intValue() % 10); } } Listagem 4. Produtor/Consumidor com Semforo package br.com.jm.concurrent; public class ProducerConsumer { private static final int MAX_PRODUCER = 2; private static final int MAX_CONSUMER = 6;

public static void main(String args[]) { Queue queue = new Queue(); // Producers Producer producer = null; for (int i = 0; i < MAX_PRODUCER; i++) { producer = new Producer(queue, "Producer " + i); producer.start(); } Consumer consumer = null; // Consumers for (int i = 0; i < MAX_CONSUMER; i++) { consumer = new Consumer(queue, "Consumer " + i); consumer.start(); } } } A classe principal ProducerConsumer instancia alguns Producers, que geram dados, e Consumers, que os utilizam. Ambos se comunicam por intermdio da fila customizada (representada na classe Queue), implementada utilizando recursos primitivos do Java como synchronized, alm dos algoritmos especficos a este tipo de fila. Por exemplo, o mtodo add() no pode inserir elementos se a fila j estiver cheia, neste caso o recurso de bloqueio seguido de retry (ver o loop while(isFull()) com um wait()) garante a integridade; assim, se a fila estiver cheia, a thread-produtor que est tentando inserir ficar em wait() at que alguma thread-consumidor remova um elemento com remove(), que ao final faz um notifyAll(), acordando o produtor para o prximo retry. Todo este cdigo bastante trabalhoso e complexo, alm de

limitado, em escalabilidade e outras qualidades. O conceito Thread-safe Como difcil definir se uma classe thread-safe , alguns pontos devem ficar claros: Para uma classe ser considerada thread-safe, primeiro ela deve funcionar bem em um ambiente no concorrente, ou seja, deve ser implementada de acordo com as especificaes e qualquer operao (leitura ou alterao de valores utilizando membros ou mtodos pblicos) realizada em objetos dessas classes no devem coloc-los em estado invlido. Alm disso, a classe deve funcionar bem em ambientes multi-thread. Nesse cenrio, a estratgia de agendamento e tempo de execuo, ou sincronizaes adicionais necessrias ao cdigo, no devem influenciar o bom funcionamento da classe. Para que as operaes executadas por um objeto thread-safe atendam esses critrios, elas devem estar bem encapsuladas e a integridade dos dados deve ser mantida de forma transparente. Antes do Java 5, o nico mecanismo para garantir que as classes atendiam o conceito thread-safe era a primitiva synchronized. Assim, as variveis compartilhadas entre mltiplas threads precisavam ser sincronizadas para que as operaes de leitura e alterao de valores fossem coordenadas. Mesmo que no exista nenhuma linha de cdigo que indique explicitamente o uso de threads em sua aplicao, o uso de frameworks e alguns recursos podem exigir que as classes que os utilizam sejam thread-safe. Mas desenvolver classes thread-safe exige muito mais ateno e anlise do que classes no thread-safe. Servlets containers, por exemplo, criam muitas threads e uma determinada Servlet pode ter acessos simultneos para atender mltiplas requisies, por isso, uma classe Servlet deve ser thread-safe. A Listagem 5 mostra o exemplo de uma Servlet no thread-safe (a princpio o cdigo parece correto) que salva o endereo das mquinas que acessam o servidor. Entretanto, a Servlet no thread-safe, pois a classe HashSet tambm no . Nessas condies, poderamos perder algum dado ou corromper o estado da coleo. O modo simples de corrigir esse problema, utilizando a nova API, seria usar uma das colees seguras, criando o objeto ipAdressSet da seguinte forma: private Set<String> ipAddressSet = Collections.synchronizedSet(new HashSet<String>()); muito interessante observar que a nova API simplifica o trabalho do desenvolvedor, ao mesmo tempo em que exige um maior conhecimento sobre concorrncia, mesmo para um exemplo to simples quanto esse. Listagem 5. Servlet no thread-safe public class ServletNaoSeguro extends HttpServlet{ private Set<String> ipAddressSet = new HashSet<String>(); protected void doGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException { String ipAddress = httpServletRequest.getRemoteAddr(); if (ipAddressSet != null) ipAddressSet.add(ipAddress); } } Colees Seguras Na plataforma Java (desde a JDK 1.0) existem colees thread-safe como Hashtable e Vector. A API de Collections (introduzida no JDK 1.2) introduz muitas colees sem esta caracterstica (como ArrayList, HashSet etc.), mas podemos transform-las em thread-safe, com o uso das factories:

Collections.synchronizedSet; Collections.synchronizedMap; Collections.synchronizedList. Essas colees geralmente tm baixa performance e alguns problemas, principalmente quando o processamento depende de dados processados anteriormente. Chamadas aos mtodos Iterator.hasNext() e Iterator.next() podem lanar uma ConcurrentModificationException, pois alguma thread pode ter alterado a coleo. Analogamente, testar se um objeto existe na lista antes de inseri-lo, ou recuperar o tamanho da coleo (por exemplo um List.size()), pode provocar data races. Esses cenrios so conhecidos pelo nome "conditionally thread-safe". Alm desses recursos, a java.util.concurrent traz novas colees como: ConcurrentHashMap, CopyOnWriteArrayList e CopyOnWriteArraySet. Os propsitos dessas classes so alta performance e alta escalabilidade para classes thread-safe. O uso dessas classes cumprir seus objetivos em todas as aplicaes que no tenham a necessidade de bloquear toda a coleo para evitar alteraes. A ConcurrentHashMap, por exemplo, feita para cenrios de alta concorrncia e leva to a serio essa idia que muito raramente bloqueia em locks, mesmo por pouco tempo. As colees da nova API retornam weakly consistent iterators ao contrario das colees da java.util que retornam "fast-fail iterators". Desde a introduo da java.util.concurrent, voc deve encarar estes recursos como meros quebra-galhos - talvez para cdigo legado que voc no tenha tempo de revisar mais profundamente com a nova API. As classes CopyOnWriteArrayList e CopyOnWriteArraySet sempre criam uma cpia da lista quando ela alterada (add(), set() ou remove()), assim as threads que esto iterando sobre a lista continuaro trabalhando sobre a mesma lista que comearam. Mesmo com o custo de copiar a lista, na maioria dos casos, o numero de iteraes bem maior que o de modificaes. E o custo de tais cpias menor do que o normal devido otimizao copy-on-write: grosso modo, cada thread s copia de forma incremental os elementos que alterou, no a coleo inteira. Para esses cenrios as novas classes oferecem melhor performance e permitem maior concorrncia que as outras. Os fast-fail iterators lanam uma ConcurrentModificationException (como explicado anteriormente) pois consideram que a lista no pode ser alterada, seja por outra thread ou pelo mesmo, enquanto est sendo percorrida. J para os weakly consistent iterators se um objeto foi removido, ele no ser retornado e se um objeto foi adicionado, ele pode ou no ser retornado. Existe, porm, uma garantia de que o mesmo objeto no ser retornado mais de uma vez em uma mesma iterao. Para colees com ordem estvel, os objetos retornados viro na ordem correta, no importa como a coleo foi alterada. As listas baseadas em arrays (como Vector) ou criadas com uma das factories disponveis na nova API (como Collections.synchronizedList()) retornam fast-fail iterators e para evitar o cenrio conditionally thread-safe a thread que est iterando sobre a lista teria que copiar toda a lista ou bloque-la, sendo qualquer uma dessas solues muito custosa. A classe ConcurrentHashMap permite maior concorrncia que as outras alternativas de mapas threadsafe. O modo utilizado pelas outras implementaes sincronizar todos os mtodos, o que nos leva a dois problemas: 1. 2. Falta de escalabilidade, pois uma nica thread pode acessar a coleo durante o mesmo perodo; A possibilidade de falha na segurana do acesso (conditionally thread-safe) que exige sincronizao externa s classes.

Com a tcnica de sincronizar tudo, independente das operaes que outras threads queiram realizar na coleo, estas precisam esperar pela primeira thread terminar sua execuo. J a ConcurrentHashMap permite vrias operaes de leitura quase concomitantes, operaes de leitura e gravao simultneas (pode-se ler e gravar dados ao mesmo tempo) e mltiplas gravaes concorrentes (vrias threads gravando ao mesmo tempo). A JDK 5 incluiu uma nova estrutura de dados, a Queue, que uma interface bem simples. Simplesmente bloquear a thread tambm permite maior controle sobre o fluxo de dados (se os produtores esto colocando objetos na fila muito mais rpido que os consumidores, bloquear os produtores tornar o consumo mais rpido). As implementaes dessa interface so: LinkedBlockingQueue - Fila FIFO com ou sem limites baseada em ns ligados (como se fosse uma LinkedList); PriorityBlockingQueue - Fila sem limites e com prioridades(no FIFO); ArrayBlockingQueue - Fila FIFO com limites baseada num array; SynchronousQueue - Uma fila degenerada que no comporta nem um nico elemento, mas

facilita a sincronizao entre threads (permite o hand-off, ou transferncia direta, de elementos diretamente do produtor para o consumidor). No exemplo da Listagens 6 a 8 apresenta-se a implementao de um produtor/consumidor utilizando BlockingQueue. Listagem 6. Producer/Consumer utilizando BlockingQueue package br.com.jm.concurrent.bq; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ProducerConsumer { public static void main(String... args) throws Exception { BlockingQueue<String> q = new ArrayBlockingQueue<String>(10); ExecutorService executor = Executors.newCachedThreadPool(); //2 produtores executor.execute(new Producer(q)); executor.execute(new Producer(q)); //6 consumidores executor.execute(new Consumer(q)); executor.execute(new Consumer(q)); executor.execute(new Consumer(q)); executor.execute(new Consumer(q)); executor.execute(new Consumer(q)); executor.execute(new Consumer(q)); } } Listagem 7. Producer/Consumer utilizando BlockingQueue package br.com.jm.concurrent.bq; import java.util.concurrent.BlockingQueue; public class Producer implements Runnable { private final BlockingQueue<String> queue;

public Producer(BlockingQueue<String> q) {

queue = q; }

public void run() { while (true) { try { queue.put("Java Magazine"); } catch (InterruptedException e) { e.printStackTrace(); } } } } Listagem 8. Producer/Consumer utilizando BlockingQueue package br.com.jm.concurrent.bq;

import java.util.concurrent.BlockingQueue;

public class Consumer implements Runnable { private final BlockingQueue<String> queue;

public Consumer(BlockingQueue<String> q) { queue = q; }

public void run() { while (true) { try { System.out.println(queue.take()); } catch (InterruptedException e) { e.printStackTrace();

} } } } Esse exemplo tem praticamente o mesmo nvel de complexidade que o das Listagens 1 a 4 , mas o cdigo em si muito mais simples. Na classe principal ProducerConsumer temos uma ArrayBlockingQueue com tamanho fixo que controla os nmeros mximos e mnimos de elementos na fila (assim como a fila da Listagem 1), temos ainda um Executor (CachedTheadPool) que lida com a concorrncia, utilizando um pool de threads que podem ser reutilizadas, maximizando assim a performance, pois alocar recursos para uma thread no um processo simples. A fila comporta no mximo 10 elementos e o produtor s pode inserir dados se existir espao livre (assim como o primeiro exemplo), a prpria BlockingQueue controla esses limites. O consumidor utilizando o mtodo take() no corre riscos de excees por falta de objetos na fila, pois esse mtodo espera at que exista um elemento na fila para retornar. Todo o processo ocorre sem a utilizao de qualquer primitiva de concorrncia, muito utilizadas em todas as classes das Listagens 1 a 4, deixando claro como a nova API pode facilitar o nosso trabalho como desenvolvedores. FIFO - Define a ordem de entrada e sada dos elementos da fila, nesse caso o primeiro a entrar o primeiro a sair (first in, first out). O framework Executor e Thread Pools As implementaes de thread pools disponveis na API so bem flexveis e existe um framework para controlar a execuo de tasks que implementam a interface Runnable (ou uma nova variante, Callable). No framework Executor existe a interface Executor, que bem simples. O contrato dessa interface define um mtodo para executar implementaes de Runnable. Em qual thread a task ser executada no faz parte do contrato, depender da implementao de Executor sendo utilizada, ou seja, a forma de execuo desacoplada da forma de chamada. Como a interface Executor se preocupa com o modo da chamada, fica muito mais fcil ajustar os parmetros de execuo (alterando valores, como: tamanho do pool, prioridade, timeouts, etc.) com pequenas alteraes no cdigo. Dica: Thread pool uma boa soluo para os problemas de alocao e liberao de recursos enfrentados em aplicaes multi-thread. Como nos thread pools as threads so reutilizadas, o custo de alocao de cada thread dividido entre as tarefas que ela executar. Como a thread j est criada a aplicao pode responder uma requisio (ou seja, iniciar uma tarefa) imediatamente. Existem vrias implementaes de Executors, cada uma com sua estratgia de execuo. Elas so criadas por factories disponveis em mtodos estticos da classe Executors, os principais so:

Executors.newCachedThreadPool(): Um pool sem limite de tamanho, mas que reutiliza threads quando disponveis. Se no existem threads disponveis, cria uma nova e adiciona ao pool. Se uma thread no for utilizada durante um minuto, ser finalizada e removida do pool; Executors.newFixedThreadPoll(int n): Um pool que reutiliza um certo grupo de threads com tamanho definido. Se o numero de threads ultrapassar o nmero definido, as threads esperam at um espao ser liberado; Executors.newSingleThreadExecutor(): Um pool que utiliza uma nica thread para executar as tarefas. Dessa forma, as tarefas so executadas de forma seqencial. A thread de eventos do Swing, por exemplo, seria um SingleTheadExecutor.

A estratgia de execuo define em qual thread uma task ser executada. Define o modo de execuo, ou seja, como os recursos sero utilizados (ex.: memria) e como se comportar em casos de sobrecarga. Dica: Uma pergunta muito comum : Qual tamanho deve ter o Thread pool? A resposta depende, principalmente, do hardware e o tipo de tarefa (task) que ser executada. Existe uma lei que pode ajudar bastante: A lei de Amdahl. Para aplic-la, precisa-se do nmero de processadores (N) existentes na mquina que executar a tarefa.

Precisa-se ainda de aproximaes dos tempos mdio de processamento (TP) e de espera (TE) para a tarefa.O TP o tempo gasto para a concluso da tarefa e o TE o tempo gasto pela thread esperando para iniciar a execuo. Assim, o tamanho do Thread pool deve ser algo em torno de: N * (1 + TE / TP) A interface Future Essa interface pode representar uma task que completou a execuo, que est em execuo, ou que ainda no comeou. Pode-se ainda cancelar uma task que ainda no terminou, descobrir quando a task terminou ou foi cancelada e receber ou esperar pelos valores retornados. Uma implementao dessa interface a FutureTask, que encapsula Runnable ou Callable obedecendo aos contratos das interfaces Future e Runnable, assim, pode ser executada facilmente por um Executor. Alguns mtodos do Executor (como ExecutorService.submit()) retornam Future alm de executar a task. Para recuperar os resultados de uma task, usamos Future.get(), que lana uma ExecutionException caso a execuo da task tenha provocado uma exceo; caso a task ainda no tenha terminado o mtodo ficar esperando o retorno do resultado, se a execuo j acabou retorna o valor imediatamente. As diferenas entre as interfaces Runnable e Callable so: Na interface Callable o mtodo T call(), alm de devolver um resultado do tipo definido T, lana exceo. O mtodo void run() da interface Runnable no retorna valores e no lana exceo. A interface CompletionService Permite que o processamento dos resultados seja desacoplado da execuo da task. Sua interface define o mtodo submit() para indicar as tasks que sero executadas e define o mtodo take() para recuperar as tasks terminadas. Os dois mtodos retornam uma implementao de Future, o que facilita o processo de recuperao de resultados. Usando a interface CompletionService a aplicao pode ser estruturada facilmente com o pattern Produtor/Consumidor (utilizado como exemplo nas Listagens 1 a 4 e 6 a 8), onde o produtor cria e submete as tasks e o consumidor recupera os resultados para process-los. Uma implementao dessa interface a ExecutorCompletionService, que usa um Executor para processar as tasks. No exemplo das Listagens 9 a 11 apresenta-se a implementao de um produtor/consumidor utilizando essa interface. Esse exemplo usa muitos recursos da nova API para resolver praticamente o mesmo problema que os outros exemplos, mas nele as interfaces ExecutorCompletionService, Future e Callable deixam bem claro como o cdigo pode ser bem simples e executar tarefas complexas, como submeter tarefas e recuperar os valores ao final da execuo das mesmas. Para esse exemplo foi escolhido o Executor FixedThreadPool, com tamanho mximo de 10 threads. O produtor submete uma tarefa para a ExecutorCompletionService chamando o mtodo addTask(), enquanto o consumidor espera para obter o resultado com o mtodo getResult(). O getResult() retorna uma instncia da interface Future, onde o mtodo get() retorna o resultado imediatamente, se ele existir, ou espera at o final da execuo tarefa para retornar. Listagem 9. Producer/Consumer utilizando CompletionService package br.com.jm.concurrent.cs; public class ProducerConsumer { private static AtomicInteger count = new AtomicInteger(0);

public static void main(String args[]) throws InterruptedException, ExecutionException { CompletionService completionService = new ExecutorCompletionService( Executors.newFixedThreadPool(10));

Producer producer = new Producer(completionService); Consumer consumer = new Consumer(completionService); while (true) { producer.addTask("Java Magazine [" + safeIncrement() + "]"); System.out.println(consumer.getResult().get()); } } private static int safeIncrement() { if (count.equals(Integer.MAX_VALUE)) { return 0; } else { return count.addAndGet(1); } } } Listagem 10. Producer/Consumer utilizando CompletionService package br.com.jm.concurrent.cs; public class Producer { private CompletionService<String> completionService;

public Producer(CompletionService<String> completionService) { this.completionService = completionService; } public void addTask(final String value) { completionService.submit(new Callable<String>() { public String call() throws Exception { return value; } });

} } Listagem 11. Producer/Consumer utilizando CompletionService package br.com.jm.concurrent.cs;

public class Consumer {

private CompletionService<String> completionService;

public Consumer(CompletionService<String> completionService) { this.completionService = completionService; }

public Future<String> getResult() throws InterruptedException { return completionService.take(); } } Concluses Pode-se perceber que desenvolver com a nova API muito mais simples, apesar de exigir ainda conhecimentos slidos sobre programao concorrente e a necessidade de cdigos especficos que indiquem para a JVM como lidar com essas situaes. A mesma segurana que existe em um cdigo no concorrente em Java (ou seja, que a memria ser alocada e desalocada de modo correto e eficiente, as melhorias que o JIT Compiler proporciona, entre outros) o que a java.util.concurrent proporciona para os cdigos concorrentes. Claro que seria melhor no existir nenhuma preocupao em deixar explcitos os cdigos para o controle da sincronizao e concorrncia e deixar para a JVM resolver, assim como ela resolve os problemas de alocao de memria, mas no to simples (como alocao de memria), controlar a sincronizao e concorrncia de um processo. Esse um dos motivos para o assunto ser um dos mais discutidos hoje em dia. Com essa API podemos substituir a maior parte das primitivas de concorrncia por classes de alto nvel, bem testadas e de bom desempenho. Livros Concurrent Programming in Java, Doug Lea, Addison-Wesley, 1999 Livro do professor Doug Lea, que escreveu a API que serviu de base para a java.util.concurrent. Java Concurrency In Practice, Brian Goetz, Addison-Wesley, 2006 Livro do engenheiro da Sun Brian Goetz, muito conhecido e comentado. Links http://www.jcp.org/jsr/detail/166.jsp JSR 166: Concurrency Utilities http://java.sun.com/docs/books/tutorial/essential/concurrency/index.html Tutorial da Sun sobre concorrncia em Java http://gee.cs.oswego.edu/dl/concurrency-interest/

Site do Doug Lea sobre concorrncia http://www.ibm.com/developerworks/views/java/libraryview.jsp?search_by=practice: Coluna do Brian Goetz no developerWorks Saiba mais www.devmedia.com.br/articles/viewcomp.asp?comp=10017 Vdeo - Novidades do NetBeans 6.5 - Parte 1 www.devmedia.com.br/articles/viewcomp.asp?comp=8471 Java Magazine 53 - Perspectivas para um Mundo Paralelo www.devmedia.com.br/articles/viewcomp.asp?comp=9420 Java Magazine 57 - Programando com Pools www.devmedia.com.br/articles/viewcomp.asp?comp=10197 Java Magazine 59 - Quick Update: A Crise dos Threads

Anda mungkin juga menyukai