quarta-feira, 23 de abril de 2008

Implementação de Stateless Session Beans


Autor: Gleydson Lima <gleydson at j2eebrasil.com.br> e Ulisses Telemaco <ulisses at j2eebrasil.com.br>


O desenvolvimento de aplicações EJB não passa simplesmente pelo processo clássico de aplicações Java: compilação e execução. Desenvolver um componente EJB, seja ele do tipo Session Bean ou Entity Bean, envolve alguns passos adicionais. O nosso foco durante esse tutorial é explicar quais são os passos no desenvolvimento de um componente Session Bean do tipo Stateless. Vale a pena salientar que o processo de criação de um componente Stateless Session Bean é muito semelhante para outros tipo de componentes (Stateful Session Bean ou Entity Bean).


Uma aplicação EJB possui o seguinte ciclo de desenvolvimento:



A primeira etapa do desenvolvimento de EJBs é a codificação do componente. Neste processo, escrevemos as interfaces Home e Remote e a classe que de fato implementa o Bean. Após a codificação destes, passamos por um processo chamado de build, que consiste em empacotar em um JAR (Java Application Archive) as classes e interfaces que compõem o componente e os seus deployment descriptors (arquivos de configurações).


Em aplicações J2SE temos também os processos de coidificação e build. Por exemplo, um sistema de controle de estoque é formando por um conjunto de classes e interfaces que quando compiladas podem ser empacotadas em um único arquivo JAR. Esse arquivo pode ser distribuído entre várias plataformas.


Em aplicações J2EE há um novo passo: o deployment da aplicação. O container precisa realizar uma série de processos administrativos para tornar o componente pronto para utilização. A geração de objetos EJBObject, a configuração do componente de acordo com seu deployment descriptor, o binding do componente no JNDI são alguns dos processos realizados durante o processo de deployment.

1. Codificação do Componente

No desenvolvimento de um Session Bean é preciso codificar duas interfaces:


  • A interface Remote que publica para os clientes quais serão os métodos capazes de serem chamados remotamente. Os clientes devem apenas conhecer essa interface Remota para se comunicar com o componente remotamente. Como veremos a seguir, nenhuma chamada é feita ao Bean de forma direta.
  • A interface Home publica o método de criação do EJB. Os métodos de criação de um EJB tem a assinatura "create()". Uma interface Home pode sobrecarregar vários métodos de criação e assim fornecer diversas formas de se criar um objeto (assim como fazemos com sobrecarga de construtores). Para Stateless Session Bean, no entanto, a interface Home deve conter apenas um método create() sem argumentos. Uma vez que objetos Stateless não mantêm estado, não faz sentido passar argumentos na sua criação.

Ao longo desse tutorial, desenvolveremos um componente que é chamado remotamente para efetuar o saque de uma conta corrente.


Convencionalmente, as classes que compõem o componente têm os seguintes nomes: Saque, SaqueHome e SaqueBean. Essas classes representam, respectivamente, a interface remote, a interface home e a classe bean.


Abaixo segue a implementação da classe Home do componente saque.


package br.com.j2eebrasil.artigos.ejb;

/**
* A interface Home controla o ciclo de vida do componente. É através dessa interface
* que criamos e destruímos o componente. No processo de lookup, sempre se procura pela

* interface Home para a partir dela criarmos um objeto remoto.
*
* @author Gleydson Lima
*/

import javax.ejb.EJBHome;
import java.rmi.RemoteException;
import javax.ejb.CreateException;


public interface SaqueHome extends EJBHome {

public Saque create() throws RemoteException, CreateException;

}


A interface Home controla o ciclo de vida do componente. Note que a implementação da interface do componente SaqueHome herda a interface EJBHome. Para cada método create() da interface Home, deve existir um método ejbCreate() correspondente na classe Bean. Assim, quando o método create() da interface Home é acionado pelo cliente o Container chama o método ejbCreate() da implementação do componente. No nosso exemplo, quando o cliente chama o metodo create() da classe SaqueHome, o container invoca o método ejbCreate() da classe SaqueBean.


O método create da interface Home retorna um objeto que implementa a interface Remota. O diagrama abaixo ilustra o uso da interface Home:



O Cliente faz o lookup do nome do componente no servidor de nomes (JNDI), o servidor de nomes procura pelo nome requisitado e retorna para o cliente um Stub para realizar chamadas remotas ao Home. O cliente chama o método create() no HomeStub, que chama o create no Home Remoto.


No processo de criação a implementação do Bean é notificado através do callback method ejbCreate().


Quando o objeto do Bean for criado, é retornado para o cliente um Saque_Stub que permite ao cliente fazer chamadas remotas ao SaqueBean.


De posse do Stub do componente Remoto, o cliente pode realizar chamadas ao componente. O código abaixo codifica a interface Remote do componente Saque:


package br.com.j2eebrasil.artigos.ejb;

/**
* A interface é o contrato de comunicação com o componente remoto.
* Somente os métodos declarados na interface remota podem ser chamados pelos clientes

* através de uma chamada remota.
*
* Essa interface deverá ser do conhecimento de todos os clientes que desejem
* acessar o componente EJB Saque.
*
@author Gleydson Lima
*/

import javax.ejb.EJBObject
;
import java.rmi.RemoteException;

public interface Saque extends EJBObject {

/* Método remoto que realiza o saque da conta do cliente */
public String sacar(double valor) throws RemoteException;


}


A interface Remota define quais métodos serão passíveis de chamada remota. A implementação do componente (SaqueBean) poderá ter quantos métodos desejar, mas passíveis de chamada remota, somente aqueles que estiverem na interface Remote. O diagrama de seqüência abaixo ilustra o processo de chamada:



O Saque_Stub é um objeto localizado no lado cliente, e através dele fazemos as chamadas remotas ao componente.


Uma das grandes vantagens do EJB, como dito em artigos anteriores, é o gerenciamento de diversos serviços de infra-estrutura por parte do Container. Ele gerencia transações, pooling de objetos (em especial conexões), persistência, recursos dentre diversos outros serviços. Para tal, o Application Server (ou Container) gera um conjunto de classes que implementam esses serviços (de acordo com a configuração definida nos deployment descriptors). Assim, para poder ter o controle da situação, o Application Server nunca permite a chamada direta à implementação do Bean. Ao invés disso, o cliente sempre chama um objeto Proxy gerado pelo Container que gerencia os serviços e realiza as chamadas desejadas na implementação do Bean.


É por isso, que a implementação do Bean não implementa a interface Remota, pois não há chamada direta àquela classe.


package br.com.j2eebrasil.artigos.ejb;

/**
* Implementação do Bean - Essa classe contém a implementação da lógica
* de negócio.
*
* @author Gleydson Lima
*/

import javax.ejb.SessionBean
;
import javax.ejb.SessionContext;

public class SaqueBean implements SessionBean {

SessionContext sc;

/** O método ejbCreate() será chamado quando for solicitado
* o método create na interface Home. Se existir necessidade

* de fazer algum codigo de inicialização do componente ele
* deverá estar no ejbCreate()
**/

public void ejbCreate() {
System.out.println("Objeto SaqueBean criado.");

}

/* Métodos da interface SessionBean */

public void ejbActivate() {
// Esse método nunca será chamado pois esse Bean será Stateless
}

public void ejbPassivate() {

// Esse método nunca será chamado pois esse Bean será Stateless
}

public void ejbRemove() {
System.out.println("Bean sendo removido");
}

public void setSessionContext(SessionContext sessionContext) {

sc = sessionContext;
}

/* Implementação do método da interface Remota */
public String sacar(double valor) {

// implementação do método de negocio
String retorno = "Foi solicitado um saque de " +

valor +
" ao componente SaqueBean";

return retorno;

}

}


O componente remoto Stateless Session Bean é uma classe que implementa a interface SessionBean. Como dito antes, a codificação do Bean não implementa a interface Remota Saque.


