Title: Stateful Session Beans
1Stateful Session Beans
- Carrinho de compras corporativo
Ricardo Cavalcanti roc3_at_cin.ufpe.br
Jobson Ronan jrjs_at_cin.ufpe.br
2Por 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
3Passivaçã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
menos tempo usado será passivado - O bean será serializado, assim, farão parte do
dialogo apenas objetos e variáveis não
transientes!
4Stateful Session Beans
- Precisam implementar a mesma interface que
Steteless 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.
5Stateful Session Beans
- Se a 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)
6Ciclo de Vida
Cliente chama remove ou a sessão expirou
Cliente chama create(...) na interface home
Bean não existe
1 Class.newInstance() 2 ejbSetSessionContext() 3
ejbCreate(...)
Time out
ejbRemove()
Limite de beans do container atingido
ejbPassivate()
Bean inativo
Bean ativo
metodo()
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
7Exemplo
package org.citi.pec.ejbs //..imports /
_at_ejb.bean name"Calculator"
display-name"Name for Calculator"
description"Description for Calculator"
jndi-name"ejb/Calculator"
type"Stateful" view-type"remote"
/ public class 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("CalculatorB
ean.ejbRemove()") public void
ejbActivate() throws EJBException,
RemoteException System.out.println("CalculatorB
ean.ejbActivate()") public void
ejbPassivate() throws EJBException,
RemoteException System.out.println("CalculatorB
ean.ejbPassivate()")
8Exemplo
//continuação / _at_ejb.create-method
/ public void ejbCreate() throws
CreateException System.out.println("CalculatorB
ean.ejbCreate()") /
_at_ejb.interface-method view-type "remote"
/ public double add(double value) memory
memory.add(new BigDecimal(value)) return
memory.doubleValue() /
_at_ejb.interface-method view-type "remote"
/ public double mult(double value) memory
memory.multiply(new BigDecimal(value)) return
memory.doubleValue()
9Exemplo
- 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
ltsessiongt ltejb-namegtCalculatorlt/ejb-name
gt ltjndi-namegtejb/Calculatorlt/jndi-namegt
ltconfiguration-namegtmyEjbsConflt/configuration-na
megt lt/sessiongt lt/enterprise-beansgt
ltcontainer-configurationsgt ltcontainer-configur
ation extends"Standard Stateful SessionBean"gt
ltcontainer-namegtmyEjbsConflt/container-namegt
ltcontainer-cache-confgt
ltcache-policygt org.jboss.ejb.plugins.LRUStatefu
lContextCachePolicy lt/cache-policygt
ltcache-policy-confgt ltmax-capacitygt2lt/ma
x-capacitygt lt/cache-policy-confgt
lt/container-cache-confgt lt/container-configurat
iongt lt/container-configurationsgt
10Exemplo
11ejbCreate() 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!
12Exercício (1)
- Altere o tipo do bean Calculadora de Stateful
para Stateless, rode a aplicação novamente e
discuta os resultados
13Exercício (2)
- (a) Implemente um Session Bean com a seguinte
interface - O Bean mantém uma String com Produtos por linha
- listarProdutos() retorna a String
- adicionarProduto concatena a String
- Faça o deploy
Carrinho adicionarProduto(String) listarProduto
s()String
14Clientes
- 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/Calc
ulator")
- Caso a interface procurada seja a local, o
retorno do lookup já é esta
CalculatorLocalHome calculator
ctx.lookup("ejb/Calculator")
15Clientes
- 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") Calculat
orHome calculatorHome (CalculatorHome)
PortableRemoteObject.narrow(o, CalculatorHome.clas
s)
- De posse da interface home desejada, basta chamar
o create() para obter acessor a interface do bean
16Clientes
- Obtendo (configurando) o contexto JNDI
- Arquivo jndi.properties no classpath
- Configuração programática
Context ctx new InitialContext()
Hashtable props new Hashtable() props.put(Conte
xt.INITIAL_CONTEXT_FACTORY,
"org.jnp.interfaces.NamingContextFactory") props
.put(Context.URL_PKG_PREFIXES,
"org.jboss.namingorg.jnp.interfaces") props.put
(Context.PROVIDER_URL, "jnp//localhost1099")
Context ctx new InitialContext(props)
17Exercí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
18Exercí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 Produto listarConteudoCarrinho()
- public void adicionarProduto(Produto produto)
- public void removerProduto(String cod)
- public 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
19Referê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/