[dicas-list] Design Patterns J2EE - Value List Handler
Design Patterns J2EE - Value List Handler
Nome
--
Value List Handler
Outros nomes
--
Page By Page Iterator
Contexto
--
Clientes frequentemente precisam recuperar grande massa de informações para
formatação de relatórios na camada de apresentação.
Problema
--
- O alto custo do uso de métodos finders em entity beans não justifica
sua utilização para a recuperação para leitura de grande quantidade de
informações.
- Para o cliente, é muito difícil absorver toda a massa de dados recuperados
de uma só vez, fazendo necessária a utilização de algum mecanismo de
paginação do resultado da consulta.
Solução
--
Implementar um mecanismo para a recuperação de informações que não utilize
entity beans e que mantenha um cache do resultado para que os dados possam
ser fornecidos ao cliente de acordo com sua demanda.
Consequências
--
+ Melhora de performance:
. o uso de entity beans para recuperar N registros envolve N+1
consultas SQL (1 para o findByAlgumaCoisa e outras N para popular
cada bean que for encontrado). O uso de um mecanismo direto pode
reduzir esta quantidade a apenas 1 query, independente
da quantidade de registros encontrados.
. A possiblidade de implementação de um cache evita a necessidade
de realização de uma nova query a cada transição entre páginas.
Estratégias
--
Criar um session bean statefull que implemente uma interface Iterator e,
com o auxílio de DAOs (próximo pattern), acesse a camada de persistência,
recupere as informações desejadas e mantenha estas informações em cache
para fornecer ao cliente segundo sua demanda.
/**
* Interface com serviços para a navegação no resultado
* @author alegomes
*/
public interface ValueListIterator
{
/**
* Navega para a proxima pagina
*/
public Collection next(int qtd);
/**
* Navega para a pagina anterior
*/
public Collection previous(int qtd);
/**
* Recupera o elemento corrente, que e a referencia para a
* transicao entre paginas
*/
public ValueObject getCurrent();
/**
* Reinicializa o elemento corrente para o primeiro elemento da lista
*/
public void reset();
/**
* Retorna a quantidade de elementos disponiveis
*/
public int size();
}
/**
* VaueListHandle: Statefull session bean que implementa a interface
* ValueListIterator
* @author alegomes
*/
class ValueListHandler implements ValueListIterator, SessionBean
{
private Vector cache;
//Indice para o elemento corrente. Ele é a referencia para a
//transicao entre paginas.
private int idxCurr;
//Indice para o ultimo elemento disponivel
private int idxLast;
public void ejbCreate()
{
cache = new Vector();
//Nao vem ao caso por enquanto, mas o proximo passo aqui
//seria a recuperacao das informacoes e o respectivo armazenamento
//no cache.
//Logo, teriamos uma serie de cache.add(elemento);
cache.trimToSize()
idxCurr = 0;
idxLast = cache.size();
}
//Outros metodos ejb*
//Inicio da implementacao da interface ValueListIterator
public Collection next(int qtd)
{
Vector page = new Vector();
while ((idxCurr < idxLast) && (qtd > 0))
{
page.add(cache.elementAt(idxCurr));
idxCurr++;
qtd--;
}
page.trimToSize();
return page;
}
public Collection previous(int qtd)
{
Vector page = new Vector();
while (idxCurr > 0 && qtd > 0)
{
idxCurr--;
page.add(cache.elementAt(idxCurr));
qtd--;
}
}
public ValueObject getCurrent()
{
return (ValueObject)cache.elementAt(idxCurr);
}
public void reset()
{
idxCurr = 0;
}
public int size()
{
return idxLast;
}
}
Próximo design pattern J2EE: Data Access Object
Bons patterns !!!
Alexandre Gomes
Sou Jedi, Sou Java!
[dicas-list] circula diariamente com pequenas dicas sobre a plataforma Java e é
mais um serviço da Sociedade de Usuários Java - http://www.soujava.org.br
*** SouJava - Fortalecendo a Comunidade Java Brasileira! ***
- Para contribuir com uma dica, envie um e-mail para [EMAIL PROTECTED]
- Participe de outras listas de discussão sobre a linguagem Java.
Saiba mais em http://www.soujava.org.br/lista.htm
- Para assinar este boletim: mailto:[EMAIL PROTECTED]
- Para cancelar sua assinatura: mailto:[EMAIL PROTECTED]
- Dicas anteriores: http://www.mail-archive.com/dicas-list%40soujava.org.br
- Para discutir sobre as dicas, acesse o Mundo OO (http://www.mundooo.com.br)
[dicas-list] Design Patterns J2EE - Service Locator
Design Patterns J2EE - Service Locator
Nome
--
Service Locator
Outros nomes
--
EJBHomeFactory (não é exatamente outro nome, mas ambos se
assemelham em alguns aspectos)
Contexto
--
Antes de um cliente utilizar um EJB, é preciso que ele encontre
ou então crie uma nova instância do bean.
Problema
--
Utilizar um EJB implica em alguns passos:
- criação de um InitialContext JNDI, que representa os mapeamentos entre
nome lógico e nome da classe do bean
- lookup da interface home, que controla o ciclo de vida do componente
- criação ou recuperação do EJB
- finalmente, a utilização dos seus serviços
Além de incrementar a complexidade do código cliente, estas atividades são
necessárias para todos os clientes que utilizarem um mesmo bean, o que gera
um alto nível de repetição de código. Por exemplo, se um EJB é acessado
por helper classes, por uma aplicação console, por um Session Facade e até
por outros beans, as tarefas apontadas acima serão repetidas em todos os
tipos de clientes.
Solução
--
Criar uma classe (ServiceLocator) que transpareça do cliente e concentre
toda a complexidade JNDI.
Consequências
--
+ Melhora de performance, já que mecanismos de cache podem ser implementados
no ServiceLocator, para evitar lookups desnecessários
+ Reduz a complexidade do código cliente
+ Facilita a manutenção, por não pulverizar o mesmo trecho de código em vários
pontos da aplicação
+ Tira do cliente toda dependência ao mecanismo de lookup
Estratégias
--
/**
* ServiceLocator que implementa um cache de interfaces home
* @author alegomes
*/
class ServiceLocator
{
/**
* Contexto JNDI cuja instaciação será reduzida, já que o custo
* deste tipo de operação é alto.
*/
private InitialContext jndiContext;
/**
* Cache de interfaces home, para reduzir o numero de lookups
*/
private Hashtable homeCache;
/**
* Este ServiceLocator será um Singleton
*/
private static ServiceLocator instance;
/**
* Criação
*/
public ServiceLocator()
{
homeCache = new Hashtable();
jndiContext = new InitialContext();
//Obs: excessões omitidas
}
/**
* Recupera a instancia do Singleton
*/
public ServiceLocator getLocator()
{
return instance;
}
/**
* Recupera uma interface home.
* O lookup do bean só é feito se não houver nenhuma
* referência sua no cache
*/
public EJBHome getService(String jndiName)
{
if (!homeCache.containsKey(jndiName))
{
//É a primeira vez que este bean é solicitado.
//Vamos colocá-lo no cache.
Object ref = jndiContext.lookup(jndiName)
EJBHome home = (EJBHome)PortableRemoteObject.narrow(ref, EJBHome.class);
homeCache.put(jndiName, home);
}
return homeCache.get(jndiName);
}
}
}
Do lado cliente, para um bean ser utilizado, basta utilizarmos:
ServiceLocator.getLocator().getService("meuEJBPreferido");
Observações
--
1 - Este código está longe de ser a solução ótima. Não é o objetivo.
2 - Uma outra estratégia é implementar o ServiceLocator como Stateful Session Bean.
3 - O ServiceLocator pode ser utilizado para a recuperação de qualquer tipo de
serviço que esteja disponível na estrutura JNDI:
- QueueConnectionFactory
- Queue
- TopicConnectionFactory
- Topic
- DataSource
- URL
- EJBLocalHome
Próximo design pattern J2EE: ValueListHandler
Bons patterns !!!
Alexandre Gomes
Sou Jedi, Sou Java!
[dicas-list] circula diariamente com pequenas dicas sobre a plataforma Java e é
mais um serviço da Sociedade de Usuários Java - http://www.soujava.org.br
*** SouJava - Fortalecendo a Comunidade Java Brasileira! ***
- Para contribuir com uma dica, envie um e-mail para [EMAIL PROTECTED]
- Participe de outras listas de discussão sobre a linguagem Java.
Saiba mais em http://www.soujava.org.br/lista.htm
- Para assinar este boletim: mailto:[EMAIL PROTECTED]
- Para cancelar sua assinatura: mailto:[EMAIL PROTECTED]
- Dicas anteriores: http://www.mail-archive.com/dicas-list%40soujava.org.br
- Para discutir sobre as dicas, acesse o Mundo OO (http://www.mundooo.com.br)
[dicas-list] Design Patterns J2EE - Business Delegate
Design Patterns J2EE - Business Delegate
Demorou mas saiu!
Nome: Business Delegate
Outros nomes: Client Facade, Session Proxy
Contexto: Aplicação cliente necessita acessar serviços de uma Session Facade (poderia ser qualquer outro tipo de EJB, mas é bom para que percebam como os patterns se relacionam)
Problema: Vários passos são necessários para a utilização dos serviços da Session Facade (ou qualquer outro EJB). Veja na classe abaixo:
/**
* Cliente que NÃO USA Business Delegate
* @author alegomes
*/
class ClienteSemBusinessDelegate
{
void metodo()
{
//Passsos para a utilização dos serviços de uma Session Facade
Context ctx = new InitialContext();
Object ref = ctx.lookup("SessionFacade");
SessionFacadeHome home = (SessionFacadeHome)
PortableRemoteObject.narrow(ref, SessionFacadeHome.class);
SessionFacade sf = home.create();
sf.servico1();
}
}
Esta sequência de tarefas, além de tornar complexa a aplicação cliente, cria dependências diretas entre a camada de apresentação e a tecnologia utilizada na camada de negócios. Caso fosse necessário alterar a tecnologia dos componentes de negócios, toda a aplicação cliente haveria de sofrer modificações, pois aquele código é específico para EJB.
Solução: Ocultar da aplicação cliente todos os detalhes específicos da tecnologia utilizada na construção dos componentes de negócio.
+-++--++-+
| || || |
| Cliente | -> | Business | -> | Session |
| || Delegate || Facade |
+-++--++-+
Consequências:
+ Maior desacoplamento entre as camadas
+ Simplifica o código cliente
+ Incrementa a performance na medida em que se pode implementar mecanismos de cache no Business Delegate
Estratégias: Para cada Session Facade, implementar uma classe local com a mesma interface de serviços.
Exemplo:
/**
* Session Facade
* @author alegomes
*/
class SessionFacade implements SessionBean
{
//métodos ejb
//métodos de negócio
void servico1()
{
//Implementação do serviço 1
}
void servico2()
{
//Implementação do serviço 2
}
}
/**
* Business Delegate
* @author alegomes
*/
class BusinessDelegate
{
SessionFacadeHome home;
//Construtor
BusinessDelegate()
{
Context ctx = new InitialContext();
Object ref = ctx.lookup("SessionFacade");
home = (SessionFacadeHome)PortableRemoteObject.narrow(ref, SessionFacadeHome.class);
}
//métodos de negócio
void servico1()
{
SessionFacade sf = home.create();
sf.servico1();
}
void servico2()
{
SessionFacade sf = home.create();
sf.servico2();
}
}
/**
* Cliente que USA Business Delegate para realização de "metodo"
* @author alegomes
*/
class ClienteComBusinessDelegate
{
BusinessDelegate bd;
ClienteComBusinessDelegate()
{
bd = new BusinessDelegate();
}
void metodo()
{
bd.servico1();
}
}
Usando o Business Delegate, o código cliente só enxerga invocações locais, e toda a complexidade das chamadas remotas ficam ocultas dentro dele. Além de facilitar o desenvolvimento da aplicação cliente, o uso do Business Delegate desata as amarras entre as camada de apresentação e a tecnologia da camada de negócio. Caso haja a necessidade de migrar de EJB para qualquer outra tecnologia de componentes de negócios, a aplicação cliente permaneceria intacta, ficando as consequências limitadas apenas nos Business Delegates.
Próximo design pattern J2EE: Service Locator
Bons patterns !!!
Alexandre Gomes
Sou Jedi, Sou Java!
[dicas-list] circula diariamente com pequenas dicas sobre a plataforma Java e é
mais um serviço da Sociedade de Usuários Java - http://www.soujava.org.br
*** SouJava - Fortalecendo a Comunidade Java Brasileira! ***
- Para contribuir com uma dica, envie um e-mail para [EMAIL PROTECTED]
- Participe de outras listas de discussão sobre a linguagem Java.
Saiba mais em http://www.soujava.org.br/lista.htm
- Para assinar este boletim: mailto:dicas-list-subscribe@;soujava.org.br
- Para cancelar sua assinatura: mailto:dicas-list-unsubscribe@;soujava.org.br
- Dicas anteriores: http://www.mail-archive.com/dicas-list%40soujava.org.br
- Para discutir sobre as dicas, acesse o Mundo OO (http://www.mundooo.com.br)
[dicas-list] Design Patterns J2EE - Session Facade
Design Patterns J2EE - Session Facade
Olá amigos, por razões estratégicas, ao contrário do anunciado, vamos
apresentar o design pattern Session Facade na sequência. Ele
facilitará a apresentação posterior do Business Delegate.
Nome : Session Facade
Outros nomes: não achei. Deve ser consenso :-)
Contexto: Às vezes, a realização de um caso de uso envolve a
invocação de diversos EJBs.
Problema: O alto índice de chamadas remotas traz prejuízos à
performance da aplicação.
Solução: Ocultar a alta interatividade entre EJBs, através de
interfaces locais, atrás de um único método remoto.
Consequências:
+ Menos invocações remotas
+ Simplifica a interface de serviços remotos para o cliente,
disponibilizando um ponto central para a realização de um caso de uso
+ Desacoplamente entre as camadas de apresentação e negócio, uma vez
que todas os relacionamentos e dependências entre as entidades envolvidas
na realização do caso de uso ficam transparentes ao cliente.
Estratégias: Implementar um session bean stateless com serviços de
alto nível de granularidade
Exemplo:
/**
* Cliente que NÃO USA Session Facade
* @author alegomes
*/
class ATM
{
void transferenciaEntreContas(long c1, long c2)
{
//Lookup e find do EJB ContaCorrente de origem
//Lookup e find do EJB ContaCorrente de destino
ejbCCOrigem.sacar(valor);
ejbCCDestino.depositar(valor);
}
}
/**
* Cliente que USA Session Facade
* @author alegomes
*/
class ATM
{
void transferenciaEntreContas(long c1, long c2)
{
//Lookup e find da Session Facade OperacoesBancarias
sf.transferir(c1, c2);
}
}
/**
* Session Facade
* @author alegomes
*/
public class OperacoesBancarias implements SessionBean
{
//ejbMetodos
/**
* Método único que o cliente deve chamar para realizar
* transferência de fundos entre contas correntes.
*/
public void transferir (long c1, long c2)
{
//Lookup e find do EJB ContaCorrente de origem
//Lookup e find do EJB ContaCorrente de destino
ejbCCOrigem.sacar(valor);
ejbCCDestino.depositar(valor);
}
}
À primeira vista, pela simplicidade do exemplo, talvez se tenha
tido alguma decepção quanto aos reais benefícios do uso do pattern.
Entretanto, imaginem que no mundo real a transferência entre contas
não é apenas tirar de um lugar e por no outro, mas envolve também a
autenticação do usuário, validação das contas (bloqueadas, saldo
suficiente), geração de logs etc. Quando este volume de passos começa
a crescer é que efetivamente percebemos o quão importante é implementar
uma fachada de serviço de alto nível de granularidade a fim de
facilitar o desenvolvimento por parte do cliente, reduzir o
acomplamento entre as camadas e diminuir o overhead relativo ao grande
número de chamadas remotas que estariam sendo realizadas.
Observações: Pessoal, quisera eu detalhar aqui todas as nuâncias
relativas à aplicação deste e outros design patterns. Infelizmente,
por questões de espaço (e tempo), isto não é possível. Considerem estas
dicas apenas como catalizadores para o início de um longo processo de
aprendizado. Conforme consta abaixo, na assinatura do email, todas as
dicas podem ser discutidas no MundoOO. Incentivo também o uso da
enterprise-list, do SouJava, para a resolução de dúvidas e obtenção
de maiores detalhes práticos relativos ao tema.
Próximo design pattern J2EE: Business Delegate (agora sim)
Bons patterns !!!
Alexandre Gomes
Sou Jedi, Sou Java!
[dicas-list] circula diariamente com pequenas dicas sobre a plataforma Java e é
mais um serviço da Sociedade de Usuários Java - http://www.soujava.org.br
*** SouJava - Fortalecendo a Comunidade Java Brasileira! ***
- Para contribuir com uma dica, envie um e-mail para [EMAIL PROTECTED]
- Participe de outras listas de discussão sobre a linguagem Java.
Saiba mais em http://www.soujava.org.br/lista.htm
- Para assinar este boletim: mailto:dicas-list-subscribe@;soujava.org.br
- Para cancelar sua assinatura: mailto:dicas-list-unsubscribe@;soujava.org.br
- Dicas anteriores: http://www.mail-archive.com/dicas-list%40soujava.org.br
- Para discutir sobre as dicas, acesse o Mundo OO (http://www.mundooo.com.br)
[dicas-list] Design Patterns J2EE - Value Object
Design Patterns J2EE - Value Object
--
Sem dúvida este é o design pattern J2EE mais famoso que temos. Por ser o
primeiro a ser apresentado, irei reforçar a importância da correta
compreensão do modelo que estamos utilizando para a descrição de cada
padrão. Detalhes sobre este modelo estão no email anterior, que pode ser
encontrado em http://www.mail-archive.com/dicas-list@;soujava.org.br/. Vamos
ao pattern:
Nome : Value Object
Outros nomes: Detail Object, Data Transfer Object, Replicate Object
Contexto: Aplicação cliente necessita trazer grande quantidade de
informações de um serviço remoto.
Problema: Buscar uma informação por vez tem um custo de rede e performance
extremamente alto.
Solução: Trazer todos os dados de uma só vez, em uma única requisição de
rede, em um objeto chamado Value Object.
Consequências:
+ Menos invocações remotas
+ Simplifica a interface remota e sua implementação
- Se não tomar cuidado, os dados carregados por um VO podem tornar-se
inválidos.
Estratégias: Implementar um JavaBean com todos os atributos que devem ser
transportados "numa única viagem".
Exemplo:
/**
* Classe cliente de um session bean qualquer
* @author alegomes
*/
class Cliente
{
void lerDadosRemotos()
{
Object ref = InitialContext.lookup("MeuSession");
MeuSessionBeanHome home = PortableRemoteObject.narrow(ref,
MeuSessionBeanHome.class);
MeuSessionBean bean = home.create();
/* Ao inves de fazermos isso, que envolve várias conexões de
rede.
* atr1 = bean.getAtributo1();
* atr2 = bean.getAtributo2();
* atr3 = bean.getAtributo3();
* ()
*/
/* fazemos isto, que trará o mesmo conjunto de informações
* com apenas 1 chamada remota:
*/
atr = bean.getValueObject();
}
}
/**
* Interface remota do session bean
* @author alegomes
*/
public interface MeuSessionBean extends EJBObject
{
/* Não precisa mais desses métodos:
* public String getAtributo1() throws RemoteException;
* public String getAtributo2() throws RemoteException;
* public String getAtributo3() throws RemoteException;
*
* Declara apenas um:
*/
public ValueObjectQualquer getValueObject() throws RemoteException;
}
/**
* Implementação do ValueObject
* @author alegomes
*/
public class ValueObjectQualquer implements Serializable
{
private String atributo1;
private String atributo2;
private String atributo3;
(...)
public void setAtributo1(String a)
{
atributo1 = a;
}
public String getAtributo1()
{
return atributo1;
}
() /* gets e sets para os outros atributos */
}
Observações: Originalmente, o Value Object tinha entity beans como principal
ponto de utilização, ou seja, ao invés de fazermos diversos gets e sets para
obter e modificar todos os atributos do entity, poderíamos buscar ou
submeter todas as informações com uma única chamada de rede, através do VO.
Entretanto, a partir da especificação EJB 2.0, com a presença das interfaces
locais, a "exigência" de um Value Object para cada entity bean acabou caindo
no desuso, pois o overhead de rede foi naturalmente eliminado. Em
contrapartida, a idéia do Value Object ainda permanece ativa sempre que se
falar no transporte da muitas informações entre dois nós da sua arquitetura.
Próximo design pattern J2EE: Business Delegate
Bons patterns !!!
Alexandre Gomes
Sou Jedi, Sou Java!
[dicas-list] circula diariamente com pequenas dicas sobre a plataforma Java e é
mais um serviço da Sociedade de Usuários Java - http://www.soujava.org.br
*** SouJava - Fortalecendo a Comunidade Java Brasileira! ***
- Para contribuir com uma dica, envie um e-mail para [EMAIL PROTECTED]
- Participe de outras listas de discussão sobre a linguagem Java.
Saiba mais em http://www.soujava.org.br/lista.htm
- Para assinar este boletim: mailto:dicas-list-subscribe@;soujava.org.br
- Para cancelar sua assinatura: mailto:dicas-list-unsubscribe@;soujava.org.br
- Dicas anteriores: http://www.mail-archive.com/dicas-list%40soujava.org.br
- Para discutir sobre as dicas, acesse o Mundo OO (http://www.mundooo.com.br)
[dicas-list] Design Patterns J2EE - Modelo
Design Patterns J2EE - Modelo Em breve estaremos dando início à sequência de padrões de projeto J2EE a serem apresentados na dicas-list. Contudo, antes disso, precisamos homogeneizar nosso vocabulário. Para a apresentação de cada pattern, será utilizado o modelo abaixo. A utilização de um modelo fixo na descrição de design patterns facilita o aprendizado, utilização e comparação entre padrões: . Nome: Uma ou duas palavras que traduzam, intuitivamente, os objetivos do pattern . Contexto: situação em que o problema foi detectado . Problema: dificuldade encontrada com uma certa constância . Solução: conjunto de estratégias para eliminar o problema encontrado . Consequências: efeitos colaterais causados pela utilização do pattern . Estratégias: normalmente existem várias alternativas para a implementação de um design pattern J2EE. Será mostrada apenas uma destas estratégias. . Exemplo: código fonte exemplificando a estratégia escolhida Próximo design pattern J2EE: Value Object Bons patterns !!! Alexandre Gomes Sou Jedi, Sou Java! [dicas-list] circula diariamente com pequenas dicas sobre a plataforma Java e é mais um serviço da Sociedade de Usuários Java - http://www.soujava.org.br *** SouJava - Fortalecendo a Comunidade Java Brasileira! *** - Para contribuir com uma dica, envie um e-mail para [EMAIL PROTECTED] - Participe de outras listas de discussão sobre a linguagem Java. Saiba mais em http://www.soujava.org.br/lista.htm - Para assinar este boletim: mailto:dicas-list-subscribe@;soujava.org.br - Para cancelar sua assinatura: mailto:dicas-list-unsubscribe@;soujava.org.br - Dicas anteriores: http://www.mail-archive.com/dicas-list%40soujava.org.br - Para discutir sobre as dicas, acesse o Mundo OO (http://www.mundooo.com.br)
[dicas-list] Design Patterns J2EE
Design Patterns J2EE A recente adoção da plataforma J2EE implica em um nível de imaturidade ainda grande nos códigos que entram diariamente em produção. Antes de adotarmos uma nova tecnologia, precisamos estar preparados às armadilhas que nos serão impostas. Utilizar o J2EE de forma incorreta pode ser tão perigoso quanto não usá-lo. Para reduzir o risco de sermos pegos em alguma dessas ciladas tecnológicas, devemos sempre ouvir a voz da experiência de quem já tropeçou muito nesta estrada e conhece os melhores atalhos para nos conduzir. Modelados na forma de design patterns, estes atalhos são definidos na forma de estratégias para solucionar problemas cotidianos. A correta adoção e utilização de design patterns no mundo J2EE aumenta a qualidade do código, incrementa o desempenho da aplicação e provavelmente reduz o retrabalho consequente de refactorings de projetos mal elaborados. Iniciaremos hoje uma sequência de dicas voltadas exclusivamente a este tema. A cada dica, um novo design pattern será apresentado com códigos e exemplos. Até lá! Para quem quiser se adiantar: http://www2.theserverside.com/patterns http://java.sun.com/blueprints/corej2eepatterns/Patterns Bons códigos!!! Alexandre Gomes Sou Jedi, Sou Java! [dicas-list] circula diariamente com pequenas dicas sobre a plataforma Java e é mais um serviço da Sociedade de Usuários Java - http://www.soujava.org.br *** SouJava - Fortalecendo a Comunidade Java Brasileira! *** - Para contribuir com uma dica, envie um e-mail para [EMAIL PROTECTED] - Participe de outras listas de discussão sobre a linguagem Java. Saiba mais em http://www.soujava.org.br/lista.htm - Para assinar este boletim: mailto:[EMAIL PROTECTED] - Para cancelar sua assinatura: mailto:[EMAIL PROTECTED] - Dicas anteriores: http://www.mail-archive.com/dicas-list%40soujava.org.br - Para discutir sobre as dicas, acesse o Mundo OO (http://www.mundooo.com.br)