Os métodos ejbCreate(), ejbActivate(), ejbPassivate() e ejbRemove() são métodos callback. Eles são chamados pelo Container para notificar alguns eventos:


  • ejbCreate(): esse método é chamado pelo Container quando o cliente requisita a criação do componente através da interface Home.
  • ejbActivate() e ejbPassivate(): esses método são chamados apenas para os componentes do tipo Stateful Session Beans. Essas chamadas são feitas para notificar, respectivamente, os eventos de ativação e passivação do componente. Esses conceitos serão revistos e detalhados no tutorial sobre Stateful Session Beans.
  • ejbRemove(): Esse método é chamado pelo Container para notificar ao Bean que essa instância será removida.

2. Build do Componente

O próximo passo é o empacotamento do componente em um arquivo JAR. Esse processo envolve tipicamente a compilação do código Java criado anteriormente e a criação do arquivo JAR. Existem diversas ferramentas de automatização de build, uma das mais usadas atualmente é o ant (http://jakarta.apache.org/ant). Apesar de não ser o foco desse tutorial o uso da ferramenta Ant no desenvolvimento de aplicações J2EE, iremos disponibilizar aqui o arquivo build.xml usado para configurar essa ferramenta e iremos forcener instruções básicas para a sua utilização. Lembramos no entanto que é altamente aconselhável para o leitor conhecer essa ferramenta. O J2EEBrasil traz um tutoriail mais detalhado sobre essa ferramenta.


Para que possamos montar um pacote é necessário termos:


  • o código compilado (.class) das classes e interfaces que compõe os componentes
  • arquivos de configuração dos componentes (Deployment Descriptors).

3. Deployment Descritors

Os deployment descriptors são arquivos XML que descrevem os componentes. É através deles que podemos configurar o comportamento transacional, persistência, e diversos outros recursos providos automaticamente pelo Container.


Existem dois tipos de deployment descriptors, os portáveis e os específicos. Os deployment descriptors portáveis configuram genericamente o componente com comportamentos providos por todos os Application Servers. A mudança de Container não afeta a mudança desses descriptors.


A competição de mercado faz com que Application Servers diferentes possuam recursos e serviços variados. Não existe uma forma de prever quais são esses serviços, nem uma forma de configurá-los genericamente, uma vez que essa configuração varia de servidor para servidor. Dessa forma, existe também um deployment descriptors específico do Application Server.


O descriptor geral é armazenado em um arquivo no formato XML chamado ejb-jar.xml. É nesse descriptor que configuramos genericamente os componentes.


<?xml version="1.0" encoding="Cp1252"?>
<!DOCTYPE ejb-jar PUBLIC '-//Sun Microsystems, Inc.//DTD
Enterprise JavaBeans 2.0//EN' '
http://java.sun.com/dtd/ejb-jar_2_0.dtd'
>

<!-- Copyright 2002 Sun Microsystems, Inc. All rights reserved. -->

<ejb-jar>
<display-name>SaqueJAR</display-name>
<enterprise-beans>

<session>
<display-name>SaqueBean</display-name>
<ejb-name>SaqueBean</ejb-name>
<home>br.com.j2eebrasil.artigos.ejb.SaqueHome</home>
<remote>
com.j2eebrasil.artigos.ejb.Saque</remote>
<ejb-class> com.j2eebrasil.artigos.ejb.SaqueBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>

<security-identity>
<description></description>
<use-caller-identity></use-caller-identity>
</security-identity>
</session>
</enterprise-beans>

<assembly-descriptor>
<container-transaction>
<method>
<ejb-name>SaqueBean</ejb-name>
<method-intf>Remote</method-intf>
<method-name>*</method-name>

</method>
<trans-attribute>Required</trans-attribute>
</container-transaction>
</assembly-descriptor>
</ejb-jar>


O arquivo ejb-jar.xml acima traz várias configurações genéricas do componente. As <ejb-class>, tags <home> e <remote> informam onde estão a classe que representa o Bean e as interfaces Home e Remote desse componente.


Não há como especificar no código fonte, se o componente Session é do tipo Stateful ou Stateless, uma vez que os dois implementam a mesma interface. Essa configuração é feita no deployment descriptor através da tag <session-type>.


A tag <transaction-type> configura quem irá gerenciar o serviço de transação deste componente, podendo ser Bean ou Container. A primeira opção transfere para a implementação do Session Bean controlar a transação do componente através do uso da API JTA. Já a opção Container define que o Application Server irá gerenciar as transações deste componente, sem haver a necessidade do desenvolvedor se preocupar com esse serviço de infra-estrutura.


A tag <assembly-descriptors> configura os serviços providos por todos os Application Servers, como serviço de nomes, segurança, transações, persistência... No exemplo acima, essa tag descreve como será o comportamento das transações no Container.

O Container usado nesse exemplo é o JBoss (www.jboss.org). O deployment descriptor específico do JBoss é chamado jboss.xml. Mostrado abaixo:


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE jboss PUBLIC "-//JBoss//DTD JBOSS 3.0//EN" "http://www.jboss.org/j2ee/dtd/jboss_3_0.dtd
">

<jboss>

<enterprise-beans>
<session>
<ejb-name>SaqueBean</ejb-name>
<jndi-name>J2EEBrasilSaque</jndi-name>
</session>


</enterprise-beans>

<resource-managers>
</resource-managers>

</jboss>


Construído os deployment descriptors, estamos aptos a executar o build de nossa aplicação. De acordo com a configuração da ferramenta Ant usada nesse exemplo, devemos ter a seguinte estrutura de diretórios:



Dentro do diretório "src" encontram-se os códigos fontes do componente. O diretório "src/META-INF" contém os descritores. O diretório "build" é gerado pelo Ant em durante o build da aplicação. O código abaixo representa o arquivo build.xml (arquivo de configuração do Ant) que deve estar no diretório raiz da aplicação.


<?xml version="1.0"?>

<!-- ======================================================================= -->
<!-- Template build file -->

<!-- ======================================================================= -->

<project name="jspbrasiltutorial" default="main" basedir=".">

<property name="Name" value="J2eebrasilSaque"/>

<property name="version" value="1.0"/>

<property name="jboss.home" value="C://java//jboss-3.2.1_tomcat-4.1.24" />
<property name="jboss.configuration
" value="default" />
<property name="jboss.lib" value="${jboss.home}/server/${jboss.configuration}/lib" />

<property name="src.dir" value="${basedir}/src"/>

<property name="build.dir" value="${basedir}/build"/>
<property name="deploy.dir" value="${jboss.home}/server/${jboss.configuration}/deploy" />

<path id="
classpath.lib">
<pathelement location="${jboss.lib}/jboss-j2ee.jar" />
</path>


<!-- =================================================================== -->

<!-- Compila o codigo fonte -->
<!-- =================================================================== -->

<target name="compile">

<mkdir dir="${build.dir}"/>

<javac
destdir="${build.dir}"
debug="on"
deprecation="off"
optimize="on"

classpathref="classpath.lib"
>
<src path="${src.dir}"/>
</javac>
</target>

<!-- =================================================================== -->

<!-- Executa o build -->
<!-- =================================================================== -->

<target name="build" depends="compile">

<mkdir dir="${build.dir}/META-INF" />
<copy todir="${build.dir}/META-INF">
<fileset dir="${src.dir}/META-INF" includes="**" />
</copy>

<jar
basedir="${build.dir}"
jarfile="${basedir}/${Name}.jar" />
</target>

<!-- =================================================================== -->

<!-- Deploy in JBoss -->
<!-- =================================================================== -->

<target name="deploy" depends="build">

<copy todir="${deploy.dir}">
<fileset dir="${basedir}" includes="*.jar">
</fileset>
</copy>
</target>


<!-- =================================================================== -->
<!-- Main Target -->
<!-- =================================================================== -->


<target name="main" depends="deploy" />


<!-- =================================================================== -->
<!-- Cleans up the current build -->

<!-- =================================================================== -->

<target name="clean">
<delete dir="${build.dir}"/>
<delete file="${basedir}/${Name}.jar" />

</target>

</project>


Para executar o build utilizando o Ant a partir desse arquivo de configuração basta digitar "ant build" a partir da linha de comando. O resultado dessa operação é a criação do diretório build contendo os arquivos Java compilados, os arquivos XML e o arquivo Jar.

4. Deployment

O processo de deployment consiste simplificadamente em instalar o componente no Application Server. Esse processo é específico de cada servidores. Alguns deles possuem ferramentas próprias para efetuarem o deployment, outros possuem esquemas bem simples para efetuar a instalação de um novo componente.


Durante a instalação de um componente, o Container avalia os seus descritores para ativar os serviços configurados para aquele componente (transação, persistências, binding de objetos, etc). Possíveis erros nos descritores são identificados nessa etapa. Se o desenvolvedor, por exemplo, não informar as classes Home ou Remote de forma correta, o container irá cancelar o deployment do componente e exibir o erro para o desenvolvedor.


O processo de deployment no JBoss é bem robusto, basta copiar o arquivo JAR para o diretório deploy da configuração desejada. Normalmente, $JBOSS_HOMEserverdefaultdeploy. Assim, para efetuarmos o depployment de nossa aplicação, a única coisa que temos que fazer é copiar o arquivo Jar gerado no processo de build para o diretório citado anteriormente. Se você preferir, pode utilizar a ferramenta Ant para executar essa operação através da chamada na linha de comando "ant deploy".


A figura acima ilustra a saída do JBoss após a inslação do componente. Observe que vários passos são executados durante esse processo. O componente está correto e foi instalado com sucesso.



Vamos agora simular um erro nos descritores do componente e ver qual o efeito durante o processo de deployment no JBoss. Para construirmos esse erro, substituímos a interface SaqueHome por SaqueHomeQueNaoExiste no arquivo ejb-jar.xml. Veja código e imagem abaixo:


...
<session>
<display-name>SaqueBean</display-name>
<ejb-name>SaqueBean</ejb-name>
<home>br.com.j2eebrasil.artigos.ejb.SaqueHomeQueNaoExiste</home>

<remote>com.j2eebrasil.artigos.ejb.Saque</remote>
<ejb-class> com.j2eebrasil.artigos.ejb.SaqueBean</ejb-class>
<session-type>Stateless</session-type>

<transaction-type>Container</transaction-type>
<security-identity>
<description></description>
<use-caller-identity></use-caller-identity>

</security-identity>
</session>
...



É portanto, durante o deployment que o Containner verifica os arquivos de configurações do componenente. Possíveis erros são identificados nessa fase.

5. Codificando um Cliente

O cliente de um EJB precisa conhecer apenas as interfaces Home e Remota para comunicação com o Bean. O código abaixo implementa o cliente:


package br.com.j2eebrasil.artigos.client;

/**
*
* @author Gleydson Lima
*/

import javax.rmi.PortableRemoteObject;
import javax.naming.Context;
import javax.naming.InitialContext;

import br.com.j2eebrasil.artigos.ejb.SaqueHome;
import br.com.j2eebrasil.artigos.ejb.Saque;
import java.util.Hashtable;


public class SaqueCliente {

public static void main(String[] args) throws Exception {


Hashtable t = new Hashtable();
t.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
t.put(Context.PROVIDER_URL, "localhost");



Context ic = new InitialContext(t);
SaqueHome saqueHome = (SaqueHome) PortableRemoteObject.narrow(
ic.lookup("J2EEBrasilSaque"),
SaqueHome.class );


Saque saque = saqueHome.create();
System.out.println(saque.sacar(100.0));

}

}


O bloco em vermelho constrói as propriedades necessárias para conectar-se com o servidor JNDI. O ponto de entrada em um serviço de nomes é um contexto inicial. Para podermos nos conectar ao JNDI do JBoss precisamos dizer quem é a fabrica de contextos inicias através da propriedade
Context.INITIAL_CONTEXT_FACTORY. A propriedade Context.PROVIDER_URL especifica onde se encontra o servidor de nomes.


O InitialContext é requisitado e usado para executar um lookup pelo nome J2EEBrasilSaque. O trecho em azul representa a criação do objeto home. No processo de lookup de componentes EJB sempre é retornado um objeto Home.


A partir do Home podemos criar um componente remoto (método create). O trecho em verde mostra como usar o bean.

5. Conclusão

O desenvolvimento de um Session Bean envolve tipicamente três etapas: codificação, build e deploy. No primeiro passo, três arquivos Java são codificados: Interfaces Home e Remote, além da classe Bean. Convencionalmente, essas classes seguem a seguinte nomenclatura: SaqueHome, Saque e SaqueBean. Além desses arquivos Java, dois arquivos XML descrevem a configuração desses componentes. Esses arquivos são conhecidos como Deployment Descriptors. O segundo passo, build, consiste em construir um pacote JAR contendo o código Java compilado e os descritores do componente. O processo de deployment varia entre os Application Server e consiste em instalar o pacote gerado no Container.

Introdução a Enterprise JavaBeans - Parte 2

Autor: Gleydson Lima - gleydson at j2eebrasil.com.br


O componente EJB precisa interagir com o Container, seja para se comunicar com outros componentes EJB, para ser notificados de eventos ou obter informações sobre o contexto de execução.

Existem três formas de um componente interagir com o Container, são elas:


1. Métodos de Callback


Os métodos de callback informam ao Bean sobre os eventos do ciclo de vida do componente. Esses métodos oferecem ao bean a chance de fazer algum processamento relacionado com esses eventos. Os eventos variam de acordo com o tipo do Bean em questão.


2. JNDI (Java Naming and Directory Interface)

O JNDI é uma extensão da plataforma Java para acessar serviços de nomes e diretório como LDAP, NetWare, NIS, sistemas de arquivos, dentre outros. O componente pode acessar o JNDI para obter conexões com o banco de dados e acessar outros componentes EJB.


3. EJBContext

A interface EJBContext permite ao bean acessar algumas informações sobre container como a identidade do cliente, o estado da transação bem como obter referência própria.

Como acessar componentes EJB

Os clientes seguem uma padronização para acessar um componente EJB. A primeira coisa a ser feita é procurar pela interface Home em um serviço de nomes JNDI. Caso o Bean seja encontrado, uma referência remota para a interface Home é retornada. Através da interface Home o cliente pode criar o componente e ter acesso a interface Remota.


Os métodos de negócio do componente podem ser acessados a partir da interface remota. Como ilustra o diagrama abaixo:



Diagrama de seqüência do uso de um componente EJB

A figura acima pode ser dividas nos seguintes passos:

  1. getInitialContext() : Obtêm o ponto de acesso ao serviço de nomes (veja o tutorial de JNDI);
  2. lookup() : Procura pela interface Home do componente;
  3. create() : Solicita a criação do componente;
  4. newInstance(), setXXXContext() : Trabalhos feitos pelo Container;
  5. ejbCreate() : Método callback para informar ao Bean que foi solicitado uma criação;
  6. performTask : O método de negócio é solicitado ao EJBObject;
  7. performTask : O EJBObject repassa a chamada de negócio para a implementação do componente;
  8. remove : Chamada de um remove no componente
  9. ejbRemove : Método callback para informar que o bean será removido.

Exemplo de código de um cliente:

01. public class ClienteEJB {
02.
03. public static void main(String args[]) {
04.
05. Properties props = new Properties();
06. props.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory

");
07. props.put(Context.PROVIDER_URL, "jnp://localhost:1099");
08. Context ctx = new InitialContext(props);
09. PousadaHome home = PortableRemoteObject.narrow( ctx.lookup("ejb/PousadaBean"),

PousadaHome.class);
10. Pousada compNegocio = home.create();
11. System.out.println("Total de vagas:" + compNegocio.getVagas() );
12. home.remove();
13. }
14. }


O programa Java acima acessa um componente EJB chamado "PousadaBean". O primeiro passo é informar onde se localiza o servidor de nomes (linha


5. Um objeto Properties é construído com essas informações. Em seguida precisamos obter o contexto do servidor de nomes que foi estabelecido pelo Properties (linha 8).

Uma vez que o contexto foi obtido, o próximo passo é fazermos lookup pelo responsável pela criação do Bean - o Home, como mostrado na linha 9. A linha ctx.lookup("ejb/PousadaBean") faz a busca pelo Home do Bean no JNDI e o método PortableRemoteObject.narrow() faz as conversões necessários para trabalharmos com objetos IIOP(CORBA).


Criamos então um componente Pousada através da chamada home.create(), e logo após fazemos a chamada de seus métodos de negócio.

A linha 12 remove o componente do servidor.

Tipos de Componentes

A especificação do EJB 2.0 define três tipos de componentes:


1. Session Beans - Os Session Beans são componentes de negócio. A lógica de negócio dos componentes EJB se encontram nestes componentes. Existem dois tipos de Componentes Session Bean, o Stateless Session Bean e o Stateful Session Beans. O Stateless é um componente de negócio que não mantém conversação com o usuário, não há garantia que chamadas sucessivas de métodos remotos vão ser feitas no mesmo objeto. O Stateful é um componente que mantêm estado, com ele temos a garantia que chamadas sucessivas de métodos remotos feitas por um mesmo cliente serão processadas por um mesmo objeto.


2. Entity Beans - Entity Beans são componentes que representam entidades de negócio, como Cliente, Fornecedor, Gerente. Os dados das entidades se encontram em base de dados, e os componentes são responsáveis por realizar o mapeamento entre objetos de negócio e o banco de dados. Esses componentes facilitam o desenvolvimento uma vez que eliminam a necessidade do programador desenvolver código de persistência. O Container realiza a persistência e faz com que o desenvolvedor se concentre na lógica de negócio.


3. Message-Driven Beans - Message-Driven Beans são componentes ativados assíncronamente através de mensagens JMS. Os componentes Message-Driven Beans escutam uma determinada fila de mensagens e realizam algum processamento quando recebem algum dado da fila de mensagens.

Quais as vantagens de utilizar EJB?

Invocação remota de métodos Com a invocação remota de métodos podemos ter diversos clientes remotos nas mais diversas localidades.
Load Balancing Podemos ter diferentes servidores, e a cada chamada do cliente podemos balancear a carga entre os diversos servidores disponíveis.
Fail-over Quando um desses servidores der problema, devemos passar a chamar automaticamente outro servidor transparentemente para o cliente.
Transações O conceito de transação é muito importante para EJB. Com o conceito de transações, é possível acessar diversar base de dados e executar uma série de modificações, caso algum erro ocorra durante o processamente de alguma das tarefas solicitadas todo o processo é cancelado e o sistema volta ao estado inicial.
Clustering Para podermos ter tolerância à falhas, devemos replicar a aplicação entre os diversos servidores.
Threading O desenvolvedor de componentes EJB não precisa se preocupar com aspectos multitheading da aplicação. Como tratar diversos clientes? Como evitar deadlock entre as threads? Como sincronizar os objetos? Essas perguntas não devem ser respondidas pelo desenvolvedor uma vez que o Container é responsável pele tratamento dessas questões.
Suporte a MOM
(Message-oriented middleware)
Algumas requisições são baseadas em mensagens. A especificação EJB permite esse tipo de processamento através do Message-Driven Bean.
Ciclo de Vida do Objeto Quando o trafego aumente ou diminui os objetos para servi-los deverão ser criados e destruídos.
Gerenciamento de recursos Se o cliente não está mais conectado ao servidor, o servidor deve reutilizar ao máximo os recursos, retornando-os ao pool, marcando suas conexões como livre.
Segurança Podemos definir a segurança de um componente EJB simplesmente por configuração (segurança declarativa).
Caching O servidor de aplicações faz caching de componentes de Entidade de forma a otimizar o acesso ao banco de dados.


Muitos são os serviços gerenciados pelo Container EJB e que estão disponíveis ao desenvolvedor para o desenvolvimento de aplicações coorporativas escaláveis, seguras e transacionais.

Introdução a Enterprise JavaBeans - Parte 1

Autor: Gleydson Lima - gleydson at j2eebrasil.com.br


Os componentes EJB facilitam o desenvolvimento uma vez que eles tratam automaticamente a segurança, persistência, transação dentre outros serviços. Dessa forma o desenvolvedor não precisa se preocupar com a implementação programática desses serviços, a não ser que realmente deseje. Por ter essas facilidades, rapidamente o EJB tornou-se um padrão para desenvolvimento de aplicações coorporativas distribuídas e multicamadas.


Os componentes EJB não são acessados diretamente pelo cliente, como ocorre em RMI (Remote Method Invocation). A aplicação cliente requisita o acesso ao Container que por sua vez faz a chamada ao objeto EJB. O gerenciamento do ciclo de vida do Bean, o controle transacional, pooling, dentre outros aspectos são gerenciados pelo Container EJB. Todo componente EJB é executado dentro de um Container EJB.


A tecnologia Enterprise Java Beans é, portanto, um modelo de componentes do lado servidor. Por ser um modelo de componentes, ele deve seguir algumas regras durante o seu desenvolvimento. Existem interfaces responsáveis por tarefas definidas, regras de herança, dentre outros aspectos que devemos seguir durante a implementação de componentes EJB.

Modelo de componentes

O modelo de componentes define como criar componentes Enterprise JavaBeans, para isso precisamos conhecer alguns dos elementos mais importantes:


Interface Remota Na interface remota encontram-se os métodos que o componente vai publicar para chamada por clientes remotos.
Interface Home A interface Home define métodos para tratar do ciclo de vida do Bean, como criação, remoção e busca de componentes. É através da interface Home que o cliente obtêm a interface Remota do Bean.
Bean O Bean é onde se encontra a implementação da lógica de negocio do componente distribuído.


Imagine que temos um componente que trata algumas das atividades de uma Pousada, como por exemplo reservar quartos, solicitar total de vagas etc. Para desenvolvermos esse componente, precisamos de uma interface do tipo Home (responsável pelo ciclo de vida) e uma outra do tipo Remote (responsável pela efetivação dos métodos de negócio). Essas interfaces necessitam seguir o seguinte diagrama de classes:



A interface Pousada (interface Remota) deve herdar da interface javax.ejb.EJBObject que por sua vez herda de java.rmi.Remote. Todas as interfaces que definem chamadas remotas devem herdar da interface java.rmi.Remote.


A interface Home herda de javax.ejb.EJBHome.


import javax.ejb.EJBObject;
import java.rmi.RemoteException;

public interface Pousada extends EJBObject {
public int getVagas() throws RemoteException;

public int getTotalHospedes() throws RemoteException;


public void reservar(Reserva hospede) throws RemoteException;
}


A interface Remota Pousada define os métodos de negócio do componente. Nesse exemplo, este componente possui três métodos de negócio que podem ser chamados remotamente.


A interface Home define agora como podemos criar o componente Pousada, como é mostrado abaixo:


import javax.ejb.EJBHome;
import java.rmi.RemoteException;

public interface Pousada extends EJBHome {
public void create() throws RemoteException;


}


O componente pode ser criado através do método create() sem argumentos. Porém, poderíamos ter componentes (aqueles que mantêm estado) que desejássemos iniciar algumas variáveis, e a definição da assinatura do método create() seria importante.


O Bean possui a implementação da lógica de negócio. Como mostramos abaixo:


import javax.ejb.*;
import java.rmi.RemoteException;

public class PousadaBean implements SessionBean {

private javax.ejb.SessionContext context;

public void setSessionContext(javax.ejb.SessionContext
aContext) {

context=aContext;

}

public void ejbActivate() {
/* Esse método é chamado pelo EJB Container para
notificar que esse Bean foi ativado */
}


public void ejbPassivate() {

/* Esse método é chamado pelo EJB Container para notificar
que esse Bean foi passivado */
}

public void ejbRemove() {

/* Esse método é chamado pelo EJB Container para notificar

que esse Bean vai ser removido */
}

/* implementação do create definido na interface Home.

public void ejbCreate() {
System.out.println("Bean Criado");
}


/* Implementação dos métodos de negócio */

public int getVagas() {
// Implementação do método getVagas()
}
public int getTotalHospedes() {
// Implementação do getTotalHospedes

}


public void reservar(Reserva hospede) {
// Implementação do método reservar
}
}


Note que a codificação do Bean não implementa a interface Remota. Isto ocorre porque o cliente não chama diretamente a implementação do Bean, existe um outro objeto que o cliente se comunica diretamente e que repassa para o Bean como mostra a figura abaixo:



Alguns métodos foram declarados com o prefixo ejb. Esses métodos são os denominados callback methods. Eles são chamados para notificar a instância do Bean sobre algum evento que aconteceu, como criação, ativação, remoção, dentre outros eventos que serão visto com mais detalhes em outros artigos/tutoriais.

Deployment Descriptors

Os Deployment Descriptors são arquivos XML que permitem configurar os componentes EJB antes de serem implantados, possibilitando realizar ajustes sem a necessidade de alterar o código fonte. Essa flexibilidade na utilização dos componentes é importante uma vez que o mesmo componente EJB pode ter diferentes configurações a depender de sua utilização. Os deployment descriptors configuram os serviços usados pelos componentes EJB, tais como: segurança, controle transacional, persistência de dados, dentre outros.


Abaixo temos um exemplo de um deployment descriptor:


<?xml version="1.0" encoding="UTF-8"?> 

<!DOCTYPE ejb-jar PUBLIC '-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN'
'
http://java.sun.com/dtd/ejb-jar_2_0.dtd'
>

<ejb-jar>
<display-name>PousadaBean</display-name>
<enterprise-beans>
<session>
<display-name>PousadaBean</display-name>

<ejb-name>PousadaBean</ejb-name>
<home>PoousadaHome</home>
<remote>Pousada</remote>
<ejb-class>PousadaBean</ejb-class>
<session-type>Stateless</session-type>

<transaction-type>Bean</transaction-type>
</session>
</enterprise-beans>

</ejb-jar>


Esse documento XML descreve a configuração do Componente PousadaBean. No deployment descriptor se diz qual o tipo do Bean, sua interface Home e Remota, seu modelo de transação, dentre diversas outras informações que não foram mostradas por motivo didático.

Processo de Deployment

O processo de deployment é a implantação do componente no servidor de aplicações. É no processo de deployment que o Container EJB irá ler os deployment descriptors da aplicação e implantá-la com as características desejadas.


O processo de deployment varia de servidor para servidor, não havendo uma regra universal para sua realização. Depois desse processo, o componente está pronto para receber solicitações.


Ajax vai desifentar o Flash?

Autor: Frederick van Amstel - About:<http://www.usabilidoido.com.br/cat_sobre_o_autor.html> - Contato: <http://www.usabilidoido.com.br/cat_contato.html>


Uma novo jeito de fazer aplicações na Web está ficando popular e ameaça tomar o lugar do Flash e suas Rich Internet Applications.


Antigo comercial do lava-roupas Ajax


Ajax é um xunxo (gambiarra) no Javascript do HTML que permite atualizar informações numa página sem precisar recarregar a página. Apesar do recurso estar disponível há anos, parece que só agora descobriram ele.


Quicou uma bola nova no campo e os futebolistas de plantão correm como loucos pra ver quem será o primeiro a chutá-la. E chuta pra cá e chuta pra lá, não querem nem saber se é de basquete ou pingue-pongue, o negócio é experimentar. De vez em quando, de tão afoitos, chutam na torcida.


O gol fica lá, criando teia.


A torcida vaia, mas eles não ouvem. Perguntar se eles estão gostando? "Imagina, claro que estão! Se eu estou gostando, eles também estão," dizem para si mesmos os jogadores.


Bizarro?


Foi mais ou menos assim que começou o futebol, mais de um século atrás. O mercado Web está começando agora, mas ao invés de aprender com o passado, só quer saber do futuro.


Volta e meia, começa uma nova onda tecnológica e surgem fóruns, sites, livros e etc . Ou você vai atrás, ou é considerado atrasado. Estou escrevendo esse post porque fui pressionado pelos meus leitores: "e aí, não vai comentar o tal de Ajax?"


A última é a onda que ainda não atingiu o apogeu no Brasil é o tableless, que conta inclusive com uma tendência de design , já comentada aqui antes. Se continuar como sempre, seguindo os estadunidenses com dois anos de atraso, o Ajax deve bombar no Brasil só depois de 2007, quando os estadunidenses já tiverem descobrido que o Ajax também tem suas desvantagens e não só vantagens, como vêem agora. Então, devemos ter um


Ajax maduro aqui lá por 2009.


Não precisamos esperar tanto. Se desde o início, formos críticos diante de tecnologias como o Ajax, estaremos inclusive na frente dos estadunidenses que, pelo fato de serem os criadores dessas tecnologias, ficam ainda mais enfeitiçados.


A Isabel já falou sobre as vantagens que o Ajax pode trazer para a usabilidade de um website, porém, como tudo na vida, sempre há as contra-indicações.


Todos os problemas do Ajax decorrem do fato de que páginas são páginas, não ambientes de desenvolvimento. Navegadores não foram feitos para rodar aplicações, muito menos para debugá-las. Javascript é uma linguagem feita às pressas e é interpretada diferentemente por cada navegador.


Usuários estão acostumados a navegar por páginas dentro de um navegador e não se sentem muito à vontade para operar uma aplicação ali dentro.


Vejamos alguns exemplos de novidades com Ajax. Detalhe importante: meu navegador é o Opera 8, o navegador mais inovador do mercado. Se Ajax é moderno, então tem que funcionar nele.


Abas dinâmicas


Tabtastic é um experimento de abas dinâmicas, que mudam seu conteúdo sem carregar novas páginas. É como se ao clicar num item de menu, a nova página abrisse instantaneamente.


Vantagem: não precisa esperar carregar uma nova página


Desvantagens:

  • botão voltar do navegador não funciona
  • posição de rolagem inconsistente em cada página, causando desorientação

Yahoo Mindset: ordene as buscas


Yahoo Mindset é uma busca que permite ordernar os resultados de acordo com seu objetivo: comprar ou pesquisar. Claro que o usuário pode ter muito mais objetivos do que esses dois, mas trata-se apenas de um experimento do laboratório do Yahoo que pesquisa como ensinar algoritmos a serem mais inteligentes.


Vantagem: o usuário pode filtrar o que interessa mais rapidamente do que se tivesse que refinar a busca ou passar de página em página


Desvantagens:

  • a bolinha de controle não pode ser arrastada como em outros controles deslizantes (sliders) só porque os desenvolvedores acharam melhor usar uma animação suavizando o movimento (e mostrando como eles são bons nisso)
  • no screenshot fiz uma busca pelo último nome do compositor clássico Bach e defini que meu objetivo é pesquisa e ainda assim aparecem os links patrocinados que tentam me vender algo
  • se escolho meu objetivo antes de começar uma nova busca (uma ação bastante lógica), o marcador volta pro meio


Já me peguei diversas vezes no Google digitando uma palavra-chave e só depois clicando na aba de busca por imagens. Antigamente, na nova página que abria não constava o que já tinha digitado, agora pelo menos o termo continua. No Yahoo quando se clica na aba, ela muda instantaneamente.


Vantagens:

  • a mudança drástica de cor avisa o usuário que algo aconteceu depois que ele clicou na aba, pois ele esperava que abrisse uma nova página
  • permite que o usuário acesse

Desvantagens:

  • links levam à novas páginas, botões realizam ações instantâneas. Esse problema seria resolvido se as abas tivessem relevo e fossem ativadas só passando o mouse por cima, como faz o portal Verdes Mares

No Yahoo News, ao clicar num hiperlink no corpo do texto, abre-se imediatamente uma caixa dentro do próprio texto que retorna notícias que contenham a palavra hiperlinkada. Na captura acima, cliquei no hiperlink CIA. Depois dessa tela, apareceram os resultados:


Vantagens

  • não sai do contexto
  • o usuário pode criticar a funcionalidade clicando em "Got feedback?"
  • permite fazer busca por imagens ou pela Web


Desvantagens

  • surprende o usuário acostumado a clicar em links e ir pra outras páginas, podendo causar desorientação
  • difícil voltar ao estado anterior ao clique
  • não tem uma borda em volta delimitando o que faz parte da busca e o que é a continuação da matéria
  • nem sempre os resultados da busca são relevantes


Neste blog, coloquei na busca um script que faz sugestões de termos, de forma parecida com o Google Suggest. Os termos que são sugeridos são as palavras-chave dos posts definidas pelo autor e pelos leitores (veja no fim do post).


Vantagens:

  • previne o usuário contra erros de digitação e informa os termos preferidos antes mesmo dele buscar
  • economiza digitar


Desvantagens:

  • não permite usar as setas pra cima e pra baixo do teclado, como outros campos com intellisense do navegador (o nome desse padrão)
  • retorna uma lista de itens com baixa relevância quando o número de letras é pequeno
  • não faz sugestões de termos com duas palavras


Alguns amigos abandonaram o Outlook para usar o Gmail porque ele é mais rápido e prático de usar. Em geral aplicações Web são mais lentas que de desktop, mas realmente não é o caso do Gmail. Uso o Gmail só para receber as listas de email e funciona extremamente bem, melhor do que num cliente de email desktop. Porém, ainda prefiro o Thunderbird para gerenciar minhas contas principais.


Vantagens

  • maior velocidade de carregamento
  • funcionalidades que agilizam a manipulação dos emails


Desvantagens

  • não funcionava no Opera até alguns meses atrás
  • demora mais pra carregar no início


Na imagem acima, vemos fotos tirada por satélite da cidade de São Paulo e mostradas pelo Google Maps. Você digita o endereço e ele mostra o local, seja num mapa, seja na foto.


Vantagens

  • permite navegação fluida, sem sair da tela
  • permite salvar as imagens do mapa


Desvantagens

  • demora muito para atualizar uma tela nova
  • mensagens de erro que não avisam se a localidade não está disponível no sistema

Mais exemplos de Ajax, você encontra no Ajax Patterns.

Conclusão

O que todos esses exemplos tem em comum? Todos tentam melhorar a experiência do usuário diminuindo o tempo de resposta do sistema. Clicou, abriu. Alguns deles abre sem nem precisar clicar. O problema é que o usuário está acostumado a esperar pelo carregamento de uma nova página a cada vez que dá um clique. Então, se não houver uma dica visual de que algo está acontecendo ou já aconteceu, a resposta pode passar desapercebida e o usuário pode ficar se perguntando porque nada aconteceu. Luke Wroblewski dá algumas dicas de como fazer isso.


E o Flash? Onde entra nessa história toda? Bem, até antes de surgir o Ajax, o Flash era a ferramenta mais indicada para dar esse tempo de resposta instantâneo. Porém, com Ajax não dá pra fazer tudo que o Flash faz. Em 2003, escrevi um artigo pro Webinsider anunciando as Rich Internet Applications e levantei algumas vantagens que serão usadas na tabela comparativa abaixo:


Vantagens pro usuário Flash Ajax
tempo de resposta menor + +
atualização em tempo real + +/-
atalhos no teclado + +/-
elementos gráficos mais leves + -
interface mais compacta + +
interface animada + +/-
suporte a áudio/vídeo + -
acessibilidade +/- +
graceful degradation - +
não precisa de plugin - +


Vantagens pro desenvolvedor Flash Ajax
designers definem a aparência direto na ferramenta de desenvolvimento + -
maior flexibilidade para desenvolver interfaces inovadoras + -
linguagem de programação fácil de aprender + -
reduz a carga do servidor + +
boa ferramenta de produção + -


E então Ajax vai ou não vai desinfetar o Flash? Não já já, mas se a Adobe bobear, é possível. A grande vantagem do Ajax é que ele atende aos padrões da W3C e, consequentemente, oferece maior acessibilidade e indexabilidade do que o Flash. A grande desvantagem a meu ver, é a falta de ferramentas de produção como tem o Flash, mas isso é uma questão de tempo para surgir.


Porém, mesmo que o Ajax vença o Flash na disputa pelas Rich Internet Applications, este não vai desaparecer. No seu nicho original, experiências multimídia na Web, ele ainda é imbatível.


Auto-completar Ajax

Autor: Elcio Ferreira <http://elcio.com.br/ajax/autocompletar>

Algumas pessoas tem escrito perguntando como se produz um efeito semelhante ao Google Suggest. Esta série de artigos e o script que a acompanha são uma maneira de tentar responder a esta dúvida.

Exemplo do efeito desejado:

O script

Embora a idéia original seja bastante simples, o controle de eventos do teclado é bastante complexo e exige um bocado de código, além de um bom conhecimento de DOM. Além disso, é muito interessante que esse tipo de coisa seja produzida no formato de um script reaproveitável, o que exige uma série de outros conhecimentos que tornam o código complexo demais para um artigo simples.

Assim, resolvi escrever sobre algumas coisas:

  1. Como usar este script para implementar um recurso de auto-completar em seu site.
  2. Como personalizar este recurso.
  3. Como escrever um script como este, que trata eventos do navegador, inclusive do IE bugado.
  4. Como escrever código ajax usando JSON, uma das maneiras mais práticas de se fazer ajax.
  5. Como escrever código javascript que seja facilmente reaproveitado.

Como usar este script

Tentei construir um script que você possa reaproveitar sem ter o trabalho de entendê-lo todo. Nas partes posteriores desta série de artigos vamos entender este script passo a passo, e pretendo dar dicas de como construir código reaproveitável como este. Então vamos começar analisando o resultado, isto é, aproveitando este código numa página para ver como será a experiência de quem quiser usá-lo sem entendê-lo.

Para começar, copie para seu site os arquivos:

Em seguida inclua estes arquivos na seção head do seu HTML, assim:

<link rel="stylesheet" href="css/autocompletar.css" />
<script src="js/events.js"></script>
<script src="js/xmlhttp.js"></script>
<script src="js/autocompletar.js"></script>

Seu formulário HTML precisa ter a class autocompletar e o campo de formulário que vai ser preenchido terá o id completeaqui. Defina então a largura do seu campo de formulário junto com a da caixa de sugestões, no CSS:

.completeaqui,div#completando{
width:300px;
}

Fazendo a busca via Ajax, com JSON

A maneira mais simples de usar este script é fazê-lo buscar os dados do servidor via Ajax, no formato JSON. Para isto, basta fazer sua página PHP, ASP ou seja lá o que estiver usando, retornar um Array de strings formatado em JSON. (Vou falar mais de JSON na quarta parte desta série.)

Veja um exemplo disso na página python que estou usando neste tutorial: ap, fi. É esta página que meu script vai buscar.

window.onload=function(){
ac_registraJSON(document.forms[0],"q","busca.pt?q=")
}

Onde "busca.pt?q=" é o endereço de onde esse script vai buscar os dados. O primeiro argumento (document.forms[0]) é o formulário que contém o campo, e o segundo ("q") o nome do campo.


ANEXO 1: <script src="js/events.js">

/*
Tratamento de eventos crossbrowser
Baseado em http://simon.incutio.com/archive/2003/11/06/easytoggle
Elcio Ferreira - 2004 - http://elcio.locaweb.com.br
*/

function addEvent(obj, evType, fn){
if(obj.addEventListener)obj.addEventListener(evType,fn,true)
if(obj.attachEvent)obj.attachEvent("on"+evType,fn)
}


function getSource(e){
if(typeof e=='undefined')var e=window.event;
var source=typeof e.target!='undefined'?e.target:typeof e.srcElement!='undefined'?e.srcElement:true
if(source.nodeType == 3)source=source.parentNode;
return source
}

ANEXO 2:<script src="js/xmlhttp.js">
try{
xmlhttp = new XMLHttpRequest();
}catch(ee){
try{
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
}catch(e){
try{
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}catch(E){
xmlhttp = false;
}
}
}

ANEXO 3: <link rel="stylesheet" href="css/autocompletar.css" />
form.autocompletar{
position:relative;
top:0;
left:0;
}
div#completando{
position:absolute;
top:1.5em;
left:0px;
background:white;
}
div#completando ul{
margin:0 1px;padding:0;
border:1px solid black;
list-style:none;
}
div#completando li{display:inline}
div#completando a{
display:block;
padding:1px 5px;
}
div#completando a:hover,div#completando li.selecionado a{
background:blue;
color:white;
}

