Groovy – Parte 1 (Introdução)
Postado por Diego Ferreira da Silva como Groovy em 10 de abril de 2010
Breve Introdução
Groovy é uma linguagem ágil e dinâmica para a plataforma Java com muitas características
inspiradas em linguagens como Python, Ruby e Smalltalk, disponibilizando-as para os
desenvolvedores utlizando uma sintaxe similar à de Java.
Porque estudar Groovy?
Sou programador java e gosto muito desta linguagem, porém estava buscando algo novo, dentre tantas linguagens mais modernas que visam código mais limpo e produtivo encontrei o groovy que se encaixa perfeitamente com o java, podendo até trabalhar com as duas na mesma plataforma, afinal groovy é java. Então resolvi estudá-la para ver como ela se comporta e aumentar minha visão com relação a poder analisar novas soluções no cotidiano desenvolvimento de aplicações JEE.
Neste primeiro post vou passar uma breve introdução a linguagem, nos pots seguintes vamos aprofundando cada vez mais.
Classes
Como Groovy é orientado a objetos igual ao Java, ele possui a declaração de classes, abaixo um exemplo de uma classe em Groovy que possui a declaração de um atributo de instância, um construtor utilizando este atributo e um método getTitulo, note que é tudo muito parecido com Java exceto pela falta de modificadores de acesso, no Groovy os métodos são públicos por padrão.
class Livro {
private String titulo;
Livro(String titulo) {
this.titulo = titulo;
}
String getTitulo(){
return titulo;
}
}
Existem detalhes sobre as porcas e parafusos da declaração de classes em groovy que serão explicados mais a frente.
Utilizando scripts
Scripts são arquivos de texto, normalmente com uma extensão. Groovy, que podem ser executados a partir de comandos vis prompt, ex:
>groovy meuarquivo.groovy
Podemos executar o código fonte diretamente que ele é compilado em tempo de execução.
Crie um arquivo com o nome TesteLivro.groovy, no mesmo diretorio que nossa classe Livro.groovy e dentro dele coloque o seguinte conteudo:
Livro livro = new Livro("teste");
assert livro.getTitulo() == "teste"
assert getTituloAoContrario(livro) == "etset"
String getTituloAoContrario(Livro livro){
String titulo = livro.getTitulo();
return titulo.reverse();
}
Observe como podemos invocar o método getTituloAoContrario antes que ele seja declarado, essa é uma diferença fundamental entre Groovy e outras linguagens de script como Ruby. O script Groovy é todo analisado e compilado antes de ser executado. Outra observação importante é que não precisamos compilar a classe livro para que façamos uso dela no nosso script, basta que ela esteja no classpath que o groovy compila em tempo de execução.
GroovyBeans
GroovyBeans é similiar ao JavaBeans porem com alguns facilitadores:
- Geração de métodos de acesso
- Acesso simplificado a todos os JavaBeans e GroovyBeans
- Simplificação no registro de eventos
Ex:
class Book {
String title
}
def groovyBook = new Book()
groovyBook.setTitle('Groovy conquers the world')
assert groovyBook.getTitle() == 'Groovy conquers the world'
groovyBook.title = 'Groovy'
assert groovyBook.title == 'Groovy'
No exemplo acima temos a classe Book, observe que por nao definirmos o atributo title privado o Groovy criou automaticamente os métodos setTitle de getTitle, o script acima é perfeitamente válido e pode ser executado normalmente, mesmo que tenhamos a declaração de uma classe dentro dele.
<h2>Manipulação de Texto</h2>
Assim como no Java, Groovy trata textos utilizando a classe java.lang.String, porém no Groovy existe alguns ajustes para tornar isto mais fácil, com mais opções para trabalhar com String e mais alguns operadores.
Ex:
def nick = 'Diego' def book = 'Groovy' assert "$nick is $book" == 'Diego is Groovy'
No exemplo acima podemos ver que o Groovy permite a utilização de aspas duplas e simples, e que a concatenação de Strings pode ser feita dentro de uma String, veremos também em detalhes a manipulação de textos em posts posteriores.
Números
Números são objetos em Groovy, não existem tipos primitivos como no Java, todo número criado automaticamente se torna um objeto, e mesmo sendo objetos é permitido a utilização de operadores para cálculos ex:
def x = 1 def y = 2 assert x + y == 3 assert x.plus(y) == 3 assert x instanceof Integer
As variáveis x e y são convertidas automaticamente em tipos java.lang.Integer
Listas Mapas e Intervalos
Trabalhar com Listas em Groovy é extremamente simples, ele permite utilizar os mesmos tipos de acesso para todas as listas e a declaração é bem simples, como arrays em java, ex:
def roman = ['', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII'] //Declarando uma lista assert roman[4] == 'IV' //acessando pelo indice roman[8] = 'VIII' //expandindo a lista assert roman.size() == 9
Com mapas não é diferente, a maneira de declaração e acesso são bastante simples:
def http = [ 100 : 'CONTINUE', 200 : 'OK', 400 : 'BAD REQUEST' ] assert http[200] == 'OK' http[500] = 'INTERNAL SERVER ERROR' assert http.size() == 4
Observe como a meneira de declaração e acesso são parecidas entre mapas e listas, as mudanças são mínimas, desta forma fica fácil se lembrar na hora da utilização.
No Groovy é possível utilizar intervalos na declaração de objetos, observem abaixo como é simples:
def x = 1..10 assert x.contains(5) assert x.contains(15) == false assert x.size() == 10 assert x.from == 1 assert x.to == 10 assert x.reverse() == 10..1
Esse tipo de declaração pode ser útil com outros conceitos do Groovy que vamos ver mais a frente.
Closures
Closures não é um conceito novo, porém é mais utilizado em linguagens funcionais, ele consiste basicamente em passar um bloco de código em tempo de execução e esse bloco de código é executado retornando ou iterando dentro de variáveis locais do contexto atual. Em java isso muitas vezes é feito utilizando classes internas ou interfaces, como exemplo do método java.io.File.list(FilenameFilter) que recebe uma implementação da interface FilenameFilter que possui um único método que permite que os arquivos retornados pela lista sejam filtrados enquanto vão sendo gerados. Mas desta maneira é necessário uma implementação de uma interface o que talvez seria desnecessário se essa regra fosse exclusiva deste momento, poderiamos resolver esse tipo de problema utilizando classes internas, mas mesmo assim é necessário um código extra para que isso seja possível.
Um exemplo simples de uso de closures em Groovy:
[1,2,3].each {entrada -> println entrada }
Estruturas de Controle e Condicionais
O Groovy possui todas as estruturas de controle e condicionais que as linguagens tem hoje, if, else, for, while, try catch finally, essas estruturas de controle possuem suas paticularidas que serão abordadas em posts posteriores, por enquanto só alguns pequenos exemplos delas:
if (false) assert false //if de uma linha
if (null) //null é false
{
assert false
}
else
{
assert true
}
def i = 0
while (i < 10) { //while clássico
i++
}
assert i == 10
def clinks = 0
for (remainingGuests in 0..9) { //for em intervalos
clinks += remainingGuests
}
assert clinks == (10*9)/2
def list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
for (j in list) { //for em uma lista
assert j == list[j]
}
list.each() { item -> //método each com closure
assert item == list[item]
}
switch(3) { //swithc clássico
case 1 : assert false; break
case 3 : assert true; break
default: assert false
}
Conclusão
Então neste post foi apresentado apenas conceitos básicos desta linguagem, em posts posteriores vamos aprofundar nestes conceitos.
Referências
Groovy em Action
Acessando Classes Java de Dentro do Oracle
Postado por Diego Ferreira da Silva como Oracle em 28 de março de 2010
Entao, ta ai um negócio meio esquisito, mas recentemente um colega meu precisou fazer tal proesa para utilizar os serviços de nota fiscal eletrônica de dentro do banco.
Os recursos disponíveis na jdk do banco são meio escassos, pois sua jdk não é totalmente compatível com as jdks da sun, mas existem boa parte das classes e métodos disponíveis da jdk 1.4, e também é possível incluir no classpath do banco arquivos .jar.
Bom o que vamos fazer aqui hoje é criar uma classe java, carregá-la no banco e após isso criar uma function que acessa os recursos desta classe, e tambem irei mostrar como se faz o upload de arquivos .jar no banco.
O ambiente utilizado é:
- Oracle 11g
Primeiro vamos criar uma classe com nosso método, ele deve ser estático:
public class TesteOracle{
public static String metodo(String nome){
return "Olá :"+nome;
}
}
Após isto podemos compilar nossa classe, através do comando javac -target 1.4 -source 1.4 TesteOracle.java, é gerado entao o arquivo TesteOracle.class.
Quando é instalado o Oracle ele adiciona nas variaveis de ambiente do sistema operacional o diretio \bin do mesmo, dentro deste diretorio existe disponível a aplicação loadjava.bat(no caso de windows), para carregar nossa classe no banco, basta acessarmos o prompt e digitarmos: loadjava -user usuario/senha caminhoDoSeuArquivo .class.
Após feito isso, nossa classe ja estaria disponível no banco de dados:
A imagem acima mostra o objeto dentro do banco de dados, esta sendo utilizado a ferramente sqldeveloper 2.1 do oracle.
Agora, vamos criar nossa function:
create or replace FUNCTION ACESANDOJAVA RETURN VARCHAR2 AS LANGUAGE JAVA NAME 'TesteOracle.metodo() return java.lang.String';
Após criada nossa function podemos fazer um select nela e ver o resultado:
A imagem acima mostra o resultado apos o select na function.
E é isso ai, abraço !
Mapeando Arrays de Objetos Oracle no Java
Postado por Diego Ferreira da Silva como Java, Oracle em 11 de janeiro de 2010
Fala pessoal,
Este tutorial explica como fazer binding de objetos/arrays de objetos java para objetos declarados em procedures no oracle.
Existe um ótimo artigo neste link que explica como fazer estes mapeamentos, gostaria apenas de complementar este artigo pois ele aborda como criar os objetos no oracle/java, como recuperar os arrays destes objetos, porem ficou faltando mostrar como passar os arrays como parametro para as procedures.
A única coisa que muda para passar um array como parâmetro é o seguinte
public static void proSelectClass2(TypeClass[] classQry, Connection conn) {
//vc tem que obter um OracleCallableStatement
OracleCallableStatement cs = null;
try {
conn.getTypeMap().put(TypeClass.ORACLE_CLASS_ARRAY_NAME, TypeClass[].class);
conn.getTypeMap().put(TypeUser.ORACLE_USER_ARRAY_NAME, TypeUser[].class);
//aqui obtém o OracleCallableStatement fazendo um cast
cs = (OracleCallableStatement) conn.prepareCall("{call PAC_BEAN.PRO_SELECT_CLASS2(?)}");
//Vc cria um array descriptor
ArrayDescriptor descriptor = ArrayDescriptor.createDescriptor(TypeClass.ORACLE_CLASS_ARRAY_NAME, conn);
//cria um array do oracle utilizando o arraydescriptor criado acima
oracle.sql.ARRAY array = new ARRAY(descriptor, conn, classQry);
//apos isto seta o array criado na posicao em que é passado o array na procedure, obs: este método setARRAY(maíusculo) só está disponível no OracleCallableStatement
cs.setARRAY(1, array);
//aqui esta registrando um array de saida, mas isso é igual ao tutorial passado no link
cs.registerOutParameter(1, OracleTypes.ARRAY, TypeClass.ORACLE_CLASS_ARRAY_NAME);
cs.execute();
É isso ai, qualquer dúvida podem entrar em contato comigo.
abraço.
Hello World RichFaces
Postado por Diego Ferreira da Silva como Java EE em 1 de maio de 2009
E ai pessoal, hoje famos fazer um exemplo passo a passo de uma aplicação Hello World utilizando o RichFaces.
Para quem não conhece o RichFaces ele é uma biblioteca de componentes para aplicações web que utilizam o framework JSF. Os componentes desta biblioteca possuem um incrível suporte AJAX, e ela, pode ser considerada uma extensão do Ajax4jsf com inúmeros componentes com Ajax “embutido” e com um suporte a Skins que podem deixar as interfaces da sua aplicação com um visual padronizado.
O ambiente que utilizamos neste post é o seguinte:
- Eclipse Ganymede
- Tomcat 6.0
- RichFaces 3.3.0
Vamos por a mão na massa, primeiro criamos um projeto web no eclipse e damos o nome a ele de HelloRichFaces.
Efetue o download do arquivo richfaces-ui-3.3.0.GA-bin.zip no seguinte link . Descompacte o arquivo e copie os arquivos richfaces-api-3.3.0.GA.jar, richfaces-impl-3.3.0.GA.jar, richfaces-ui-3.3.0.GA.jar para do diretório WEB-INF/lib da nossa aplicação.
Precisamos também copiar os seguintes jars para o diretório WEB-INF/lib da nossa aplicação:
jsf-api.jar, jsf-impl.jar(Jar’s do framework JSF).
jstl.jar, standard.jar.
commons-beanutils-1.8.0.jar, commons-collections-3.2.1.jar, commons-digester-1.8.jar, commons-logging-1.1.1.jar.
Vamos criar agora dentro da nossa pasta WEB-INF um arquivo com o nome faces-config.xml, neste arquivo ficará nossas configurações referente ao JSF(Managed beans, Regras de navegação, etc…).
Agora criaremos dentro da pasta WebContent uma página jsp com o nome: helloWorldRichFaces.jsp
Vamos criar um pacote dentro da pasta src do nosso projeto com o seguinte nome br.com.diegosilva.helloworld
Pronto, nossa estrutura para o helloWorld já está criada, se você chegou até aqui veja abaixo como deve ficar a estrutura de seu projeto.

Imagem-01
Agora que já temos nossa estrutura do projeto pronta, vamos criar um simples managed bean dentro do pacote br.com.diegosilva.helloworld como o nome de Bean.
Abaixo o código da classe Bean:
package br.com.diegosilva.helloworld;
public class Bean {
private String text;
public Bean() {
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
O managed bean criado acima será utilizado na nossa página JSF, mas para que possamos utilizá-lo precisamos confirar nosso arquivo faces-config.xml inserindo as confirações necessárias para que nosso manage bean seja reconhecido pela nossa página.
Segue abaixo a configuração do nosso faces-config.xml do nosso exemplo:
<?xml version="1.0" encoding="UTF-8"?> <faces-config version="1.2" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd"> <managed-bean> <managed-bean-name>bean</managed-bean-name> <managed-bean-class>br.com.diegosilva.helloworld.Bean</managed-bean-class> <managed-bean-scope>request</managed-bean-scope> <managed-property> <property-name>text</property-name> <value/> </managed-property> </managed-bean> </faces-config>
O arquivo acima está informando ao JSF que estamos criando um managed bean, que seu nome será bean que a classe será a que está no caminho br.com.diegosilva.helloworld.Bean que o escopo utilizado será como atributo de request e que este bean tem uma propriedade que se chama text.
Agora vamos criar nossa página que utilizará nosso managed bean criado.
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@ taglib uri="http://richfaces.org/a4j" prefix="a4j"%>
<%@ taglib uri="http://richfaces.org/rich" prefix="rich"%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<html>
<head>
<title>Hello World RichFaces</title>
</head>
<body>
<f:view>
<h:form>
<rich:panel header="Simples Impressão">
<h:inputText size="50" value="#{bean.text}">
<a4j:support event="onkeyup" reRender="rep" />
</h:inputText>
<h:outputText value="#{bean.text}" id="rep" />
</rich:panel>
</h:form>
</f:view>
</body>
</html>
Na nossa página acima primeiramente fazemos os imports das taglibs utilizadas pelo JSF e RichFaces, dentro ta tag <body> criamos um <f:view>, todos os componentes JSF devem vir dentro de uma tag <f:view>, dentro da nossa tag <f:view> criamos um formulário e dentro desse formulário um painel no qual terá o título de Simples Impressão, dentro desse painel temos um input que irá setar a propriedade text do nosso bean com o valor digitado no input, nesse input adicionamos um evento onkeyup utilizando a api de ajax que o richfaces utiliza, neste evento setamos o atributo reRender=”rep”, no qual rep é o id do nosso outputText declarado logo abaixo, o nosso outputText recebe o valor da propriedade text do nosso bean. O que acontece aqui é que a cada evento de onkeyup nosso bean recebe o valor e o componente de id rep e recebe a atualização desse valor sem refresh na página, totalmente ajax.
Não podemos esquecer de configurar o arquivo web.xml do nosso projeto para que tudo funcione belezinha tem que ser feito algumas configurações neste arquivo.
Segue abaixo nosso arquivo web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app id="WebApp_ID" version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <display-name>HelloRichFaces</display-name> <!-- Rich Faces --> <context-param> <param-name>org.richfaces.SKIN</param-name> <param-value>blueSky</param-value> </context-param> <context-param> <param-name>javax.faces.STATE_SAVING_METHOD</param-name> <param-value>server</param-value> </context-param> <filter> <display-name>RichFaces Filter</display-name> <filter-name>richfaces</filter-name> <filter-class>org.ajax4jsf.Filter</filter-class> </filter> <filter-mapping> <filter-name>richfaces</filter-name> <servlet-name>Faces Servlet</servlet-name> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> <dispatcher>INCLUDE</dispatcher> </filter-mapping> <listener> <listener-class>com.sun.faces.config.ConfigureListener</listener-class> </listener> <!-- Java SErver Faces --> <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>0</load-on-startup> </servlet> <!-- Faces Servlet Mapping --> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>*.faces</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>helloWorldRichFaces.faces</welcome-file> </welcome-file-list> </web-app>

Imagem 2
Download do projeto(Sem os Jars).
Bom pessoal é isso ai espero que tenham gostado deste post, e qualquer dúvida é só entrarem em contato.
Abraço.
Factory
Postado por Diego Ferreira da Silva como Padrões de Projeto em 1 de maio de 2009
O Factory tem como principal objetivo a criação de objetos, como seu próprio nome diz, fábrica.
Com esse padrão é possível que eu fabrique minhas instâncias de forma centralizada, de forma que quando eu precisar alterar a forma que esses objeto são instanciados eu altero em apenas um só lugar.
Vamos ver isso na prática com um exemplo bem simples e de fácil entendimento.
Vamos imaginar o seguinte cenário: temos uma classe Forma e teremos suas subclasses Triangulo e Circulo, nossa classe forma que ficará encarregada de instanciar e retornar um Circulo ou Triangulo de acordo com o que foi solicidado.
Abaixo nossa classe Forma:
abstract public class Forma {
abstract public void calcularArea();
public static Forma getForma(int [] atributos){
//circulo
if(atributos.length == 1){
return new Circulo(atributos[0]);
}
//triangulo
if(atributos.length==2){
return new Triangulo(atributos[0], atributos[1]);
}
//caso a forma solicitada não exista
return null;
}
}
Vemos acima na nossa classe Forma que temos um método abstrato calcularArea() e um método estático getForma(int[] atributos) esse método é que é responsável por verificar que tipo de instância a classe cliente precisa, que no nosso caso é verificado de acordo com a quantidade de parâmetros passadas no array.
Normalmente uma classe Factory retorna apenas objetos de suas subclasses.
Abaixo nossas classes Circulo e Triangulo:
public class Circulo extends Forma {
private int raio;
public Circulo(int raio) {
this.raio = raio;
}
public String toString() {
return "Circulo";
}
@Override
public void calcularArea() {
//PI * raio^2
System.out.println(Math.PI*Math.pow(this.raio, 2));
}
}
public class Triangulo extends Forma {
private int base;
private int altura;
public Triangulo(int b, int a) {
this.base = b;
this.altura = a;
}
public String toString() {
return "Triângulo";
}
@Override
public void calcularArea() {
// (base * altura)/2
System.out.println((this.base*this.altura)/2);
}
}
Acima nas nossas classes Circulo e Triangulo apenas reescrevemos o método toString() da classe Object para retornarmos o tipo de objeto e reimplementamos o o método calcularArea() herdado da nossa classe abstrata Forma, observe que a reimplementação do método é feita de acordo com cada tipo de objeto em suas respectivas classes.
Agora vamos escrever nossa classe cliente que utilizará dos serviços da nossa classe Forma para criar seus objetos.
public class Cliente {
public static void main(String[] args){
Forma forma = Forma.getForma(new int[]{4});//será retornado um Circulo
forma.calcularArea();//será invocado o método calcularArea de Circulo
Forma forma2 = Forma.getForma(new int[]{8,9});//será retornado um Triangulo
forma2.calcularArea();//será invocado o método calcularArea de Triangulo
}
}
Na nossa classe Cliente criamos dois objetos do tipo forma, no primeiro obtemos uma instância de Forma através do método estático getForma(int[] att) passando um array contendo uma posição, desta forma na nossa classe forma será verificado dentro do método e retornado um objeto Forma do tipo Circulo.
Após isso invocamos o método calcularArea() do objeto recem criado, no qual será calculado a área de um Circulo.
Na segunda instanciação do objeto forma na nossa classe Cliente foi feita da mesma forma que a primeira, só que desta vez passamos um array de duas posições para o nosso método getForma(int[] att) que por sua vez retornará um objeto Forma do tipo Triângulo.
Após isso invocamos o método calcularArea() do objeto recem criado, no qual será calculado a área de um Triangulo.
Bom é isso, espero que tenha ficado bem claro, qualquer dúvida estou a disposição.
Obrigado.
Template Method
Postado por Diego Ferreira da Silva como Padrões de Projeto em 4 de abril de 2009
A principal funcionalidade deste padrão de projeto é criar métodos genéricos e passar a responsabilidade de implementação as subclasses ou desenvolver métodos genéricos e alguma parte ou funcionalidade deste método possa ser feito nas subclasses.
Vamor fazer um exemplo prático para melhor entendermos:
Varmos criar uma classe conforme abaixo:
abstract public class Operacao {
abstract int handleEfetuarOperacao(int valor1,int valor2);
public void efetuarOperacao(int valor1, int valor2){
int resultado = handleEfetuarOperacao(valor1, valor2);
System.out.println("O resultado é: "+ resultado);
}
}
No código acima criamos uma classe abstrata que possui o método abstrato handleEfetuarOperacao(int valor1, valor2) que as classes filhas de Operacao serão obrigadas a implementar e possuimos também nosso método efetuarOperacao(int valor1, int valor2), que utiliza dos serviços de handleEfetuarOperacao que será implementado pelas classes filhas.
Vamos criar mais uma classe:
public class Soma extends Operacao {
@Override
public int handleEfetuarOperacao(int valor1, int valor2) {
return valor1 + valor2;
}
}
Observe que na classe acima herdamos de Operacao, portanto reimplementamos o método handleEfetuarOperacao devolvendo a soma dos valores passados por parâmetro.
Vamos agora fazer outra classe:
public class Subtracao extends Operacao {
@Override
public int handleEfetuarOperacao(int valor1, int valor2) {
return valor1 - valor2;
}
}
Na classe acima também herdamos de Operacao, portanto reimplementamos o método handleEfetuarOperacao
mas desta vez devolvendo a subtração dos parâmetros.
Vamos agora fazer uma classe que utilizará estes métodos:
public class Cliente {
public static void main(String[] args) {
Operacao op = new Soma();
Operacao op2 = new Subtracao();
op.efetuarOperacao(10, 4);
op2.efetuarOperacao(10, 4);
}
}
Na classe acima criamos dois objetos Operacao um Soma e outro Subtracao e em ambos chamamos o método efetuarOperacao(10,4) passando os mesmos valores nas duas chamadas, porém a primeira chamada irá invocar o método handleEfetuarOperacao da classe Soma e o segundo irá chamar o da classe Subtracao.
Estes serão os resultados obtidos:
O resultado é: 14
O resultado é: 6
Ok, finalizamos este post aqui.
abraço.
Singleton
Postado por Diego Ferreira da Silva como Padrões de Projeto em 28 de março de 2009
Olá pessoal!
Vamos falar hoje sobre o padrão de projeto Singleton.
Para melhor entendermos vamos imaginar que temos um sistema que necessita estabelecer conexões em diversos instantes do seu funcionamento com o banco de dados, e dependendo to tamanho do nosso sistema pode ser que ele solicite centenas de conexões com o banco de dados a cada minuto, não seria viável a nível de performance que a cada solicitação desta fosse criada uma nova conexão com o banco de dados, é ai que vamos utilizar o padrão de projetos Singleton, é claro que ele pode ser utilizado em diversos outros cenários, mas no nosso caso vamos exemplificar através deste pois o mesmo é bem didático.
O papel do Singleton é fazer com que uma determinada classe possua apenas uma instância, independente de quantas solicitações forem feitas.
Vamos então simular este cenário com duas classes, uma que representará nossa conexão com o banco de dados e a outra que seria uma usuária desta classe.
Abaixo o código da classe que representa nossas conexões no sistema:
public class ConexaoBanco {
/*Criamos um atributo estático que representará
* nossa única instancia desta classe no sistema
*/
private static ConexaoBanco instancia = null;
/*Aqui estamos tornando nosso construtor privado de
* forma que ele nunca possa ser utilizado por outra
* classe.
*/
private ConexaoBanco() {
}
/*Aqui nosso método que faz o serviço principal do Singleton
* ele verifica se ja existe uma instância desta classe
* caso nao exista ele cria uma e retorna o objeto
* caso exista ele simplesmente retorna o objeto que
* já existe.
*/
public static ConexaoBanco getInstancia() {
if (instancia == null) {
instancia = new ConexaoBanco();
}
return instancia;
}
}
Basicamente os passos que fizemos foram os seguintes:
- Criamos um atributo de classe referente a uma instância da classe em questão
- Tornamos nosso construtor private de forma que ele só possa ser acessado pela própria classe
- Criamos um método estático que verifica se existe uma instância da classe, caso existe ele retorna ela, caso não exista ele retorna uma nova instância.
Agora vamos a nossa classe que utiliza a classe ConexaoBanco:
public class Cliente {
public static void main(String args[]){
/*Obtemos uma instância de ConexaoBanco
* como ainda não havia nenhuma criada no sistema
* ele retorna uma nova instância.
*/
ConexaoBanco con = ConexaoBanco.getInstancia();
//Outros códigos
/*
* Obtemos outra instancia de ConexaoBanco, agora
* como ja havia uma ele retorna a instância que
* já havia sido criada no método anterior.
*/
ConexaoBanco con2 = ConexaoBanco.getInstancia();
}
}
Na nossa classe Cliente ao obtermos um objeto da classe ConexaoBanco pela primeira vez através do método ConexaoBanco.getInstancia(), este método verifica se há uma instancia da
classe criada no sistema, no nosso caso como é a primeira vez que o estamos invocando ele criará um novo objeto de ConexaoBanco e o retornará, agora quando invocarmos novamente o método
ele não criará mais instâncias da classe apenas retornará a que já foi criada anteriormente.
É isso ai, muito simples e util não?!
Abraços!
Classe Properties
Postado por Diego Ferreira da Silva como Java, Java SE em 28 de março de 2009
Veremos neste post como pode ser útil a utilização da classe Properties para ler arquivos de configuração.
A classe
A classe java.util.Properties, presente desde a versão 1.0 do JDK, é filha (extende) da classe java.util.Hashtable e, por consequência, implementa a interface Map. Ela armazena pares de valores, assim como a Hashtable, com uma diferença: ambos os valores (chave e valor) são Strings.
Para quem nunca usou nenhum Map, é interessante saber que um Map associa dois objetos: dado uma chave, pego um valor. Um exemplo de Mapa que poderia ser representado em java:
| norte = tesouro sul = pirata oeste = pirata leste = oasis |
Como podemos ver, um Map é um conjunto de pares chave->valor associados. Uma chave só tem um valor, mas podem existir várias chaves que tem o mesmo valor. No nosso caso, sul e oeste tem o mesmo valor.
O Properties é um mapa especial, pois não associa dois objetos, e sim duas Strings.
Alguns dos métodos da classe Properties:
//retorna null caso não exista um objeto na coleção em que a chave
// tenha o valor "nome" no nosso caso, retornaria "tesouro"
String nome = props.getProperty("norte");
// caso não exista chave com o valor "sudoeste",
// em vez de retornar null, retorna sempre o valor "vazio"
String nome2 = props.getProperty("sudoeste", "vazio");
// adiciona ao mapa a chave "extremoSul", com valor
// "caverna". Caso já exista um elemento na coleção
// com esta chave, o valor na coleção é alterado para este último
props.setProperty("extremoSul", "caverna");
// retorna um Enumeration, sem ordem definida, com as chaves das propriedades
Enumeration enum = props.propertyNames();
// lê os dados de um determinado InputStream
// veremos neste tutorial o formato que este arquivo deve ter
props.load(InputStream in);
// o head representa a comentário que será inserido no começo do arquivo,
// junto com a hora em que os dados foram armazenados.
props.store(OutputStream out, String head);
O método save(OutputStream out, String header) está depreciado (deprecated) porque ele não gera uma IOException caso aconteça algum problema.
Os métodos put() e get(), herdados da classe Hashtable, podem ser utilizados ao invés de setProperty() e getProperty(), desde que os objetos inseridos sejam Strings, caso contrário será gerada uma ClassCastException no momento em que for feita a leitura dos valores presentes na coleção, em razão do tipo dos objetos inseridos não serem Strings.
Estratégia
É possível ler pares de valores armazenados em arquivos texto, a partir do método load(), desde que seja declarado um par de valores por linha no arquivo e que a chave seja separada do valor pelo caracter igual (=). Exemplo: O arquivo mail.properties possui as seguintes configurações:
| #Configurações do arquivo mail.properties mail.pop3.host=pop.dot.com mail.debug=false mail.from=from_user@mail.dot.com mail.user=to_user mail.smtp.host=smtp.dot.com mail.store.protocol=pop3 |
Para inserir um comentário de uma linha no arquivo, utilize a cerquilha (#). Se houver gravação no arquivo, o conteúdo anterior será apagado inclusive os comentários.
Convencionou-se colocar a terminação .properties a esses arquivos textos de configurações utilizados pelo java, assim como existem os arquivos .ini no windows. É possível encontrar os arquivos .properties no JBoss, Tomcat e em outros projetos.
Atenção: os dados do arquivo .properties serão utilizados na aplicação de acordo com as regras da classe String, por exemplo, user é diferente de User.
Utilizando Properties, não é possível garantir a ordem em que os dados serão armazenados, quer dizer, se vocês armazenarem a coleção do mesmo objeto properties em momentos diferentes da aplicação, o conteúdo do arquivo poderá estar em ordens diferentes. Se a ordem for importante, veja a classe LinkedHashMap, que foi adicionada ao jdk1.4. Ela devolve um iterator com os valores ordenados pela ordem de inserção na HashMap.
Lendo um arquivo .properties
Para ler um arquivo, é necessário criar um InputStream a ser lido e um objeto da classe Properties. O passo seguinte é chamar o método load() da classe Properties para ler os dados que estão no arquivo.
// o arquivo encontra-se no mesmo diretório
//da aplicação
File file = new File("mail.properties");
Properties props = new Properties();
FileInputStream fis = null;
try {
fis = new FileOutputStream(file);
//lê os dados que estão no arquivo
props.load(fis);
fis.close(0;
}
catch (IOException ex) {
System.out.println(ex.getMessage());
ex.printStackTrace();
}
Agora é possível manipular os dados que foram lidos do arquivo.
String user = props.getProperty("mail.user");
String from = props.getProperty("mail.from");
String smtp = props.getProperty("mail.smtp.host");
String pop3 = props.getProperty("mail.pop3.host");
String protocol = props.getProperty("mail.store.protocol");
String debug = props.getProperty("mail.debug");
Para alterar o valor de user no objeto props, utilize o método setProperty():
String user = "guj";
props.setProperty("mail.user", user);
Notem que o valor anterior de “mail.user” foi perdido.
A sequência a seguir mostra como persistir os dados do objeto props em um arquivo diferente:
//o arquivo encontra-se no mesmo diretório da aplicação
File file = new File("mail2.properties");
FileInputStream fos = null;
try {
fos = new FileOutputStream(file);
//grava os dados no arquivo
props.store(fos,"Configurações do arquivo mail.properties");
fos.close();
}
catch (IOException ex) {
System.out.println(ex.getMessage());
ex.printStackTrace();
}
Conclusão
A utilização da classe Properties com um arquivo de configurações permite mais facilidade para manter a aplicação sem a necessidade de recompilar o código fonte a cada mudança nas configurações. Basta alterar o arquivo com as configurações e reiniciar a aplicação. Existem formas de atualizar o conteúdo do objeto properties sem reiniciar a aplicação e serão abordadas em um outro post.
Integrando DWR ao Spring
Postado por Diego Ferreira da Silva como Java, Java EE em 20 de março de 2009
Neste post vamos desenvolver uma pequena aplicação passo a passo mostrando como efetuar as configurações necessárias para integrar o DWR 3.0 ao springframework 2.5.
- Ambiente:
- Eclipse Ganymede
- Tomcat 6.0
- Spring 2.5
- DWR 3.0
Primeiramente efetuamos o download do DWR no site, efetue o download do arquivo dwr.jar.
Após o download copie o arquivo dwr.jar para o diretório WEB-INF/lib de sua aplicação(ctrc+c no arquivo, ctrc+v na pasta lib dentro do eclipse).
Agora vamos vazer o download do spring no site, efetue o download do arquivo spring-framework-2.5.6.zip.
Extraia este aquivo em alguma pasta no seu computador e depois copie os arquivos: spring.jar e spring-webmvc.jar para a pasta WEB-INF/lib do seu projeto.
Precisaremos tambem do arquivo commons-logging-xxx.jar que pode ser adiquirido aqui. Após efetuar o downlaod repita o processo acima, extraia o arquivo zip e copie o arquivo commons-logging-xxx.jar para a pasta WEB-INF/lib de sua aplicação.
Pronto! Estamos com o ambiente projeto para utilizar o DWR com o Spring!
Agora crie dois pacotes na dentro da pastar src do seu projeto br.com.diego.bean e br.com.diego.dwr.
Crie uma página jsp dentro de WebContent com o nome index.jsp.
Crite um arquivo applicationContext-DWR.xml dentro da sua pasta WEB-INF.
A estrutura do seu projeto deve ser como esta abaixo:

Vamos alterar nosso arquivo web.xml, deixe seu arquivo conforme a configuração abaixo:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>springDwr</display-name> <!-- Mapeamento dos arquivos de configuração do spring --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext*.xml</param-value> </context-param> <!-- fim mapeamento arquivos spring --> <!-- Mapemento do filtro do spring --> <filter> <filter-name>requestContextFilter</filter-name> <filter-class>org.springframework.web.filter.RequestContextFilter</filter-class> </filter> <filter-mapping> <filter-name>requestContextFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- Fim do mapeamento do spring --> <!-- Listerners do spring --> <listener> <listener-class> org.springframework.web.context.request.RequestContextListener</listener-class> </listener> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!--Fim Listerners do spring --> <!--Servlet DWR - que efetua a integração do DWR com o spring --> <servlet> <servlet-name>dwr</servlet-name> <servlet-class>org.directwebremoting.spring.DwrSpringServlet</servlet-class> <init-param> <param-name>debug</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>crossDomainSessionSecurity</param-name> <param-value>false</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>dwr</servlet-name> <url-pattern>/dwr/*</url-pattern> </servlet-mapping> <!-- Fim servlet DWR --> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
Agora vamos criar uma classe no nosso pacote br.com.diego.bean com o nome de UsuarioBean.java com o conteúdo abaixo:
package br.com.diego.bean;
public class UsuarioBean {
private int id;
private String nome;
private String telefone;
private String endereco;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public String getTelefone() {
return telefone;
}
public void setTelefone(String telefone) {
this.telefone = telefone;
}
public String getEndereco() {
return endereco;
}
public void setEndereco(String endereco) {
this.endereco = endereco;
}
}
Vamos criar outra classe, agora no nosso pacote br.com.diego.dwr, vamos dar o nome de UsuarioAjax.java, esta classe que terá nosso método que será invocado através do nosso javascrpit através de uma chamada AJAX do DWR. Segue abaixo o conteúdo da classe:
package br.com.diego.dwr;
import br.com.diego.bean.UsuarioBean;
public class UsuarioAjax {
private UsuarioBean usuario;
public UsuarioBean getUsuario() {
return usuario;
}
public void setUsuario(final UsuarioBean usuario) {
this.usuario = usuario;
}
//Método que será invocado pela nossa chamada DWR
public UsuarioBean find(String nome){
getUsuario().setId(1);
getUsuario().setNome(nome);
getUsuario().setEndereco("Rua santo DWR número 555");
getUsuario().setTelefone("9999-9999");
return getUsuario();
}
}
Agora vamos a parte principal do nosso artigo, a configuração do arquivo applicationContext-DWR.xml, pois é neste arquivo que fica nossas configurações do DWR e também nossos beans da aplicação e do DWR.
Segue abaixo a configuração do arquivo applicationContext-DWR.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:dwr="http://www.directwebremoting.org/schema/spring-dwr" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.directwebremoting.org/schema/spring-dwr http://directwebremoting.org/schema/spring-dwr-3.0.xsd"> <!-- Configurações de inicialização da Engine do DWR --> <bean id="dwrHandlerMappings" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="order" value="1" /> <property name="alwaysUseFullPath" value="true"></property> <property name="mappings"> <props> <prop key="/dwr/**/*">dwrController</prop> <prop key="/dwr/*">dwrController</prop> <prop key="/engine.js">dwrController</prop> <prop key="/util.js">dwrController</prop> <prop key="/interface/**">dwrController</prop> <prop key="/call/**">dwrController</prop> </props> </property> </bean> <!-- Configurações do DWRControle que é o controlador do DWR --> <dwr:controller id="dwrController" debug="true"> <dwr:config-param name="activeReverseAjaxEnabled" value="true" /> </dwr:controller> <!-- Nosso bean do DWR que converte nosso método find dentro da classe UsuarioAjax em um metodo javascript --> <bean id="dwrUsuario" class="br.com.diego.dwr.UsuarioAjax"> <dwr:remote javascript="usuarioAjax"> <dwr:include method="find" /> </dwr:remote> <property name="usuario" ref="usuarioBean"/> </bean> <!-- Inserimos uma configuracao do DWR para nossos convertes aqui, estes convertes servem para converter nossos beans java em objetos javascript --> <dwr:configuration> <dwr:convert type="bean" class="br.com.diego.bean.UsuarioBean" /> </dwr:configuration> <!-- Nosso bean referente a classe UsuarioBean, este será injetado na classe UsuarioAjax --> <bean id="usuarioBean" class="br.com.diego.bean.UsuarioBean"/> </beans>
Nossa página index.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Exemplo Spring DWR</title>
<script type='text/javascript'
src='/springDwr/dwr/interface/usuarioAjax.js'></script>
<script type='text/javascript' src='/springDwr/dwr/engine.js'></script>
<script type='text/javascript' src='/springDwr/dwr/util.js'></script>
<script type="text/javascript">
function findUser() {
var nome = document.getElementById("inputNome").value;
usuarioAjax.find(nome, {
callback : function(usuarioBean) {
dwr.util.setValue('divShow', usuarioBean.id + " / "
+ usuarioBean.nome + " - " + usuarioBean.endereco
+ " - " + usuarioBean.telefone);
}
});
}
</script>
</head>
<body>
<table>
<tr>
<td><label for="inputNome">Nome:</label></td>
<td><input type="text" id="inputNome" maxlength="20" width="20px"></td>
<td><input type="button" value="Enviar" onclick=findUser();></td>
</tr>
</table>
<br>
<div id="divShow"></div>
</body>
</html>
Observe que temos alguns imports de javascript na nossa página jsp, se você criou um projeto idêntico ao que foi passado aqui neste artigo você poderá acessar a url da imagem abaixo para verificar que o próprio DWR lhe fornecess os imports necessários que você deverá incluir na sua página jsp para que tenha acesso a seu método na sua classe java, inclusive tem como até mesmo você testar atravéz desta url de teste do DWR.

Se deu tudo certo você poderá acessar sua aplicação que você terá o resultado abaixo, ao clicar no botão enviar o DWR irá invocar seu método find dentro da sua classe UsuarioAjax que retornará um bean UsuarioBean que será exibido na página sem refresh algum.

Efetutem o donwload do projeto(sem os arquivos jar) aqui.
Bom pessoal este artigo fica por aqui, este é apenas o primeiro de muitos que virão, espero que tenham gostado.
Estou a disposição para esclarecer dúvidas!
Abraços !!!
Novas features do Java EE 6
Postado por Diego Ferreira da Silva como Java, Java EE em 20 de março de 2009
Plataforma Java EE
A plataforma Java EE é especializada no desenvolvimento de aplicações multicamadas, baseadas em componentes distribuidos, executadas em um servidor de aplicações. Esse servidor (compatível com a especificação Java EE) oferece uma série de serviços de infra-estrutura aos componentes da aplicação (ex. tolerância a falhas, segurança, transações, autenticação, distribuição, etc) que ajudam a garantir a robustez da aplicação sem que o desenvolvedor necessite escrever muitas linhas de código para isso.
Na Java EE 5, o foco foi basicamente na simplicidade de desenvolvimento de componentes, com o uso intensivo de anotações e Injeção de Dependência, a inclusão do JavaServer Faces(JSR 127) e a substituição do padrão Entity Beans pelo padrão Java Persistence API(JSR 220).
Vencida a barreira da complexidade de desenvolvimento, o objetivo na Java EE 6(JSR 316) passa a ser a busca pela maturidade da plataforma, por meio da evolução e fortalecimento de seus padrões, e o aumento na sua flexibilidade de uso e integração.
O maior desafio na especificação da Java EE 6 tem sido na definição de novos conceitos para a plataforma: profiles, extensibility e pruning. Esses conceitos permitem melhor adequação da plataforma às diferentes necessidades do mercado e mais facilidade de integração com novas tecnologias, frameworks e aplicações.
Dentre as melhorias esperadas estão a evolução de algumas APIs mais importantes, como JavaServer Faces 2.0(JSR 314), Java Persistence API 2.0(JSR 317), Enterprise Java-Beans 3.1(JSR 318) e Java Servlet 3.0(JSR 315), e a inclusão de novas APIs como WebBeans(que agora se chama Java Contexts and Dependency Injection JCDI)(JSR 299), Bean Validation(303) e JAX-RS(311).
Profile, Extensibility e Pruning
Desde as primeiras versões da Java EE, várias tecnologias, frameworks e aplicações tem sido criadas para suprir as imperfeições da plataforma ou aumentar sua facilidade de desenvolvimento. Para melhorar a capacidade de integração das aplicações Java EE com essas tecnologias, a versão 6 da plataforma tem dois grandes objetivos: a definição de profiles e o suporte à extensibilidade
Profiles
Um profile é caracterizado por um conjunto de tecnologias, que fazem parte ou não da especificação Java EE completa, necessários para suportar o desenvolvimento de aplicações de diferentes segmentos do mercado.
O uso de profiles na Java EE 6 é a resposta às críticas enfrentadas pela plataforma no que diz respeito ao tamanho da especificação Java EE. Nem todas as aplicações que desenvolvemos necessitam de utilizar o vasto conjunto de tecnologias que fazem parte do Java EE, o que causa um desespedício de suporte quando se utiliza um servidor Java EE completo. Daí a necessidade para a definição de profiles.
Requisitos comuns como serviço de nomes, recursos de injeção de dependência, regras de empacotamento, segurança, entre outros, devem ser compartilhados por todos os profiles para garantir a uniformidade dos produtos e das aplicações Java EE. Além disso, todas as dependências dos componentes suportados por cadas profile devem estar confidos no profile para garantir o seu funcionamento out-of-the-box.
Extensibility
O aspecto da extensibilidade na plataforma Java EE está relacionada com a necessidade de melhorar o suporte de outras tecnologias e frameworks dentro dos servidores de aplicação Java EE. Por exemplo, atualmente, para usar um framework em uma aplicação Java EE é necessário fazer alterações nos deployment descriptors, criar filtros, ajustar bibliotecas, etc. A proposta de extensibilidade da Java EE 6 é facilitar esse processo criando mais pontos de extensão na plataforma.
Algumas das idéias discutidads para aumentar os pontos de extensão consideram o uso de anotações, injeção de dependência, interceptadores, APIs de serviço (SPIs – Service Providers Interfaces) e, até mesmo, facilidade de implantar um simples jar dentro da aplicação(sem a necessidade de configurações complexas).
Profiles e extensibility são dois conceitos que estão diretamente relacionados, pois os profiles, além de oferecer o conjunto de tecnologias especificadas, também devem permitir a integração simplificada de outras tenologias, mesmo que estas não sejam padrão Java EE.
Pruning
Apesar de não estar como objetivo principal da especificação, pruning ou “poda” é um objetivo igualmente importante para a Java EE 6, que passa por um momento de amadurecimento.
Alguns dos padrões considerados essenciais em versões anteriores da Java EE agoar não são mais tão importantes. Exemplo disso são os Entity Beans, substituídos por JPA na Java EE 5.
A partir da Java EE 6, tecnologias consideradas de pouca relevância podem ser depreciadas para que, somente nas versões futuras da plataforma, se tornem opcionais. Assim, os vendedores de produtos poderão optar se querem ou não manter suporte a essas tecnologias na próxima versão da plataforma. Essa é a definição de pruning adotada no JCP.
Na especificação Java EE 6, as tecnologias eleitas para o pruning são: EJB CMP, substituído pelo JPA, e JAX-RPC(JSR-101), substituído por JAX-WS(JSR-224), ambos na Java EE5. Portanto, a partir da próxima versão da Java EE(Java EE 7), os servidores escolhem se mantêm ou não suporte a essas tecnologias.
Novas versões das principais APIs
Com o objetivo de melhorar ainda mais a facilidade de uso e oferecer recursos mais poderosos para as tecnologias padronizadas na Java EE 6, essa versão também está prevendo uma evolução da principais APIs.
JavaServer Faces 2.0
A versão 2.0 de JavaServer Faces, parte de Java EE 6, está sendo desenvolvida na JSR 314, liberada por Ed Burns e tem como principais novidades:
- Configuração do estágio do projeto/ Project Stage: Permite configurar qual o estágio de desenvolvimento: Production, Test, Development, UnitTest, System Test, Extension. Possibilitando que a aplicação seja executada de forma diferente, dependendo do estágio do projeto, por exemplo, se a aplicação está em produção pode ter um comportamento de log diferente da mesma aplicação em desenvolvimento.
- Criação do escopo View: baseado no escopo Page do JBoss Seam e no escopo KeepAlive do RichFaces, permite que um componente esteja associado a uma página, ou seja, estes componentes tem a “duração de uma página”. Quando o usuário sai daquela página o componente não estará mais acessível;
- Simplificação do desenvolvimento de componentes com conceito similar a TagFiles, baseado em Facelets;
- Definição de uma PDL(Page Description Language): baseada em Facelets, tornando-se a forma padrão para a criação de páginas em detrimento a JSPs.
- Melhor suporte a AJAX: trazendo conceitos de diversas bibliotecas do mercado, como DynaFaces, JMaki e Shale Remoting;
- Introdução do conceito de Resources(recursos): todos os artefatos (arquivos CSS, imagens e scripts) necessários para que o User Agent (geralmente um browser) possa renderizar o componente JSF são chamados recursos e devem ser disponibilizados em um diretório padrão.
Java Persistence API 2.0
A primeira versão da JPA foi lançada em 2006 como parte da especificação do EJB 3.0(JSR-220) para facilitar o desenvolvimento da camada de persistência das aplicações. Muitas das idéias utilizadas na definição da JPA foram baseadas nas esperiências do mercado com frameworks de persistência. No entanto, a JPA 1.0 teve foco nos requisitos essenciais de persistência, não envolvendo aspectos mais podedoros de mapeamento e pesquisa.
Com o crescente interesse nessa API não apenas na plataforma Java EE, a JPA ganhou sua própria especificação (JSR-317) sob a liderança de Linda DeMichiel, que também foi líder das especificações EJB 2.1 e 3.0.
Essa JSR foi incluída na Java EE 6, sendo que o objetivo na versão 2.0 é a inclusão de recursos mais avançados de ORM e de busca.
Em relação aos recursos de ORM, algumas das melhorias trazidas pela JPA 2.0 são:
- Suporte ao mapemaneto de coleções de tipos básicos.
- Suporte a listas ordenadas.
- Melhor suporte a coleção de tipo Map
- Suporte ao relacionamento OneToMany unidirecional com mapeamento por chave estrangeira.
- Inclusão da API de Criteria.
Java Servlet 3.0
Uma das principais melhorias nessa API é a plugabilidade. O objetivo é permitir que frameworks como Struts, JSF, Spring, entre outros, possam ser mais facilmente configurados numa aplicação Web, sem a necessidade de configuração de deployment descriptor como é exigido atualmente. Para isso, o arquivo web.xml passa a ser modular. Cada framework pode definir seu próprio web.xml, usando uma tag específica para definição de fragmentos de aplicação Web, e incluí-lo no diretório META-INF de um arquivo jar. O container é responsável por reconhecer os fragmentos que estão nos jars vinculados à aplicação Web.
A facilidade de desenvolvimento é outro objetivo importante dessa especificação. O uso de recursos da Java SE 5, como anotações e generics, permitem tornar o web.xml opcional e reduzir erros de compilação e execução comumente gerados por implementações e configurações equivocadas. Para criar um servlet na Java EE 6, basta adicionar a anotação @Servlet(url-mapping=”url”) numa classe POJO. Os métodos podem ser anotados com @GET, @POST, entre outras, para identificar o tipo de requisição HTTP atendida. Essas facilidades também estão sendo extendidas para a criação de filtros e listeners.
Um modelo de Servlet assíncrono também está sendo incluído por meio do estilo de programação Comet.
Enterprise JavaBeans 3.1
Na Java EE 5, o componente EJB, que por muitos anos foi criticado por sua complexidade, teve alterações significativas para facilitar o seu uso. O uso de anotações permitiu evitar as interfaces complexas e reduzir as necessidades de configuração no deployment descriptor. Mas a busca pela simplicidade continua na Java EE 6 com o EJB 3.1(JSR 318), liberado por Kenneth Saks.
As interfaces de negócio passam a ser opcionais para acesso local: o loolup pode ocorrer diretamente pela classe do componente, sendo que todos os seus métodos públicos ficam disponíveis. Para oferecer esse suporte, basta não adicionar interfaces para o componente, ou, se uma interface remota(ou mesmo local) já estiver sendo oferecida, basta usar a anotação @LocalBean.
Alguns métodos do EJB podem ser marcados como a anotação @Asynchronous.
O Cliente do componente faz a requisição ao método assíncrono sem precisar esperar pelo retorno imediado, solicitando o resultado quando necessário. O cliente só é bloqueado para esperar um retorno do componente caso a resposta da requisição ainda não tenha sido totalmente concluída quando o cliente a solicita.
Novas APIs
É comum ouvirmos falar que Web Beans é o JBoss Seam, assim JPA é o Hibernate, ou como Facelets está sendo incorporado no JSF 2.0. Mas na verdade a história não é tão simples. Uma analogia válida équando criamos uma classe e depois “extraímos” a interface desta classe. A interface pode não conter todos os métodos e certamente não contém todos os detalhes de implementação da classe. A mesma coisa acontece com os frameworks que estão sendo “incluídos” na Java EE.
Web Beans
A JSR 299: Web Beans, foi criada para unificar os padrões de componentes EJB e JSF Managed Beans, oferecendo um modelo de programação mais simples para aplicações Web. Diversos traços do framework JBoss Seam estão presentes em Web Beans, mas não exatamente como uma réplica, pois diversas funcionalidades de JBoss Seam não serão implementadas. Além disso, houve uma redução do acoplamento com JavaServer Faces, tornando o Web Beans útil para todos os tipos de aplicação, independente do uso de JSF ou EJB 3.0.
Algumas das principais caracteristicas desta API são:
- Permitir que qualquer componente possa ser acessado via Unified Expression Language(EL) em páginas JSF e JSP.
- Introduzir um novo escopo/contexto para as aplicações Web, chamado Conversation, que é maior do que o escopo de Request, e menor do que o escopo Session.
- Um Web Bean poderá ser injetado em qualquer componente Java EE.
O gerenciador de Web Beans oferece os seguintes serviços para aplicações com EJBs:
- Injeção de Web Beans em qualquer EJB, Servlet ou Listener ou outro Web Bean;
- Binding de interceptors e decorators;
Gerenciamento do ciclo de vida dos EJBs, criando e destruindo os componentes e disponibilizando as instâncias no contexto da aplicação.
Existem quatro formas diferentes de criarmos um Web Bean, são elas:
- Simple Web Bean: uma classe Java simples, concreta;
- Enterprise Web Bean: é um Web Bean implementado com um Enterprise Java Bean;
- Producer Methods: são fábricas de objetos que retornam objetos para serem injetados em outros componentes;
- JMS endpoint: é um Web Bean que representa uma fila ou tópico JMS.
Bean Validation
A JSR 303: A API de validação definida por essa JSR não foi projetada para atender a um tipo específico de aplicação(Web ou Desktop) ou ainda a uma camada específica da aplicação. Pelo contrário, foi criada para unificar a validação em todas as camadas e nos diversos tipos de aplicação Java, sendo vista como uma extensão ao modelo de componentes JavaBeans. Sua configuração pode ser feita por anotações ou XML.
JAX-RS 1.0
Para oferecer suporte ao novo formato de serviços web(REST), a JSR 311 definiu a API JAX-RS 1.0, baseada em anotações da Java SE 5, para viabilizar a disponibilização de RESTFul web services na plataforma Java SE e Java EE.
É isso ai, este artigo fica por aqui!
Abraços!

