Session Beans Luiz C. D´Oleron SJCP [email protected] Jobson Ronan [email protected] O que são? São objetos de processo de negócio Implementam lógica e regras de negócios, algoritmos e workflow São componentes reusáveis que representam acções Sua principal diferença dos Entity Beans é o seu escopo de vida Um Session Bean dura no máximo uma sessão (do cliente) O que são? Sessão? Tempo que o browser está aberto Tempo que um outro bean usa o session bean Tempo que uma aplicação remota esta aberta Session Beans são Objetos transientes Não tem seu estado armazenado em meio persistente Tipos de Session Beans Clientes efetuam um diálogo com o bean (dialogo é a interação do cliente com o bean) Consiste de uma ou mais chamadas entre cliente e bean Dura um processo de negocio para o cliente Os dois tipos de Session Beans implementam diferentes tipos de diálogos Stateful Session Beans Stateless Session Beans Tipos de Session Beans Stateful Session Beans implementam diálogos que consistem de várias requisições onde certas requisições podem depender de requisições anteriores Stateless Session Beans implementam dialogos que consistem de apenas um requisição Stateless Session Beans Como stateless session beans não mantém informação de estado do diálogo, todas as instâncias do mesmo bean são equivalentes e indistiguíveis Não importa que chamou o bean no passado, qualquer instância disponível de um session bean pode servir a qualquer cliente Por este motivo, Stateless Session beans podem ser guardados em um pool, reutilizados, e passados de um cliente para outro em cada chamada de método Stateless Session Beans Pool de Stateles Session Beans Cliente invoke() Pool de Stateles Beans EJBObject Interface remota Bean Bean Bean invoke() Bean Bean Stateless Session Beans Pela interface javax.ejb.SessionBean, cada Session bean precisa implementar os seguintes métodos void setSessionContext (SessionContext ctx) • Associa o bean com o contexto da sessão • O contexto pode ser usado para obter referências para o interceptador remoto e local do bean, se necessário • Guarde //... a referência em uma variável de instância private SessionContext ctx; void setSessionContext(SessionContext ctx) { this.ctx = ctx } //... Stateless Session Beans void ejbCreate() • Realiza a inicialização do bean. Pode ser vazio. void ejbRemove() • Chamado antes de liberar recursos e ser removido da memória. Pode ser vazio. void ejbPassivate() • Não implementado por Stateless Session Beans. Deixe vazio. void ejbActivate() • Não implementado por Stateless Session Beans. Deixe vazio. Stateless Session Beans javax.ejb.SessionContext Usado para obter o contexto de execução do Session Bean Extende javax.ejb.EJBContext com dois metodos • getEJBLocalObject(): retorna a referência para o interceptador local (gerado pelo container) • getEJBObject(): retorna a referência para o interceptador remoto (que é objeto Remote) Estes métodos podem ser usados quando desejar passar a referência de seu objeto remoto para algum método. Ciclo de vida Container decide que precisa de mais instancias para servir aos clientes Bean não existe 1: Class.newInstance() 2: ejbSetSessionContext() ejbRemove() 3: ejbCreate() metodo() Qualquer cliente chama um método de negócio em qualquer EJBObject Pool de instancias equivalentes prontas Container decide que não precisa mais de tantas instancias Exemplo Interfaces Home e Remote package org.citi.pec.ejbs; //imports... public interface Loja extends javax.ejb.EJBObject { public Collection listarProdutos() throws RemoteException; //... } package org.citi.pec.ejbs; //imports... public interface LojaHome extends javax.ejb.EJBHome { public Loja create() throws RemoteException, CreateException; //... } * Compare o create() do EJBHome com o ejbCreate() do Bean Exemplo Enterprise JavaBean package org.citi.pec.ejbs; //imports... public class LojaBean implements javax.ejb.SessionBean { private SessionContext sessionContext; public Collection listarProdutos() { System.out.println("LojaBean.listarProdutos()"); // implementação; Implementação } da interface public void ejbCreate() throws CreateException { System.out.println("LojaBean.ejbCreate()"); } public void ejbRemove() { System.out.println("LojaBean.ejbRemove()"); } public void ejbActivate() { System.out.println("LojaBean.ejbActivate()"); } public void ejbPassivate() { System.out.println("LojaBean.ejbPassivate()"); } public void setSessionContext(SessionContext ctx) { this.sessionContext = ctx; System.out.println("LojaBean.setSessionContext()"); } } Exemplo 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> <enterprise-beans> <session> <ejb-name>Loja</ejb-name> <home>org.citi.pec.ejbs.LojaHome</home> <remote>org.citi.pec.ejbs.Loja</remote> <ejb-class>org.citi.pec.ejbs.LojaBean</ejb-class> <session-type>Stateless</session-type> <transaction-type>Container</transaction-type> </session> </enterprise-beans> </ejb-jar> Exemplo Deployment Descriptor proprietário (JBoss – jboss.xml) <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE jboss PUBLIC "-//JBoss//DTD JBOSS 4.0//EN" "http://www.jboss.org/j2ee/dtd/jboss_4_0.dtd"> <jboss> <enterprise-beans> <session> <ejb-name>Loja</ejb-name> <jndi-name>ejb/Loja</jndi-name> </session> </enterprise-beans> </jboss> ...Tudo isso só para um simples Stateless Session Bean? ...Não poderia ser mais simples? XDoclet O que é? É um engine open source gerador de código Permite programar orientado a atributos em Java (antes do JDK1.5) utilizando tags especiais de JavaDoc Desenvolvedor trabalha em apenas um arquivo .java por componente XDoclet Benefícios: Não se preocupar com deployment descriptors desatualizados Normalmente um simples EJB é composto por vários arquivos. Com XDoclet, trabalha-se apenas com um e o resto é gerado. Incrível redução no tempo de desenvolvimento Exemplo package org.citi.pec.ejbs; //..imports import javax.ejb.CreateException; /** * @ejb.bean name="Loja" * display-name="Name for Loja" * description="Description for Loja" * jndi-name="ejb/Loja" * type="Stateless" * view-type="remote" */ public class LojaBean implements SessionBean { private SessionContext ctx; public void setSessionContext(SessionContext ctx) throws EJBException, RemoteException { this.ctx = ctx; } public void ejbRemove() throws EJBException, RemoteException {} public void ejbActivate() throws EJBException, RemoteException {} public void ejbPassivate() throws EJBException, RemoteException {} /** * @ejb.create-method */ public void ejbCreate() throws CreateException {} /** * @ejb.interface-method view-type = "remote" */ public Collection listarProdutos() { //...implementação } } ...O resto é gerado Loja.java /* * Generated by XDoclet - Do not edit! */ package org.citi.pec.ejbs; /** * Remote interface for Loja. * @xdoclet-generated at ${TODAY} * @copyright The XDoclet Team * @author XDoclet * @version ${version} */ public interface Loja extends javax.ejb.EJBObject { public java.util.Collection listarProdutos( throws java.rmi.RemoteException; } ) ...O resto é gerado LojaHome.java /* * Generated by XDoclet - Do not edit! */ package org.citi.pec.ejbs; /** * Home interface for Loja. * @xdoclet-generated at ${TODAY} * @copyright The XDoclet Team * @author XDoclet * @version ${version} */ public interface LojaHome extends javax.ejb.EJBHome { public static final String COMP_NAME="java:comp/env/ejb/Loja"; public static final String JNDI_NAME="ejb/Loja"; public org.citi.pec.ejbs.Loja create() throws javax.ejb.CreateException,java.rmi.RemoteException; } ...O resto é gerado ejb-jar.xml <?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 > <description><![CDATA[No Description.]]></description> <display-name>Generated by XDoclet</display-name> <enterprise-beans> <!-- Session Beans --> <session > <description><![CDATA[Description for Loja]]></description> <display-name>Name for Loja</display-name> <ejb-name>Loja</ejb-name> <home>org.citi.pec.ejbs.LojaHome</home> <remote>org.citi.pec.ejbs.Loja</remote> <ejb-class>org.citi.pec.ejbs.LojaBean</ejb-class> <session-type>Stateless</session-type> <transaction-type>Container</transaction-type> </session> .... ...O resto é gerado jboss.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE jboss PUBLIC "-//JBoss//DTD JBOSS 3.2//EN" "http://www.jboss.org/j2ee/dtd/jboss_3_2.dtd"> <jboss> <enterprise-beans> <!—alguns comentarios gerados--> <session> <ejb-name>Loja</ejb-name> <jndi-name>ejb/Loja</jndi-name> <method-attributes> </method-attributes> </session> </enterprise-beans> <resource-managers> </resource-managers> </jboss> Exemplo Demostração prática: Eclipse + JBossIDE (plugin) + XDoclet Patterns Session Facade Aplicar os beneficios do padrão tradicional facade para EJBs Esconder completamente o modelo dos objetos do servidor da camada do cliente Implementar um caso de uso por chamada de rede Patterns Sem o padrão Session Facade Patterns Sem o padrão Session Facade Problemas • Alto overhead da rede • Probre concorrencia (Transações longas) • Alto acoplamento • Pobre reusabilidade • Difícil manutenção • Pobre separação de papéis Patterns Com Session Facade Patterns Com Session Facade Benefícios • Baixo overhead da rede • Limpa e estrita separação entre lógica de negócio e lógica da camada de apresentação • Integridade transacional • Baixo acoplamento • Boa reusabilidade • Melhor manutenção • Limpa separação verbo-nome Conclusões Stateless Session Beans são os Beans mais simples Permitem implementar qualquer aplicação distribuída implementável com RMI Porém, tem seu ciclo de vida controlado pelo container, além de poderem utilizar os serviços fornecidos por este (autenticação, autorização, transações, etc.) *Não defina atributos de instâncias em Stateless Session Beans! E mais... A partir da especificação 2.1 dos EJBs, Stateless Session Beans podem prover interfaces de Web Services para clientes 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/ Exercício (1/3) Criar um Session Bean Stateless Loja que possui o metodo: String[] listarProdutos() • Retorna uma array de Strings com o nome dos produtos cadastrados no sistema • Este produtos podem estar cadastrados staticamente. Ex: Como Atributo Exercício (2/3) Criar uma Calculadora remota com metodos: double somar(double, double) double multiplicar(double, double) Exercicio (3/3) Criar um objeto Produto, com nome e valor Criar um Session Bean ListaProdutos com o metodo: Produto[] listarProdutos() boolean isDisponível(Produto p)