ANEXO 4:<script src="js/autocompletar.js">
//Variáveis Globais
ac_idx=0
ac_old=""
ac_showing=false

//Registra o autocompletar
function ac_registra(formulario,inputname,funcao){
ac_campo=formulario.elements[inputname]
addEvent(ac_campo, "keyup", ac_up)
addEvent(ac_campo, "keypress", ac_mudou)
addEvent(ac_campo, "focus", ac_focus)
addEvent(ac_campo, "blur", ac_blur)
ac_pegaLista=funcao
}
//Registra o autocompletar com um endereço Ajax/JSON
function ac_registraJSON(formulario,inputname,endereco){
ac_JSON=endereco
ac_registra(formulario,inputname,ac_getJSON)
}

//Função para obter o JSON
function ac_getJSON(t,func){
ac_f=func
xmlhttp.open("GET", ac_JSON+escape(t),true);
xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState==4)
ac_f(eval(xmlhttp.responseText))
}
xmlhttp.send(null)
}

//Monta a lista a partir de um Array
function ac_fazLista(t){
ac_Lista=t
var ret="<ul>"
for(var i=0;i<ac_Lista.length;i++)
ret+="<li"+(i==ac_idx?' class="selecionado"':'')+
"><a href='javascript:ac_completa("+i+")'>"+
ac_getHTML(ac_Lista[i])+"</a></li>"
ret+="</ul>"
document.getElementById("completando").innerHTML=ret
}

