26-07-2010 Programa de disciplina resumido: Revisão de collections7 Java Persistence API (JPA) Enterprise JavaBeans (EJB) Estruturas de Dados Estruturas estáticas Variável Array (vetores, matrizes) Estruturas dinâmicas Listas ligadas Fila (FIFO – First In First Out) Pilha (FILO – First In Last Out) Árvore Grafo Exemplo de lista ligada em JAVA public class No { public int dado; public No proximo; } public class ListaLigada { private No primeiro; public void inserePrimeiro(int dado){ No aux = new No(); aux.dado = dado; aux.proximo = primeiro; primeiro = aux; } public void insereUltimo(int dado){ if(primeiro == null){ inserePrimeiro(dado); return; } No aux = primeiro.proximo; while(aux.proximo != null){ aux = aux.proximo; } No aux2 = new No(); aux2.dado = dado; aux.proximo = aux2; } } 1 Genéricos (Java 5) Motivação: Tarefas semelhantes requerem sobrecarga; void imprime(int dado){} void imprime(String dado){} void imprime(No dado){} Se o método imprime não usar características específicas de dado, então um único método genérico pode ser escrito: public static <e> void imprime (e dado){} (Onde e é um parâmetro de tipo) Métodos genéricos podem usar um parâmetro de tipo como retorno: public static <e> e maior (e dado1, e dado2){} O tipo e, nos dois casos, assume o tipo dos parâmetros dos métodos. Classes Genéricas public class ClasseGenerica <e> { public static void imprime(e dado){} public static e maior(e dado1, e dado2){} } Instanciando Classes Genéricas: ClasseGenerica <String> objetoTexto = new ClasseGenerica <String>(); ClasseGenerica <int> objetoInt = new ClasseGenerica <int>(); 2010-08-09 Persistência Automatizada em Java Bibliografia: - Debu PANDA: Reza RAHMAN: Derele LENE. EJB3 em Ação “Rio de Janeiro, Alta Books, 2007, 2° Ed. Revisada.” - Richard MONSON-HAEFEL; Bill BURKE. ”Enterprise JevaBeans 3.0”. Prentice Hall , 2007. Como era antes: O tratamento dos dados fica totalmente à cargo do programador (pouca padronização e portabilidade). Acesso a bando de dados em baixo nível (linguagem SQL especifica de cada SGDB). 2 Java Persistence API (JPA) Arquitetura: Conceito Conceito integrante do Java EE5; Disponível a partir do Java 5; Definido no JSA 220(Enterprise Java Bens 3.0); Padroniza o mapeamento objeto-relacional; Não depende de container para funcionar; Baseada no conceito de PDJDS (Plam Old Java Object); Utiliza amplamente anotação (programação declarativa); Encontra-se no pacote para percistence; Os objetos persistentes são denominados entidades (Entities). Estas entidade devem possuir um atributo identificador (chave primária) e um construtor sem parâmetros. 3 Unidade de Persistência: Conjunto de classes mapeadas para um banco de dados relacional esse mapeamento é feito através de um arquivos descritor de implantação chamado persistence.xml que deve ser gravado na pasta META-INF e que pode conter a configuração de varias unidades de persistência. Contexto de Persistência (Persistence context): Ambiente (sessão) que envolve o conjunto de instancia de entidades gerenciadas pelo EntityManager Gerenciador de Entidades (EntityManager); (Java.persistence,EntityManager); Serviços que gerencia o conjunto de entidades registrados dentro de um contexto de persistência, monitorando as alterações feitas nos objetos desde contesto de persistência e gravando essas alterações no banco de dados Provedor de Persistencia (Persistence Provider): Pode ser entendido como um driver JPA para uma determinada ferramenta de mapeamento objeto-relacional. Mais especificamente é a classe que implemente a interface javax.persistence. PersistenceProvider. São alguns exemplos de fornecedores de provedores de persistência: Aoracle toplink Hibernate Kodo OPEN JPA ETC. Ciclo de vida/estado de uma entidade 4 Mapeamento Básico de Entidades É feito com anotações nas classes persistentes: @Entity: Marca uma classe como entidades persistente; @Table: Define o nome da tabela onde os objetos serão persistidos; @Id: Define o atributo que constitui o atributo identificado (chave primaria); @GeneratedValue: Define um campo autonumerico; @Column: Define o nome da coluna onde o atributo será salvo; @Transient: Define que um atributo não será salvo; Exemplo: import javax.persistence.*; @Emtity @Table(nome="Aluno") public class Aluno { @Id @GeneratedValue(strategy = GenerationType, IDENTITY) @Column(name = "id", nullable=false,columnDefinition="integer") private int id; @Column(name="nome", length=50, nullable=false) private String nome; @Coloumn(nome="ra") private long ra; public int getRa(){ return ra; } public void setName(String nome){ this.name = nome; } //Demais getters e setters } 16-08-2010 /*Exemplo usando mapeamento padrão */ import javax.persistence.*; @Entity public class Aluno2{ @Id @GeneratedValue private int id; private String nome; private lang a; } Representação em Diagrama de classe (UML): <<entity>> 5 Aluno -id: integer -nome:String -ra:long ... 23-08-2010 ROTEIRO No código da aplicação que utiliza classe peristentes: Crie um gerenciador de entidades através de uma fabrica: EntityManagerFactory emf = Persistence. createEntityManagerFactory("UnidadeDePersistencia"); EntityMnager em = emf.createEmtityManager(); Inicie uma transação em.getTransaction().begin(); Crie uma entidade Entidade e = new entidade(); Persista a entidade em.persist(e); Localize uma Entidade Entidade e = em.emf(Entidade.class,chave); Reintegre uma entidade ao Contexto de Perstência e = em.merge(e); Elimine uma entidade do BD em.remove(e) Encerra a transação em.getTransaction().commit(); Interface EntityManager Alguns métodos: void persist (Object entidade) Persiste uma entidade, tornando-a gerenciada pelo Gerenciador de Entidades Qualquer alteração feita na entidade será refletida no banco de dados automaticamente. <T>T merge(T entidade) Reintegra a entidade ao Contexto de Persistência. Retorna um objeto gerenciado(MENAGED), cujas alterações são enviadas automaticamente ao BD. Não pode ser usado em um objeto REMOVED. void refresh (Object entidade) Atualiza os atributos da entidade com os dados atuais do banci de dados. 6 void remove(Object entidade) Remove a entidade do banco de dados e do Context de Persistência, tornando-a REMOVED <T> T find(Class<T> classeDaEntidade, Object chavePrimaria) Retorna uma entidade gerenciada da classe espeficicada, encontrada através de sua chave primária. Retorna null caso não a encontre. Query createQuery(String comando) Cria uma consulta dinâmica em JPQL Query createNamedQuery(String nomeDoComando) Cria uma consulta nomeda escrita em JPQL Query creteBativeQuery(String comando SQL) Cria uma consulta em SQL nativo do BD conectado EntityTransaction getTransaction() Retorna a transação do EntityManager Interface EntityTransaction void begin() Inicia a transação void commit() Encerra a transação, confirmando as alterações feitas desde o seu início void rollback() Encerra a transação, descartando as alterações feitas desde o seu início. Exemplo de aplicações JvaSt usando Oracle TopLink Baixe o TopLink Essentials do seguinte endereço: http://www.oracle.com/technology/products/ias/toplink/jpa/download.html Obs. É um download pequeno. Coloque o arquivo baixado em uma pasta de trabalho e execute o seguinte comando nesta pasta: Java –jar glossifish-persistence-installer-v2-bxx.jaro Isto irá criar uma pasta chamada glossfish-persistence contendo os arquivos de licença, readme e as bibliotecas do Toplink Essentials 2RD-PARTY-LICENCE.txt CDDLv1.0.txt README Toplink-essentials-agent.jar Toplink-essentials.jar Crie um projeto Java5 ou superior e adicione os arquivos.jar acima ao classpath, para que sua aplicação encontre as bibliotecas. Adicione também o .jar do driver JDBC do banco de dados que for utilizar. O NetBens já incorpora o Toplink Essentials. Para utilizá-lo, clique com o botão direito no nó “Nova Biblioteca...”. A seguir selecione Toplink Essentials da lista, assim como o driver JDBC de BD que for utilizado. 7 Já no Eclipse, clique com o botão direito no seu projeto e selecione “Propriedades” -> ”Java BuildPath” -> “Libraries” e clique no botão “Add external jars”. Adicione os dois .jar. Adicione os dois .jar baixados acima e o .jar do driver JDBC. Crie a entidade Aluno abaixo: package modelo; import javax.persistent; @Entity public class Aluno{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; private String nome; private long ra; private double ms1; private double ms2; //getters e setters aqui! } Crie o arquivo persistence.xml na pasta META-INF do seu projeto: Crie a entidade Aluno abaixo: package modelo; anagimport javax.persistent; @Entity public class Aluno{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; private String nome; private long ra; private double ms1; private double ms2; } <?xml version="1.0" encoding="UTF-8"?> <persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"> <persistence-unit name="novoExemploPU" transaction-type="RESOURCE_LOCAL"> <provider>oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider </provider> <class>teste.Empresas</class> <class>teste.Cartoes</class> <properties> <property name="toplink.jdbc.url" value="jdbc:mysql://localhost:3306/devmedia"/> <property name="toplink.jdbc.user" value="root"/> <property name="toplink.jdbc.driver" value="com.mysql.jdbc.Driver"/> 8 <property name="toplink.jdbc.password" value="123456"/> </properties> </persistence-unit> </persistence> 30/08/2010 //Inclusão: Crie o seguinte aplicativo no pacote negócio do seu projeto package negocio; import modelo.*; import javax.persistence.*; public class CriaAluno{ public static void main(String args[]){ EntityManagerFactory emf=Persistence.createEntityFactory("teste"); EntityManager em=emf.createEntityManager(); em.getTransaction().begin(); Aluno a = new Aluno(); a.setNome("Maria"); a.setRa(123456789); a.setMs1("6.5"); a.setMs2("8.5"); //Insere a entidade no BD, tornando-a gerenciada em.persist(a); em.getTransaction().commit(); em .close(); emf.close(); System.out.print("Id do aluno persistido: "+a.getId()); } } //Consulta: Localiza uma entidade por sua chave primaria package negocio; import modelo.*; import javax.persistence.*; public class BuscaAluno{ public static void main(String args[]){ EntityManagerFactory emf = Persistence.createEntityFactory("teste"); EntityManager em = emf.createEntityManager(); //Método find: retorna uma entidade gerenciada Aluno a = em.find(Aluno.class,3); if(a != null){ System.out.print("RA: "+a.getRa()); System.out.print("Nome: "+a.getNome()); //Apesar da entidade estar gerenciada, a alteração não ocorre, pois não há transação a.setNome("Nome do aluno"); else{ System.out.print("Aluno não encontrado"); } 9 em.close(); emf.close(); } } //Alteração: Localiza uma entidade por sua chave primária e altera seus atributos package negocio; import modelo.*; import javax.persistence.*; public class AlteraAluno{ public static void main(String args[]){ EntityManagerFactory emf=Persistence.createEntityFactory("teste"); EntityManager em=emf.createEntityManager(); em.getTransaction().begin(); //Rertorna uma entidade gerenciada: Aluno a = em.find(Aluno.class,1); if(a != null){ //Alteracoes automáticas(sem usar transaction SQL) a.setNome("Novo nome"); a.setRa(987654321); a.setMs1(7.8); a.setMs2(8); System.out.print("Id do aluno alterado: "+a.getId); } em.getTransaction().commit(); em.close(); emf.close(); } } Exclusão: Localiza uma entidade por sua chave primária e a exclui package negocio; import modelo.*; import javax.persistence.*; public class ExcluiAluno{ public static void main(String args[]){ EntityManagerFactory emf=Persistence.createEntityFactory("teste"); EntityManager em=emf.createEntityManager(); em.getTransaction().begin(); Aluno a = em.find(Aluno.class,8); if(a != null){ 10 //Torna a entidade REMOVED. Qualquer //alteração não será reflitida no BD em.remove(a); System.out.print() System.out.print("Aluno excluido: "+a.getId()); System.out.print(""+a.getNome); }else{ System.out.print("Aluno não encontrado."); } em.getTransaction().commit(); em.close(); emf.close(); System.out.println(“Novo nome:”}+a.getNome()); }else { System.out.printl(“Aluno não encontrado”); } em.close(); emf.close(); } Private static Aluno mudaDados(Aluno a) { a.setNome(“Juliana”); return a; } } 20/09/2010 Relacionamentos @one to one = Inidica o atributo mapeia outra entidade, com a relação “um para um. No banco de dados, este campo é uma chave estrangeira. Na entidade, é uma instancia da entidade referenciada. 11 Package modelo; Import javax.persistence.*; Import java.10.Serializable; @Entity Public class Aluno implements Serializable { @Id @generatedValue(strategy=generationType.IDENTITY) Private int id; Private String nome; Private long ra; Private double ms1; Private double ms2; @oneToone Private Foto foto; //getters e setters aqui } Package modelo; Import javax.persistence.*; Import java.10.Serializable; @Entity Public class Foto implements Serializable { @Id @generatedValue(Strategy=genrationType.IDENTITY) Private int id; Private byte [] foto; @oneToone(mappedBy=”foto”) Private Aluno aluno; ‘’getters e setters aqui } Uso Main..... . . . Aluno a=em.find(Aluno.class, 12); Byte [ ] f=a.getFoto().getFoto(); . . Foto f= em.find(foto.class, 216); System.out.println(“O dono da foto é “+ f.getaluno().getNome()); @manyToOne: Indica que o atributo mapeia outra entidade com a relação “muitos para um” No banco de dados, este campo é uma chave estrangeira. Na entidade, ‘’e uma instancia da entidade referenciada. @onetomany Indica que o atributo contem um Set (conjunto) de entidades que a referenciam Este campo não possui representação em banco de dados. É preenchido em tempo de execução pelo JPA com uma consulta em SQL usando junção entre tabelas (Join) 12 Package modelo; Import javax.persistence.*; Import java.10.Serializable; @Entity import java.utiliSet; Public class Aluno implements Serializable { @Id @generatedValue(strategy=generationType.IDENTITY) Private int id; Private String nome; Private long ra; Private double ms1; Private double ms2; @oneToone Private Foto foto; @onetoMany (mappedBy= “aluno”) Private Set<Pagamento> pagamentos; //getters e setters aqui } Package modelo; Import javax.persistence.*; Import java.10.Serializable; @Entity Public class Pagamentos implements Serializable { @Id @generatedValue(Strategy=genrationType.IDENTITY) Private int id; Private double valor; Private String observações ; @ManyToOne Private Aluno aluno; ‘’getters e setters aqui } Uso Main . . 13 Pagamento p = em.find (pagamento.class,327); Aluno a=em.find(aluno.class,37); Set <Pagamentos> pagamentos=a.get pagamentos (); Iterator <Pagamentos> Iterator Pagtos=pagamentos.iterator(); While(iterator Pagtos.hasNext()); { Pagamentos p= iterator Pagtos.next(); System.out.println (p.getData()); } @ManyToMany: Indica que o atributo contém um Set(conjunto) de entidades que a referenciam com a relação “muitos para muitos”. No banco de dados este relacionamento é feito com o uso de uma tabela auxiliar. Aluno Id:integra(PK) Disciplina Id:integer(PK) Package modelo; Import javax.persistence.*; Import java.10.Serializable; @Entity Public class Aluno implements Serializable { @Id @generatedValue(strategy=generationType.IDENTITY) Private int id; Private String nome; Private long ra; Private double ms1; Private double ms2; } @OneToOne private Foto foto; @OneToMany(mappedBy="Aluno") private Set<Pagamento> pagamento; @ManyToMany private Set<Disciplina> disciplina; //getters e setters aqui 14 04/10/2010 Consulta em JPA – Exemplos Consulta que retorna um único resultado: private void consultaAlunoRA(){ try{ Query consulta = em.createQuery("SELECT a FROM Aluno a WHERE a.ra=:ra"); consulta.setParameter("ra", 12345); Aluno a = (Aluno) consulta.getSingleResult(); System.out.println("Aluno encontrado por RA: "); System.out.printf("RA: %d \n", a.getRa()); System.out.printf("Nome: %d \n", a.getNome()); } catch (NoResultException e) { System.out.println("Aluno não encontrado."); } catch (NonUniqueResultException e){ System.out.println("Mais de um aluno encontrado"); } } Consulta que retorna mais de um resultado private void consultaAlunoPorMedia(double media){ System.out.println("Consulta aluno por media: "); Query consulta = em.createQuery("SELECT a FROM Aluno a WHERE a.ms1 * 0.4 + a.ms2 * 0.6 > :media"); consulta.setParameter("media", media); List <Aluno> alunos = consulta.getResultList(); System.out.printf("\nAlunos encontrados com média final maior que %3.1f:\n", media); if(! aluno.isEmpty()){ for(Aluno a:alunos){ System.out.printf("Nome: %10s, MS1: %3.1f, MS2: %3.1f\n", a.getNome(), a.getMs1(), a.getMs2()); } } else { System.out.println("Nenhum aluno encontrado."); } } Paginação de resultados private void consultaPaginada(int alunoId){ System.out.println("Consulta com paginação de resultados:"); Query consulta; List <Pagamento> pagamentos; Aluno a = em.find(Aluno.class, alunoId); 15 int inicio = 0; int maximo = 3; int pagina = 1; do{ consulta = em.createQuery("SELECT p FROM Pagamento p WHERE p.aluno=:aluno ORDER BY p.observacoes"); consulta.setParameter(“aluno”, a); pagamentos = consulta.setMaxResults(maximo).setFirstResult(inicio).getResultList(); if(! pagamentos.isEmpty()){ System.out.printf("\nPag.: %d\n", pagina); for(Pagamento p:pagamentos){ System.out.printf("Observacoes: %s\n", p.getObservacoes()); } } inicio += maximo; pagina++; } while(! pagamentos.isEmpty()); } Consultas Nomeadas (Identificadas) São consultas pré-definidas nas classes de entidades e podem sereutilizadas em diferentes pontos da aplicação, o que facilita a sua manutenção. São declaradas atravez das seguintes anotações: @NomedQuery: Define uma consulta nomeada. @NomedQueries: Define um vetor de consultas nomeadas. Na entidade, antes da anotação @Empty, declare as consultas nomedas: @NomedQueries({ @NomedQuery(nome="consultaPorRa", query="SELECT a FROM Aluno a WHERE a.ra=:ra"); @NomedQuery(nome = "consultaPorMedia", query = "SELECT a FROM Aluno a WHERE a.ms1*0.4+a.ms2*0.6>:media"); Na aplicação, utilize as consultas nomeadas: Query consultas = em.createNomeQuery("consultaPorMedia"); consulta.setParameter("media",5); 18-10-2010 PG1 Exemplos de container BEA Web Logic Server Glass Fish da Sun Microsystems IBM Webphere JBoss Application Server Ocacle Aplication Server Alguns conceitos EJB-Enterprise JavaBeans 16 Componente de software padrão executado no lado do servidor(Camada de negócio) que encapsula a lógica que atende às necessidades de um domínio dentro de negócios. É utilizada a criação de aplicação corporativa distribuídas desenvolvidas em Java. Conteiner EJB É o ambiente responsável por gerenciar o ciclo de vida das instancias das classes Bean (Objetos EJB) Entro de um servidor de aplicação. Servidor de Aplicação Java EE Sistema que deve implementar os seguintes serviços: Enterprise Java Beans(Container EJB) Java Persistence(JPA) Java Message Service(JMS) Java Transaction Service / Java Transaction API (JTS/JTA) Servlets e Java Server Pages (JSP- Container Web) Java Naming and Directory Interface (JNDI). Disponibiliza também entre outros recursos: Pool de instâncias EJB Pool de conexões a bando de dados Controle de concorrências Conectividade remota Gerenciamento de segurança: o Autenticação (Identificação do usuário) o Autorização (Controle do que o usuário pode fazer) o Comunicação (Criptografia) Quando usar EJB em suas aplicações: Quando a aplicação deve ser estável, tanto por possuir um numero crescente de usuários, quanto quando há a necessidade de distribuir a aplicação em múltiplas maquinas. Quando transações são necessárias para garantir a integridade de dados. Quando a aplicação possuir um alto número de clientes. Como a lógica de negócio fica nos componentes do lado do servidor, a manutenção é facilitada. Os três tipos básicos de Enterprise Java Beans são: Entidades (JPA Entities) São persistentes, representam o modelo de dados e são gerenciadas pelo EntityManager Beans de Sessão (Session Beans) São freqüentemente utilizados para gerenciar as interações entre as entidades. Representam um fluxo de tarefas, um processo de negócio. Beans Baseados em Mensagens (Message Driver Beans) Recebem e processam mensagens na interação com outros aplicativos através de um serviço de mensagens (JMS). Normalmente implementam a interface MessageListener, implementando assim o método anMessage() onde se calcula a lógica de negócio. Tipos de Beans de Sessão Stateless SessionBean (Beam de sessão sem informações de estado) 17 Não mantêm nenhum estado conversacional entre cliente e o servidor. São mantidos em um pool de instâncias. Possuem um desempenho maior que os Beans de sessão com informações de estado. São utilizados para realizar tarefas que sejam realizadas em uma única chamada de método. Stateful Sesseion Bean (Bean de sessão o informações de estado) Mantêm o estado conversacional entre as chamadas de um cliente para o servidor, o que permite manter dados específicos ao cliente entre invocações de métodos. É uma extensão do aplicativo cliente. Não são mantidos em um pool de instancias. Ao invés disso, o container instancia o bean no momento em que o cliente solicita um. O bean atende apenas um cliente e é destruído quando o cliente encerra sua utilização. 25/10/2010 Componentes de um aplicativo que utiliza Session Bean Interface remota ou local Um cliente não tem acesso direto a implementação do bean de sessão. O cliente, ao invés disso, acessa uma interface desse bean. Os beans de sessão podem ser expostos por mais de uma interface e as intefaces podem ser: Interface remota, anotada com @Remote. Define quais os métodos que um cliente tem direito de acessar de fora do contêiner. Interface local, anotada com @Local. Define quais os métodos que um EJB pode acessar de dentro do mesmo contêiner. Desenho 1 Exemplo: package calculadora; import javax.ejb.remote; public interface Calculadora1 { public double soma (double a, double b); public double subtrai (double a, double b); public double multiplica (double a, double b); public double divide (double a, double b); 18 Classe do bean A classe do bean deve implementar alguma interface anotada como @Remote ou @Local. A classe do bean, por sua vez,e anotada com @Stateless ou @Stateful. Contem a lógica de negocio que é realizada pela implementação dos métodos da interface. Um EJB anotado com @Stateless não armazena informações a respeito do cliente que esteja atendendo. É disponibilizado em um pool de instâncias e apresenta um desempenho melhor em relação aos beans com informação de estado. Exemplo: package calculadora; importjavax.ejb.Stateless; @Stateless public class Calculdora1Beans implements Calculadora1 { public double soma (double a, double b) { return a + b; } public double subtrai (double a, double b) { return a - b; } public double multiplica (double a, double b) { return a * b; } public double divide (double a, double b){ return a / b; } } Cliente Remoto É a aplicação que se conecta ao servidor EJB por meio de injeção de dependência, que indica o ponto do código do aplicativo cliente onde o EJB será inserido. A injeção de dependentes é a anotação que instrui o contêiner a disponibilizar um objeto diretamente no código do cliente. Podem ser: @EJB: Injeta um objeto EJB (um bean session) @PersistenceContext: Injeta a EntityManager @ PersistenceUnit: Injeta um EntityManagerFactory Exemplo: package cliente; import javax.ejb.EJB; import calculadora.Calculadora1; public class ClienteCalculadora1{ //Injeção de dependencia @EJB private static Calculadora1 calc; public static void main(String args[]){ System.out.println("Iniciando o programa cliente"); System.out.println("Soma (3,4)=%6.2f\n",calc.soma(3,4)); System.out.println("subtrai(5,4)=%6.2f\n",calc.subtrai(5,4)); System.out.println("multiplica(2,3)=%6,2\n", calc.multiplica(2,3)) System.out.println("divide(4,3)=%(4,3)=%6.2f\n",calc.divide(4,3)) } } 19 Um bean de sessão com informações de estado atende um único cliente por todo seu ciclo de vida. Assim, ele pode armazenar dados temporários a respeito de seu cliente. Exemplo: package cliente; import javax.ejb.Remote; @Remote public interface Calculadora2{ public void novaConta(); public void soma(double d); public void subtrai (double d); public void multiplica(double d); public void divide(double d); public void obtemResultado(); } package claculadora; import javax.ejb.Stateful; @Stateful public interface Calculadora2Bean implements Calculadora2{ //Atributo que armazenam dados temporarios do cliente: private double memoria; public void novaConta(){ memoria = 0; } public void soma(double d){ memoria +=d; } public void subtrai(double d){ memoria -= d; } public void multiplica (double d){ memoria*=d; } public void divide(double d){ memoria/=d; } /* A anotação @Remote indica que a execução do próximo método é o fim da vida do bean */ @Remote public double obtemResultado(){ return memoria; } } 20 package cliente; import javax.ejb.EJB; import calculadora.Calculadora2; public class ClienteCalculadora2{ //Injeção de dependência: @EJB private static Calculadora2 calc; public static void main(String args[]){ System.out.println("iniciando o projeto cliente: "); calc.novaConta(); calc.soma(10); calc.divide(2); calc.multiplica(4); calc.subtrai(1); /*Metodo anotado com @Remote que instrui oonteiner a destruir o bean*/ System.out.println("Resultado:%6.2f\n", calc.obtemResultado()); } } Regras para se construir um bean de sessão: Deve possuir pelo menos uma interface A classe do bean deve ser concreta(não pode ser abstrata ou final) Deve ter um construtor sem parâmetros Uma classe bean de sessão pode ser uma subclasse de outro bean de sessão ou POJO Os métodos de negócios e os métodos de callback de ciclo de vida podem ser definidos em uma classe bean ou superclasse. Os nomes de métodos não podem começar com “ejb”. Por exemplo, não use “ejbCreate”como nome de método. Desenho 1 Desenho 2 21