Stateful Session Beans
Carrinho de compras
corporativo
Ricardo Cavalcanti
[email protected]
Jobson Ronan
[email protected]
Por que?

Quando um cliente chama um
metodo de um bean ele esta
iniciando um dialogo
Assim, o estado do dialogo precisa ser
mantido para a próxima chamada
 Logo, o Container não pode fazer o
mesmo tipo de “pooling” que faz com os
beans Stateless


Solução: passivação e ativação
Passivação e ativação





Semelhante ao processo de paginação efetuado pelo
sistema operacional
Dados do bean são armazanados durante a passivação e
recuperados na ativação
Permite manter poucas instancias no ar atendendo a vários
clientes
O Container decide quais beans serão passivados.
Estratégia mais comum: LRU – Last Recently Used


Se o Container precisar de mais recursos o bean a mais tempo
usado será passivado
O bean será serializado, assim, farão parte do dialogo
apenas objetos e variáveis não transientes!
Stateful Session Beans

Precisam implementar a mesma
interface que Stateless Session
Beans

Porém, algumas operações agora farão
sentido
• void ejbPassivate()
– Chamado antes do container fazer o swap do
Bean.
• void ejbActivate()
– Chamado depois do container recuperar o bean
do disco.
Stateful Session Beans


Se há mais clientes realizando operações
contínuas que beans no pool, container
pode criar mais instancias
Se há mais clientes que beans no pool
mas uma boa parte permanece inativa por
certos períodos (cenário realista) o
container gerencia os recursos utilizando
ativação e passivação

O Administrador do sistema pode configurar o
servidor para obter melhor desempenho
(deployment descriptor)
Ciclo de Vida
Cliente chama
create(...) na
interface home
Cliente chama remove
ou a sessão expirou
Bean não
existe
1: Class.newInstance()
2: ejbSetSessionContext()
ejbRemove()
Time out
3: ejbCreate(...)
Limite de beans do
container atingido
ejbPassivate()
metodo()
Bean inativo
Bean ativo
ejbActivate()
Qualquer cliente chama
um método de negócio
em qualquer EJBObject
Qualquer cliente chamou
um método de negócio em
um bean inativo. Container
precisa ativar o bean
Exemplo
package org.citi.pec.ejbs;
//..imports
/**
* @ejb.bean
*
*
*
*
*
*/
public class
name="Calculator"
display-name="Name for Calculator"
description="Description for Calculator"
jndi-name="ejb/Calculator"
type="Stateful"
view-type="remote"
CalculatorBean implements SessionBean {
private BigDecimal memory = BigDecimal.ZERO;
public void setSessionContext(SessionContext ctx)
throws EJBException, RemoteException {
}
public void ejbRemove() throws EJBException, RemoteException {
System.out.println("CalculatorBean.ejbRemove()");
}
public void ejbActivate() throws EJBException, RemoteException {
System.out.println("CalculatorBean.ejbActivate()");
}
public void ejbPassivate() throws EJBException, RemoteException {
System.out.println("CalculatorBean.ejbPassivate()");
}
Exemplo
//continuação
/**
* @ejb.create-method
*/
public void ejbCreate() throws CreateException {
System.out.println("CalculatorBean.ejbCreate()");
}
/**
* @ejb.interface-method view-type = "remote"
*/
public double add(double value) {
memory = memory.add(new BigDecimal(value));
return memory.doubleValue();
}
/**
* @ejb.interface-method view-type = "remote"
*/
public double mult(double value) {
memory = memory.multiply(new BigDecimal(value));
return memory.doubleValue();
}
}
Exemplo

Para demonstrar o efeito ejbActivate() e ejbPassivate()
vamos reduzir o tamando da cache do bean artificialmente
para a capacidade máxima de 2 beans