//Obtém o texto do item da lista
function ac_getText(i){return typeof(i)=="string"?i:i[1]}
//Obtém o HMTL do item da lista
function ac_getHTML(i){return typeof(i)=="string"?i:i[0]}

//Atualiza a lista de acordo com o conteúdo do campo
function ac_mudado(){
ac_texto=ac_campo.value
if(ac_old!=ac_texto)ac_idx=0
ac_old=ac_texto
setTimeout('ac_pegaLista(ac_texto,ac_fazLista)',100)
}

//Esconde a lista
function ac_some(){
ac_showing=false
try{document.getElementById("completando").style.display="none"}catch(e){}
}

//Mostra a lista
function ac_aparece(){
ac_showing=true
try{
document.getElementById("completando").style.display="block"
}catch(E){
var d = document.createElement("div");
d.setAttribute("id","completando")
ac_campo.parentNode.appendChild(d)
}
}

//Clique no completar
function ac_completa(l){
try{
ac_texto=ac_campo.value=ac_Lista[l]
ac_campo.focus()
setTimeout('ac_aparece()',110)
ac_mudado()
}catch(e){}
}

//Controla o índice do item selecionado
function ac_chItem(kCode){
ac_idx+=kCode-39
if(ac_idx<0)ac_idx=ac_Lista.length-1
if(ac_idx>ac_Lista.length-1)ac_idx=0
ac_mudado()
}

