Enterprise Java Beans (III) Professor: Diego Passos UFF dpassos@ic.uff.br Baseado no material original cedido pelo Professor Carlos Bazilio
Última Aula Disponibilização do EJB no container. Arquivo descritor. Opções de Segurança. Empacotamento do EJB. Utilização do Bean no lado cliente. Clientes locais vs. Clientes Remotos. Localização de interfaces home. Criação de beans. Invocação de métodos.
Nesta Aula Anotações. E como são usadas para implementar EJBs. Especificidades das beans de sessão. Beans stateless. Beans statefull. Gerenciamento (pelo container). Suporte transacional.
Anotações Atualmente, Java inclui uma funcionalidade chamada de Annotations. São pequenas notas deixadas pelo programador ao longo do código. Metadados do código-fonte. São usadas para vários objetivos: Como informações ao compilador. Supressão de warnings, detecção de erros,... Para geração de artefatos de disponibilização. Geração de XMLs. Processamento em tempo de execução.
Anotações: Sintaxe Básica Anotações são iniciadas pelo caracter @. Por convenção, anotações geralmente aparecem em uma linha sozinhas. Há exceções. Anotações contém um nome. @Override void mysupermethod(){...}
Anotações: Sintaxe Básica (II) Anotações podem incluir elementos. Listados entre parêntesis. Elementos podem ou não ter nomes. Elementos sempre têm valores. @Author( name = Benjamin Franklin", date = "3/27/2003" ) class MyClass() {... } @SuppressWarnings(value = "unchecked") void mymethod() {... } @SuppressWarnings("unchecked") void mymethod() {... }
Anotações: Sintaxe Básica (III) Anotações podem incluir elementos. Listados entre parêntesis. Elementos podem ou não ter nomes. Elementos sempre têm valores. @Author( name = Benjamin Franklin", date = "3/27/2003" ) class MyClass() {... } @SuppressWarnings(value = "unchecked") void mymethod() {... } @SuppressWarnings("unchecked") void mymethod() {... }
Anotações: Sintaxe Básica (IV) Anotações estão associadas a partes do código próximas. Exemplo: a declaração que segue a anotação. A um mesmo trecho de código, podemos associar múltiplas anotações. @Author(name = "Jane Doe") @EBook class MyClass {... }
Anotações: Definindo um tipo de Anotação Em muitos casos, desenvolvedores só precisam utilizar tipos pré-definidos de anotação. Às vezes, no entanto, é interessante definir novos tipos. Exemplo: documentação de classes. public class Generation3List extends Generation2List { // Author: John Doe // Date: 3/17/2002 // Current revision: 6 // Last modified: 4/12/2004 // By: Jane Doe // Reviewers: Alice, Bill, Cindy } // class code goes here
Anotações: Definindo um tipo de Anotação (II) Pode-se definir uma anotação para substituir os comentários. @interface ClassPreamble { String author(); String date(); int currentrevision() default 1; String lastmodified() default "N/A"; String lastmodifiedby() default "N/A"; // Note use of array String[] reviewers(); }
Anotações: Definindo um tipo de Anotação (III) Código anotado: @ClassPreamble ( author = "John Doe", date = "3/17/2002", currentrevision = 6, lastmodified = "4/12/2004", lastmodifiedby = "Jane Doe", // Note array notation reviewers = {"Alice", "Bob", "Cindy"} ) public class Generation3List extends Generation2List { // class code goes here }
Anotações: Tipos Padronizados Existem vários tipos de anotação padronizados pela linguagem. Anotação @Deprecated Indica que um elemento está obsoleto e não deve mais ser usado. Elementos: classes, métodos, atributos. Uso de elemento anotado com @Deprecated causa warning de compilação. @Deprecated static void deprecatedmethod() {... }
Anotações: Tipos Padronizados (II) Anotação @Override Indica que elemento (método, tipicamente) deve sobrecarregar um correspondente na superclasse. Não é necessário, mas evita erros. Se método anotado não sobrecarrega outro, compilador gera um erro. // Se não houver um método com mesma assinatura na superclasse, // compilador acusa erro. @Override int overriddenmethod() {...}
Anotações: Tipos Padronizados (III) Anotação @SupressWarnings Diz ao compilador para suprimir mensagens de warning que resultariam da compilação. Útil quando estamos cientes do warning e julgamos que ele não é relevante para aquela situação. @SuppressWarnings("deprecation") void usedeprecatedmethod() { // Tentamos usar um método marcado como deprecated. // Sabemos disso e assumimos a responsabilidade. objectone.deprecatedmethod(); }
Anotações: Tipos Padronizados (IV) Anotação @SupressWarnings Há dois tipos de warnings em Java: deprecation e unchecked. É possível desativar múltiplos warnings de uma só vez. @SuppressWarnings({"deprecation, unchecked }) void usedeprecatedmethod() { // Tentamos usar um método marcado como deprecated. // Sabemos disso e assumimos a responsabilidade. objectone.deprecatedmethod(); }
Anotações: Processamento Quando um código em Java é compilado, as anotações são processadas pro plug-ins do compilador. Chamados também de processadores de anotações. Estes processadores podem gerar: Mensagens durante a compilação. Outros arquivos Java. Outros recursos (como arquivos XML). Os artefatos gerados pelos processadores podem também ser compilados e processados. Podem também alterar o código anotado. Note que as anotações podem ser incluídas nas classes compiladas. Ficam disponíveis em tempo de execução.
Anotações: Usos Típicos Anotações são utilizadas pelo compilador, como já visto. Mas é também comum o uso das mesmas em Frameworks. Podem gerar configurações a partir de anotações do código. Evitam a necessidade de referenciar classes, métodos em arquivos externos. Exemplos de frameworks (já vistos no curso) que permitem o uso de anotações: Servlets: anotação @WebServlet(value= /url ) Define mapeamento de URL para o servlet anotado. JSF (beans gerenciadas): anotações @ManagedBean(name= nome ), @RequestScope, @SessionScope, e @ApplicationScope Definem que classe anotada é uma bean gerenciada com um escopo específico.
EJB 3 EJB 3 difere das versões anteriores pelos seguintes fatores: Uso de POJO s (Plain Old Java Objects); Classes simples em Java; O modelo inicial de componentes (interfaces Home e descritores XML, por exemplo) foi substituído por objetos e serviços EJB oferecidos pelo contêiner; Anotações em Java; Permitem a definição de atributos de código e opções de configuração diretamente no código Java; Injeção de Dependência. Referência: http://java.sun.com/products/ejb
EJB 3: Exemplos da Primeira Aula Nas duas primeiras aulas, vimos a maneira original de criar/manipular EJBs. Implementação de uma EJB precisa dos seguintes passos: Definição das interfaces cliente (local e remota). Definição das interfaces home (local e remota). Implementação do bean. Criação do deployment descriptor. Criação de arquivos de configuração específicos do container. Criação das classes geradas pelo container. Empacotamento da EJB em um arquivo.jar. Como é este processo na especificação EJB 3.0? Definição das interfaces cliente (local e remota). Implementação do bean. Compilação e empacotamento.
EJB 3: Criação da Interface Cliente (Remota) Não precisa estender a interface EJBObject. Utiliza a anotação @Remote. Opcional se houver apenas a interface remota. É uma POJO. import com.oreilly.jent.ejb.nosuchpersonexception; @Remote public interface ProfileManager { public Profile getprofile(string acctname) throws NoSuchPersonException; }
EJB 3: Criação da Interface Cliente (Local) Não precisa estender a interface EJBLocalObject. Utiliza a anotação @Local. Opcional se houver apenas a interface local. É uma POJO. Pode estender a interface remota, por exemplo. import com.oreilly.jent.ejb.nosuchpersonexception; @Local public interface ProfileManagerLocal extends ProfileManager { }
EJB 3: Implementação da Bean Utiliza várias anotações: @Stateless: indica EJB de Sessão Stateless. @Remote: indica que a EJB terá interface cliente remota. @Local: indica que a EJB terá interface cliente local. import javax.ejb.*; @Stateless @Remote(ProfileManager.class) @Local(ProfileManagerLocal.class) public class ProfileManagerBean implements ProfileManagerLocal { }...
EJB 3: Implementação da Bean (II) Não é necessário implementar a interface SessionBean. Consequências: Não é necessário implementar os métodos ejbcreate(), ejbpassivate(),..., a menos que precisemos deles. import javax.ejb.*; @Stateless @Remote(ProfileManager.class) @Local(ProfileManagerLocal.class) public class ProfileManagerBean implements ProfileManagerLocal { }...
import javax.ejb.*; @Stateless EJB 3: Implementação da Bean (III) Se precisarmos dos métodos de gerência do ciclo de vida, podemos dar quaisquer nomes a eles. No entanto, devemos identificá-los com anotações: @Remote(ProfileManager.class) @Local(ProfileManagerLocal.class) public class ProfileManagerBean implements ProfileManagerLocal { } @PostConstruct @PreDestroy @PostActivate @PrePassivate...
EJB Tipos de Beans Como visto na primeira aula, há três tipos de EJBs. EJBs de sessão. EJBs de entidade. EJBs orientadas à mensagens. A diferença entre os tipos de EJB está no tipo de funcionalidade que cada uma oferece. Especificamente, as EJBs de sessão se prestam a fornecer um conjunto bem definido de funcionalidades a clientes. Clientes obtém uma referência a uma EJB de sessão. Pedem um ou mais serviços.
EJB Beans de Sessão Beans de sessão recebem este nome pelo seu ciclo de vida típico. Elas não são persistentes. Seu ciclo de vida em geral é definido por sessões de uso. Beans de sessão podem ser subdivididas em mais duas classificações: Stateless Session Beans: beans de sessão que não guardam estado. Stateful Session Beans: beans de sessão que guardam estado.
EJB Beans de Sessão Stateless Estas beans não guardam estado relacionado ao cliente entre chamadas dos seus métodos. O resultado de um método não depende das chamadas anteriores feitas pelo cliente. Como estas beans não guardam estado, suas instâncias são intercambiáveis. Qualquer instância pode ser usada a qualquer momento para tratar pedidos de qualquer cliente. Container pode guardar um pool de instâncias. Ao ser requisitada por um cliente, container retorna qualquer instância do pool. Note que declarar uma bean como stateless não garante esta característica. É tarefa do desenvolvedor garantir isso. Container simplesmente assume como verdade.
EJB Beans de Sessão Stateful Estas beans armazenam estado da interação com o cliente. Execução de métodos pode alterar o estado interno da bean. Instâncias das beans pertencem a seus clientes específicos. Não podem ser usadas por outros clientes. Cliente dono de uma instância só a perde quando ativamente libera o recurso, ou quando a referência expira.
EJB Stateful vs. Stateless Vamos ilustrar a diferença entre as versões stateful e stateless com um exemplo. O exemplo utilizado na aula anterior, do ProfileManagerBean, era um exemplo de bean stateless. Ele recebia requisições para encontrar um perfil. Ele retornava o resultado na forma de objetos do tipo Profile. A partir daí, interação do cliente é com o objeto Profile. Suponha, no entanto, que desejamos transformar o próprio perfil em uma bean de sessão. Cliente requisita o carregamento do perfil. Bean carrega o estado. Métodos da bean permitem manipulação do perfil. Exemplo de uma bean de sessão stateful.
EJB Bean de Sessão Stateful Outro Exemplo Exemplo do tutorial da sun: http://docs.oracle.com/javaee/5/tutorial/doc/bnbod.html Suponha um sistema web de vendas de livro que utiliza o conceito de carrinho de compras. Queremos implementar o carrinho de compras como uma EJB de Sessão. O carrinho deve ser capaz de manipular o conjunto de livros pretendidos pelo cliente. Adicionar livros. Remover livros. Listar o conteúdo do carrinho. Note que este é um exemplo claro de um bean stateful. Após a chamada de um dos métodos de negócio, estado da bean é alterada. Uma instância da bean deve ser associada a seu cliente, e apenas a ele.
EJB Bean de Sessão Stateful Outro Exemplo (Interface) Neste exemplo, declaramos uma interface remota. Listamos os métodos de negócio. package com.sun.tutorial.javaee.ejb; import java.util.list; import javax.ejb.remote; @Remote public interface Cart { } public void initialize(string person) throws BookException; public void initialize(string person, String id) throws BookException; public void addbook(string title); public void removebook(string title) throws BookException; public List<String> getcontents(); public void remove();
EJB Bean de Sessão Stateful Outro Exemplo (Bean) A implementação define que a bean é stateful através da anotação @Stateful. Ela implementa a interface Cart (que é remota). package com.sun.tutorial.javaee.ejb; import java.util.arraylist; import java.util.list; import javax.ejb.remove; import javax.ejb.stateful; @Stateful public class CartBean implements Cart { String customername; String customerid; List<String> contents;...
EJB Bean de Sessão Stateful Outro Exemplo (Bean) Devemos implementar os métodos de negócio, normalmente. public void initialize(string person) throws BookException { if (person == null) { throw new BookException("Null person not allowed."); } else { customername = person; } customerid = "0"; contents = new ArrayList<String>(); }...
EJB Bean de Sessão Stateful Outro Exemplo (Bean) Podemos implementar métodos de ciclo de vida da bean, se necessário. Basta anotar métodos quaisquer com as anotações apropriadas. @PostActivate public void whenactivated() {... } @PrePassivate public void whenpassivate() {... }...
EJB Bean de Sessão Stateful Outro Exemplo (Bean) Métodos anotados com a anotação @Remove podem ser chamados pelo cliente para remover uma bean. Quando isso ocorre, o cliente abre mão da bean. @Remove public void remove() { } Container remove a bean. contents = null;
EJB Gerenciamento de Beans de Sessão O gerenciamento das beans de sessão pelo container depende do tipo de bean. Stateless. Stateful. Beans stateless tipicamente utilizam esquema de pool. Container instancia várias inicialmente e guarda os objetos em um pool. A medida que novas requisições são feitas para seu serviço JNDI, container devolve instâncias disponíveis no pool. Se o número de acessos simultâneos cresce, container pode acrescentar mais instâncias ao pool. Container também tem liberdade para decidir se pode/deve descartar instâncias.
EJB Gerenciamento de Beans de Sessão (II) Beans Stateful tem gerenciamento diferente. Estão associadas aos clientes que a criaram. Por isso, são tipicamente criadas sob demanda. Mas o container pode manter um pool de instâncias também. Instâncias semi-prontas. Container só chama o método ejbcreate() (se houver), quando o cliente solicita a criação. De toda forma, container não pode simplesmente remover uma instância de uma bean stateful. Instância deve permanecer criada e associada a um cliente até que ela expire ou que o cliente chame o método remove().
EJB Gerenciamento de Beans de Sessão (III) Beans Stateful também podem ser colocadas em memória secundária (Passivate) e trazidas de volta (Activate). Operações realizadas pelo container caso haja necessidade de liberar recursos (como memória). Quando uma bean é colocada em memória secundária, o container necessariamente chama o método ejbpassivate() da bean imediatamente antes. Ou o método anotado com a anotação @PrePassivate, se houver. Método deve liberar recursos não-serializáveis da bean.
EJB Gerenciamento de Beans de Sessão (IV) Beans Stateless não são colocadas em memória secundária (e, por consequência, não são re-ativadas). Logo, não necessitam dos métodos ejbpassivate ou ejbactivate. Ou versões anotadas. O motivo é simples: Como elas não guardam estado e instâncias são intercambiáveis, container pode simplesmente destruir instâncias e criar novas quando necessário.
EJB Suporte Transacional Um dos serviços fornecidos pelos containers EJB é o suporte a transações. Em geral, este suporte não é relevante às beans de sessão. Elas normalmente não representam dados persistentes compartilhados. E, no caso das beans stateful, só podem ser acessadas por um cliente por vez. Mas algumas vezes, beans de sessão stateful são utilizadas para intermediar o acesso a bases de dados remotas. Neste caso, é importante saber quando começa e termina uma transação. Clientes podem fazer diveras operações e quererem, ao final, dar um roll-back. Ou simplesmente um commit.
EJB Suporte Transacional (II) Por isso, a API do EJB dá suporte a operações transacionais nas beans de sessão stateful. Para ter este suporte, a bean deve implementar a interface javax.ejb.sessionsynchronization. Ao realizar a implementação desta interface, a bean sinaliza ao container que quer ser avisada dos eventos de início e fim de uma transação. A interface requer implementação de 3 métodos: afterbegin(): chamado logo após o início de uma transação. Permite ao bean alocar recursos para atender à transação. beforecompletion(): Permite ao bean desalocar recursos. aftercompletion(boolean): determina se deve ser feito um commit ou um roll-back da operação.