Stateful Session Beans Carrinho de compras corporativo Ricardo
Stateful Session Beans Carrinho de compras corporativo Ricardo Cavalcanti roc 3@cin. ufpe. br Jobson Ronan jrjs@cin. ufpe. br
Por que? w 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 u Logo, o Container não pode fazer o mesmo tipo de “pooling” que faz com os beans Stateless u w Solução: passivação e ativação
Passivação e ativação w w w 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 u w 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 w Precisam implementar a mesma interface que Stateless Session Beans u Porém, algumas operações agora farão sentido • void ejb. Passivate() – Chamado antes do container fazer o swap do Bean. • void ejb. Activate() – Chamado depois do container recuperar o bean do disco.
Stateful Session Beans w w 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 u 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. new. Instance() 2: ejb. Set. Session. Context() ejb. Remove() Time out 3: ejb. Create(. . . ) Limite de beans do container atingido ejb. Passivate() metodo() Bean inativo Bean ativo ejb. Activate() 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" Calculator. Bean implements Session. Bean { private Big. Decimal memory = Big. Decimal. ZERO; public void set. Session. Context(Session. Context ctx) throws EJBException, Remote. Exception { } public void ejb. Remove() throws EJBException, Remote. Exception { System. out. println("Calculator. Bean. ejb. Remove()"); } public void ejb. Activate() throws EJBException, Remote. Exception { System. out. println("Calculator. Bean. ejb. Activate()"); } public void ejb. Passivate() throws EJBException, Remote. Exception { System. out. println("Calculator. Bean. ejb. Passivate()"); }
Exemplo //continuação /** * @ejb. create-method */ public void ejb. Create() throws Create. Exception { System. out. println("Calculator. Bean. ejb. Create()"); } /** * @ejb. interface-method view-type = "remote" */ public double add(double value) { memory = memory. add(new Big. Decimal(value)); return memory. double. Value(); } /** * @ejb. interface-method view-type = "remote" */ public double mult(double value) { memory = memory. multiply(new Big. Decimal(value)); return memory. double. Value(); } }
Exemplo w Para demonstrar o efeito ejb. Activate() e ejb. Passivate() vamos reduzir o tamando da cache do bean artificialmente para a capacidade máxima de 2 beans u Jboss. xml <session> <ejb-name>Calculator</ejb-name> <jndi-name>ejb/Calculator</jndi-name> <configuration-name>my. Ejbs. Conf</configuration-name> </session> </enterprise-beans> <container-configuration extends="Standard Stateful Session. Bean"> <container-name>my. Ejbs. Conf</container-name> <container-cache-conf> <cache-policy> org. jboss. ejb. plugins. LRUStateful. Context. Cache. Policy </cache-policy> <cache-policy-conf> <max-capacity>2</max-capacity> </cache-policy-conf> </container-cache-conf> </container-configurations>
Exemplo w Em execução. . .
ejb. Create() e create() w Para cada create() na interface Home deve haver um ejb. Create() no bean u u u Com número e tipo dos parâmetros idênticos Cada create() na interface Home retorna o tipo da interface do componente Cada ejb. Create() no bean retorna void Ambos lançam as mesmas exceções( exceto Remote. Exception que só é lançada na interface Home remota). . . XDoclet faz isso para nós!
Exercício (1) w Altere o tipo do bean Calculadora de Stateful para Stateless, rode a aplicação novamente e discuta os resultados
Exercício (2) w (a) Implemente um Session Bean com a seguinterface Carrinho +adicionar. Produto(String) +listar. Produtos(): String • O Bean mantém uma String com Produtos por linha • listar. Produtos() retorna a String • adicionar. Produto concatena a String u Faça o deploy
Clientes w Para acessar um Ejb é necessário encontralo (lookup) no servidor u 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"); u Caso a interface procurada seja a local, o retorno do lookup já é esta Calculator. Local. Home calculator = (Calculator. Local. Home) ctx. lookup("ejb/Calculator");
Clientes u 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"); Calculator. Home calculator. Home = (Calculator. Home) Portable. Remote. Object. narrow(o, Calculator. Home. class); u De posse da interface home desejada, basta chamar o create() para obter acesso a interface do bean
Clientes w Obtendo (configurando) o contexto JNDI u Arquivo “jndi. properties” no classpath Context ctx = new Initial. Context(); u Configuração programática Hashtable props = new Hashtable(); props. put(Context. INITIAL_CONTEXT_FACTORY, "org. jnp. interfaces. Naming. Context. Factory"); props. put(Context. URL_PKG_PREFIXES, "org. jboss. naming: org. jnp. interfaces"); props. put(Context. PROVIDER_URL, "jnp: //localhost: 1099"); Context ctx = new Initial. Context(props);
Exercício (2) w Crie um cliente para o Carrinho Crie dois carrinhos u Preencha ambos com 3 ou 4 produtos diferentes u Liste o conteúdo de ambos u
Exercício (3) w Carrinho de compras usando Produto u u Implemente um Stateful Session Bean que mantém na memória uma coleção de Produtos O Bean deve ter a seguinterface e utilizar o objeto Produto • • u u u public Produto[] listar. Conteudo. Carrinho(); void adicionar. Produto(Produto produto); void remover. Produto(String cod); Produto detalhar. Produto(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. J 2 EE Tutorial, Sun [3] Linda G. de. Michiel et al. Enterprise Java. Beans™ 2. 1 Specification. Sun Microsystems, 2003 [4] XDoclet, Doc for 1. 2. 2 -RC 1. http: //xdoclet. sourceforge. net/
- Slides: 19