/* Eventos no textbox: */
//KeyPress
function ac_mudou(e){
if(e.keyCode==40 || e.keyCode==38 || e.keyCode==13){
if(e.keyCode!=13){
if(!ac_showing)ac_aparece()
ac_chItem(e.keyCode)
}else{
if(ac_Lista[ac_idx]==ac_campo.value || ac_Lista.length==0)return true
if(ac_showing)ac_completa(ac_idx)
else return true
}
if(e.preventDefault)e.preventDefault()
return false
}
if(e.keyCode==27)ac_some()
setTimeout('ac_mudado()',1)
}
//Tratando eventos no IE bugado
function ac_up(e){
if(typeof e.target=="undefined" && (e.keyCode==40 || e.keyCode==38 || e.keyCode==8))ac_mudou(e)
}

//Focus
function ac_focus(e){
ac_aparece()
ac_mudado()
}
//Blur
function ac_blur(e){setTimeout('ac_some()',100)}

Deixe seu windows xp mais Rapido


Seu menu Iniciar mais rápido:
Navegue para HKEY_CURRENT_USERControl PanelDesktop . Selecione MenuShowDelay na lista da direita. Lá vai estar com o valor 400, coloque 0.

Acelerando a inicialização da Restauração do Sistema
Clique em Iniciar > Programas > Acessórios > Ferramentas do Sistema ;
Clique com o botão direito em Restauração do Sistema > Propriedades ;
No campo Destino está a linha de comando que chama a Restauração do Sistema:
%SystemRoot%System32restorerstrui.exe
Altere-a de modo que fique assim:
%SystemRoot%System32restorerstrui.exe /prefetch:1
Clique em OK para confirmar.