Jboss.xml
<session>
<ejb-name>Calculator</ejb-name>
<jndi-name>ejb/Calculator</jndi-name>
<configuration-name>myEjbsConf</configuration-name>
</session>
</enterprise-beans>
<container-configurations>
<container-configuration extends="Standard Stateful SessionBean">
<container-name>myEjbsConf</container-name>
<container-cache-conf>
<cache-policy>
org.jboss.ejb.plugins.LRUStatefulContextCachePolicy
</cache-policy>
<cache-policy-conf>
<max-capacity>2</max-capacity>
</cache-policy-conf>
</container-cache-conf>
</container-configuration>
</container-configurations>
Exemplo

Em execução...
ejbCreate() e create()

Para cada create() na interface Home deve
haver um ejbCreate() no bean





Com número e tipo dos parâmetros idênticos
Cada create() na interface Home retorna o tipo
da interface do componente
Cada ejbCreate() no bean retorna void
Ambos lançam as mesmas exceções( exceto
RemoteException que só é lançada na
interface Home remota)
...XDoclet faz isso para nós!
Exercício (1)

Altere o tipo do bean Calculadora de
Stateful para Stateless, rode a
aplicação novamente e discuta os
resultados
Exercício (2)

(a) Implemente um Session Bean com a
seguinte interface
Carrinho
+adicionarProduto(String)
+listarProdutos():String
• O Bean mantém uma String com Produtos por linha
• listarProdutos() retorna a String
• adicionarProduto concatena a String

Faça o deploy
Clientes

Para acessar um Ejb é necessário
encontralo (lookup) no servidor

Faz-se o lookup da interface home ao
servidor JNDI
Context ctx;
//..obenten-se o contexto do servidor de nomes
Object o = ctx.lookup("ejb/Calculator");

Caso a interface procurada seja a local,
o retorno do lookup já é esta
CalculatorLocalHome calculator = (CalculatorLocalHome)
ctx.lookup("ejb/Calculator");
Clientes

Caso a interface procurada seja a
remota, o retorno do lookup é um
objeto RMI-IIOP. Assim, é necessário
efetuar um “cast” especial
Object o = ctx.lookup("ejb/Calculator");
CalculatorHome calculatorHome = (CalculatorHome)
PortableRemoteObject.narrow(o, CalculatorHome.class);

De posse da interface home desejada,
basta chamar o create() para obter
acesso a interface do bean
Clientes

Obtendo (configurando) o contexto
JNDI

Arquivo “jndi.properties” no classpath
Context ctx = new InitialContext();

Configuração programática
Hashtable props = new Hashtable();
props.put(Context.INITIAL_CONTEXT_FACTORY,
"org.jnp.interfaces.NamingContextFactory");
props.put(Context.URL_PKG_PREFIXES,
"org.jboss.naming:org.jnp.interfaces");
props.put(Context.PROVIDER_URL,
"jnp://localhost:1099");
Context ctx = new InitialContext(props);
Exercício (2)

Crie um cliente para o Carrinho
Crie dois carrinhos
 Preencha ambos com 3 ou 4 produtos
diferentes
 Liste o conteúdo de ambos

Exercício (3)

Carrinho de compras usando Produto


Implemente um Stateful Session Bean que
mantém na memória uma coleção de Produtos
O Bean deve ter a seguinte interface e utilizar
o objeto Produto
•
•
•
•



public
public
public
public
Produto[] listarConteudoCarrinho();
void adicionarProduto(Produto produto);
void removerProduto(String cod);
Produto detalharProduto(String cod);
Faça o deploy
Crie um cliente semelhante ao do Carrinho
Após rodar o cliente, altere o Bean para
Stateles e rode novamente e comente os
resultados
Referências
[1] Ed Roman, Mastering EJB 3, 2002,
Capítulo 4
[2] Dale Green. Session Beans. J2EE
Tutorial, Sun
[3] Linda G. deMichiel et al. Enterprise
JavaBeans™ 2.1 Specification. Sun
Microsystems, 2003
[4] XDoclet, Doc for 1.2.2-RC1.
http://xdoclet.sourceforge.net/
Download

j2ee_pcc_04_Statefull_Session_Beans