Acelere os programas :
A Microsoft usa a chave /prefetch:1 para acelerar a carga do Windows Media Player . Esta mesma chave pode ser utilizada para outros programas Microsoft Windows ou de terceiros.
Inclua esta chave logo após a linha de comando de carga do programa, em Propriedades => Objeto.
Ex.: Para fazer com o IE6, inclua a chave após o comando, ficando assim "
C:Arquivos de
ProgramasInternet ExplorerIEXPLORE.EXE" /prefetch:1


Ajustar a prioridade de processamento:
Vá em Iniciar /Executar digite regedit e clique em OK
Navegue até a chave
[HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlPriorityControl ]
E modifique o valor da chave " Win32PrioritySeparation "
O valor padrão é "2 " Decimal

Os valores que podem ser utilizados são :
0 = Iguala o nível de processamento entre Programas e Serviços em Background
1 = Prioriza aos Serviços em BackGround
2 = Prioriza os Programas


Internet Explorer mais rápido :
Internet Explorer a pesquisar por tarefas agendadas sempre que é aberto. Você pode eliminar esse problema encontrando o seguinte item do registro:
HKEY_LOCAL_MACHINESoftwareMicrosoftWindowsCurrent VersionExplorerRemoteComputerNameSpace
Encontre então na coluna da direita a chave ClassId key {D6277990-4C6A-11CF-8D87-00AA0060F5BF } e a delete simplesmente. Saia então do registro e abra o Internet Explorer. Observe a diferença!


Rapidez de acesso a programas e arquivos.
Este truque aplica-se a qualquer versão do Windows. Através dele nos permitirá , sobretudo quando a utilização do disco rígido é muito freqüente , um acesso mais rápido a arquivos e programas.
Iniciar > Executar > regedit
Navegue até HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlFileSystem e criamos um dword
valor ( Edit/New/Dword Value) . Renomeamos com o nome de ContigFileAllocSize . Duplo-clique sobre o mesmo e digitamos o valor de 200 em hexadecimal ( 512 em decimal ).
Feche o Editor do Registro


Pastas abrindo muito rápido :
Iniciar > Executar > digite: system.ini e encontre a chave [386nh ]coloque o cursor na frente da chave e de enter, abrirá uma linha, nesta linha digite:
conservativeswapfileusage=1

Liberando espaço :
O Windows reserva 12,5% do espaço livre no HD para o MFT (Master File Table ). Se você tem uma quantidade muito grande de arquivos e programas no computador, a utilização do MFT é alta. Será então útil aumentar aquela porcentagem de uso para 25% . Para fazer isso encontre no HKEY_LOCAL_MACHINESystemCurrentControlSetControlFileSystem . No painel da direita, adicione (se não existir) a chave com o nome NtfsMftZoneReservation dando ao REG_DWORD o valor 2 . O valor 1 é interpretado pelo Windows como 12,5% (padrão de instalação) e o valor 2 como 25%.

Acelerando o boot do XP navegue no regedit até:
HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlSession ManagerMemory ManagementPrefetchParameters
Altere o valor "EnablePrefetcher " para "1 " ficando assim:
"EnablePrefetcher "=dword:00000001


Liberando mais poder de processamento :
Vá em INICIAR e selecione EXECUTAR... Digite o comando:
Rundll32.exe advapi32.dll,ProcessIdleTasks


Desligar mais rápido :
Dê um passeio até a chave HKEY_CURRENT_USERControl PanelDesktop
Chegando lá, encontre o valor HungAppTimeout que deve estar em 5000 (padrão). Se não estiver, coloque. Por aí mesmo, procure o valor WaitToKillAppTimeout . Troque o valor para 1000 (o padrão
é 20000).
Depois, dê um passada em
HKEY_LOCAL_MACHINESystemCurrentControlSetControl
e troque o valor de WaitToKillServiceTimeout para 1000 também.
Pra finalizar execute o arquivo gpedit.msc vá até Modelos Administrativos, pule para Sistema e depois Perfis de Usuário. Do lado direito da tela aparece a opção Número máximo de tentativas para descarregar e atualizar perfil de usuário. Ative-o e atribua o valor 0 .


Isto faz o computador ficar ligeiramente mais rápido :
Iniciar > Executar e digite: system.ini e aperte ok
Copie essa linha abaixo:
32BitDiskAccess=on
32BitFileAccess=on
DMABufferSize=64
MinSPs=16
PageBuffers=32

5. e cole embaixo da escrição [386enh ]
6. não deixe espaços entra as linhas .
Reinicie o computador.
É o seguinte, eu vou explicar para vocês,


Navegue mais rápido :
Tanto o Windows XP como o Windows 2000 possuem um recurso (Agendador de pacotes QoS ) que "reserva " 20% da banda disponível de rede e Internet para uso próprio, o que para a maioria dos usuários não é necessário. Para recuperar esses 20% de banda, siga esses passos:
Iniciar > Executar , digite: gpedit.msc e pressione ok.
Configuração do computador > Modelos Administrativos > Rede
Selecione, na janela esquerda, "Agendador de pacotes QoS ". Na janela da direita, dê duplo-clique na em " Limite de reserva de banda ".
Na aba Configuração, selecione Ativado. Na linha "Limitar % da banda", digite 0 (zero). Clique em Aplicar , OK e saia.
Vá nas configurações da rede (Painel de Controle > Conexões de Rede ), clique com o botão direito na conexão existente, selecione Propriedades . Na aba Geral, habilite o Agendador de Pacotes QoS (se já estiver habilitado, deixe como está).
Reinicie o computador.
Obs: Se houver mais de um computador em rede, é preciso seguir os passos acima para todos.


Liberando espaço no HD :
O Windows XP usa WFP (Proteção de Arquivos do Windows ). Isso significa que se algum arquivo de sistema for substituído de forma não autorizada por você ou por algum programa, o Windows recupera a versão anterior do arquivo. Mas para poder fazer isso ele armazena em cache todas as .dll e outros arquivos de sistema na pasta System32/dllcache (ocult o). E isto custa alguns bons megabytes no seu disco (chega a mais de 300MB ). Aqui está o que pode ser feito para não perder tanto espaço: Abra uma janela de prompt e digite, sem as aspas, "sfc /cachesize=x " ondeo x é a quantidade em MB que você deseja reservar para o cache do Windows, 50MB seria um bom tamanho. Agora podemos fazer uma outra coisa: eliminar todos os arquivos armazenados no cache, que estava exageradamente grande. Para isso digite no prompt sem as aspas: " sfc /purgecache ".
Você vai notar uma intensa atividade no HD. Significa que uma infinidade de arquivos do cache estão sendo deletados. Não se preocupe, se mais tarde o Windows vier a precisar de algum delese não o encontrar no cache, pedirá que você insira o CD de instalação e o encontrará no CD.


Sabe aquelas barrinhas azuis que ficam passando no processo de boot do XP? Isto vai fazer com que as mesmas passem um ou duas vezes:
1. Abra o bloco de Notas.
2. Digite "del c:windowsprefetchntosboot-*.* /q " (sem as aspas, evidentemente )
3. Salve este arquivo com o nome ntosboot.bat (o nome fica seu critério ) na raiz.
4. Execute o gpedit.msc
5. Vá em Configurações do Computador , e depois em Configurações do Windows . Do lado direito da tela clique no item Scripts (Inicialização/Encerramento).
6. Clique duas vezes em Desligar .
7. Na janela que se abre clique em adicionar e depois procurar .
8. Encontre e selecione o arquivo que você criou lá em cima, no caso o ntosboot.bat .
Selecione-o e dê todos os OKs que tiver que dar.
9. No menu "Iniciar , selecione "Executar " & digite "devmgmt.msc ".
10. Clique duas vezes em "Controladores IDE ATA/ATAPI "
11. Clique com o botão direito em "Canal IDE primário " e selecione "Propriedades ".
12. Selecione a aba "Configurações avançadas " depois, no dispositivo 0 ou 1 (aquele que não tiver o campo "Tipo de dispositivo " travado) selecione nenhum ao invés de "Detecção automática " & click "OK".
13. Clique com o botão direito em "Canal IDE secundário ", selecione "Propriedades " e repita o
passo 12.
14. Reinicie o computador.


Descarregando dll depois de fechar programas :
Você e eu sabemos que nenhum Windows, por mais estável que seja, libera toda a memória que era ocupada por um aplicativo quando ele é fechado. Sempre fica uma DLL esquecida na memória, o que torna praticamente impossível não ter que reiniciar o computador para o micro ficar mais leve após uma sessão mais hardcore de Office, por exemplo.
Para obrigar o WindowsXP a descarregar da memória todas as DLLs que não estão em uso, dê uma espiada em: HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionExplorer
Chegando lá, você vai ter que criar uma nova chave chamada AlwaysUnloadDLL . Como criar uma nova chave, você vai me perguntar. Simples, respondo eu. Clique com o botão direito do mouse na chave Explorer, aponte para Novo , depois Chave . Uma nova chave vai ser criada dentro do item Explorer (vai parecer uma pasta nova ). Renomeie-a para AlwaysUnloadDLL e troque o valor Padrão para 1 invés de 0 .


Melhorando o comportamento do HD :Veja se o seu disco rígido está habilitado para uma melhor performance.
Iniciar > Painel de Controle > Sistema > Gerenciador de Dispositivos > Controladores IDE/ATAPI >
Canal IDE Primário (e secundário também, se for o caso) > Configurações Avançadas > Em Modo de Transferência , selecionar "DMA se disponível ".
Isso fará com que ele trabalhe mais rápido.

Lixeira ou Lixão?
O Windows reserva 10% do espaço de seu disco rígido para a Lixeira.
Isso é um desperdício, se você tiver 20Gb no seu Hd 2Gb estão reservados para sua lixeira, para que tanto?
Para diminuir o espaço alocado para sua lixeira, clique com o botão direito do mouse na lixeira e escolha um tamanho
menor, 1% está de bom tamanho.