Prof. Fellipe Araújo Aleixo fellipe.aleixo@ifrn.edu.br
A arquitetura Enterprise JavaBeans é uma arquitetura de componentes para o desenvolvimento e a implantação de aplicativos de negócio distribuídos baseados em componentes. Aplicativos escritos utilizando a arquitetura Enterprise JavaBeans são escalonáveis, transacionais e seguros com multiusuários. Esses aplicativos podem ser escritos uma vez e então implantados em qualquer plataforma de servidor que suporta a especificação Enterprise JavaBeans Sun Microsystems
Definição simplificada: Modelo padrão de componentes do lado do servidor para aplicativos de negócio distribuídos Modelo próprio para a construção de componentes do lado do servidor que representam processos do negócio Componentes distribuídos máquinas diferentes Distribuição de carga de processamento Maximização de confiabilidade
No EJB 3.0 a persistência deixou de fazer parte da plataforma, passando a ser especificada a parte Java Persistence API JPA JPA é uma abstração superior à API JDBC Os objetos são mapeados em tabelas de banco dados, de modo que possam ser consultados, carregados, atualizados ou removidos sem que necessário utilizar a API JDBC Mapeia objetos Java simples e comuns (POJOs Plain Old Java Objects) Beans de Entidade
Além do suporte a objetos distribuídos baseados em RMI, o EJB suporta também um sistema de mensagens assíncronas Uma mensagem é um pacote auto-contido de dados do negócio e cabeçalhos de roteamento de rede Mensagens assíncronas podem ser transmitidas entre um aplicativo e outro em uma rede, utilizando o Message-Oriented Middleware MOM O MOM assegura tolerância a falhas, escalabilidade, balanceamento de carga e suporte a transações
Embora cada fornecedor de um MOM utilize formatos e protocolos diferentes a semântica básica é a mesma e uma API Java é utilizada para criar, enviar e receber mensagens O EJB integra a funcionalidade do MOM ao seu modelo de componentes O EJB 3.0 suporta o sistema de mensagens assíncronas por meio do Java Message Service JMS Bean Orientados a Mensagens (MDB)
Java Connector Architecture JCA Um contêiner EJB 3.0 que suporta JCA 1.5 pode interagir com qualquer recurso compatível com a JCA 1.5 Contêiner EJB 3.0 MessageDrivenBean tipo XYZ JCA 1.5 Conector XYZ Sistema de Informações Corporativo Sistema de Mensagens XYZ
Tendência na computação distribuída Aplicativos modulares autodescritos e autocontidos que podem ser publicados, localizados e invocados pela Web Independentes de plataforma SOAP gramática XML para protocolo de aplicativo WSDL gramática XML para definição de interface O EJB 3.0 permite o desenvolvimento de Serviços Web através da API JAX-WS
Para a construção de aplicações corporativas inicialmente a de se compreender as arquiteturas propostas Beans de entidade Componente Enterprise Beans
Os beans de entidade na especificação Java Persistence 1.0 estão disponíveis como POJOs e são mapeados para tabelas de bancos de dados As entidades podem ser alocadas, serializadas e enviadas pela rede, diferentemente dos EJBs Os beans de entidade espelham os objetos do mundo real
Implementando um bean de entidade: Definir uma classe bean Qual atributo funcionará como identificador Chave primária (identificador) Fornece um identidade à classe bean Classe bean Pode conter lógica do negócio, mas normalmente define as informações necessariamente persistentes
A classe bean é um POJO que não tem de implementar nenhuma interface e nem mesmo ser serializável Deve ser sinalizada com a anotação @javax.persistence.entity Deve ter um campo ou método acessador que é designado como a chave primária, com a anotação @javax.persistence.id
Para interagir com beans de entidade, a Java Persistence API fornece o EntityManager Todo acesso às entidades passa por este serviço Este, fornece uma API de consulta e métodos de ciclo de vida para a entidade A JPA pode ser utilizada independentemente do servidor de aplicação Enterprise Edition
import javax.persistence.*; @Entity @Table(name= ALUNO ) public class Aluno { private int id; private String nome; private String matric; // matrícula @Id @GeneratedValue @Column(name= ALUNO_ID ) public int getid() { return id; } public void setid(int id) { this.id = id; } @Column(name= ALUNO_NOME ) public String getnome() { return nome; } public void setnome(string n) { this.nome = n; } } @Column(name= ALUNO_MAT ) public String getmatricula() { return matric; } public void setmatricula(string mat) { matric = mat; }
Os beans de entidade são agrupados em um conjunto finito de classes chamado unidade de persistência O serviço EntityManager gerencia uma unidade de persistência específica Uma unidade de persistência deve estar associada a um banco de dados particular Informações essas armazenadas em um descritor de implantação (persistence.xml)
Dois tipos fundamentais: Beans de sessão session beans Acessados utilizando vários protocolos de objetos distribuídos (RMI-IIOP) São extensões do aplicativo que gerenciam processos ou tarefas Beans orientados a mensagens message-driven beans Processam mensagens assincronamente a partir de sistemas como o JMS
Interface Remota - @javax.ejb.remote Define os métodos do bean de sessão que são acessíveis por aplicativos de fora do contêiner Interface Local - @javax.ejb.local Define os métodos do bean de sessão acessíveis apenas por outros beans executando na mesma JVM Interface endpoint - @javax.jws.webservice Define os métodos de negócio que são acessíveis por aplicativos fora do contêiner por meio de SOAP
Interface message - @javax.ejb.messagedriven Define os métodos por meio dos quais os sistemas de troca de mensagens podem entregar mensagens Classe bean Contém a lógica do negócio e precisa ter pelo menor uma interface remota, local ou endpoint @javax.ejb.stateless sessão sem estado @javax.ejb.stateful sessão com estado
Exemplo - CalculadoraRemote: import javax.ejb.remote; @Remote public interface CalculadoraRemote { public int soma(int x, int y); public int subtrai(int x, int y); }
Exemplo - CalculadoraBean: import javax.ejb.*; @Stateless public class CalculadoraBean implements CalculadoraRemote { public int soma(int x, int y) { return x + y; } public int subtrai(int x, int y) { return x y; } }
De que maneira o contêiner EJB sabe como tratar a segurança, transações e demais serviços? (1) padrões (default) intuitivos (2) anotações (3) descritores de implantação em XML Exemplo de padrões: O atributo de transação é REQUIRED A semântica de segurança é UNCHECKED
Os clientes acessam os EJBs pelas interfaces: Remota de fora do contêiner Local executando na mesma JVM O contêiner conectar a interface à instância da classe bean em tempo de execução Exemplo: como funciona no JBoss? Proxy Stub instância com a qual o cliente interage Gerado dinamicamente em tempo de implantação Redireciona a invocação do método para o contêiner
Problema exemplo: locação de um filme (1) são utilizados beans de entidade representam os conceitos do domínio do problema Cliente Filme Locacao (2) o fluxo de tarefas é modelado com beans de sessão AgenteLocacao
O aplicativo cliente faz a locação de um filme... // Obtém os dados necessários da GUI String cartaocredito = textfield1.gettext(); int filme = Integer.parseInt(textField2.getText()); Cliente cliente = new Cliente(nome, endereco, fone); // Cria uma nova sessão AgenteLocacao (remote) AgLocacaoRemote agloc =... // acesso ao JNDI agloc.setcliente(cliente); agloc.setfilmeid(filme); // Utiliza o cartão de crédito para pagar a locação Locacao locacao = agloc.crialocacao(cartaocredito);
@Stateful public class AgenteLocacaoBean implements AgLocacaoRemote { @PersistenceContext private EntityManager entitymanager; @EJB ProcessaPagamentoRemote caixa; private Cliente cliente; private Filme filme; public setcliente(cliente cliente) { entitymanager.persist(cliente); this.cliente = cliente; } public setfilmeid(int filmeid) { filme = entitymanager.find(filme.class, filmeid); } public Locacao crialocacao(string cartao) throws IncompleteConversationalState { if (cliente == null filme == null) { /* lança exceção */ } try { Locacao locacao = new Locacao(filme, cliente); entitymanager.persist(locacao); caixa.pagacredito(cliente,cartao, locacao.valor()); return locacao; } catch (Exception ex) { throw new EJBException(); } }
As referências ao EntityManager e ao EJB ProcessaPagamento são injetadas pelo contêiner A injeção é solicitada através das anotações @EJB @PersistenceContext Perceba a importância do controle de transação no método que cria a locação
Beans de sessão com informações de estado mantém o estado conversacional quando utilizador por um cliente O estado conversacional é mantido na memória O estado conversacional só é mantido pelo tempo em que o aplicativo cliente está ativamente utilizando o bean Para um beans de sessão sem informações de estado cada método é independente e só são utilizados os dados passados por parâmetro
O estado de um bean de sessão com informação de estado por ser salvo temporariamente em disco passivação Isto acontece se o contêiner necessitar de espaço para a alocação de novos EJBs Beans de sessão sem informação de estado fornecem um melhor desempenho e consomem menos recursos do servidor
Aplicando beans baseados em mensagem Servem de ponto de integração com outros aplicativos, até mesmo sistemas legados Cumprem o mesmo papel que os beans de sessão sem informações de estado gerenciar o fluxo de tarefas A tarefa é iniciada por uma mensagem assíncrona Método onmessage()
@MessageDriven public class ProcessaLocacao implements javax.jms.messagelistener { @PersistenceContext private EntityManager entitymanager; @EJB ProcessaPagamentoRemote caixa; public void onmessage(message message) { try { MapMessage locacaomsg = (MapMessage) message; Cliente cliente = (Cliente) locacaomsg.getobject( cliente ); int filmeid = locacaomsg.getint( filmeid ); String cartao = locacaomsg.getstring( cartao ); } } entitymanager.persist(cliente); Filme filme = entitymanager.find(filme.class, filmeid); Locacao locacao = new Locacao(filme, cliente); entitymanager.persist(locacao); caixa.pagacredito(cliente, cartao, locacao.valor()); } catch (Exception ex) { throw new EJBException(); }
O contêiner EJB da mesma forma que o contêiner Web é um dos componentes de um servidor de aplicação JEE O contêiner EJB Gerencia o ciclo de vida dos beans Fornece serviços como transações, segurança, concorrência e atribuição de nomes em tempo de execução Implementa a interface javax.ejb.ejbcontext
Os servidores EJB gerenciam os recursos utilizados pelos beans Como utilizam a memória Threads Conexões de banco de dados Poder de processamento Entre outros...
Serviços primários suportados pelo servidor: (1) Concorrência (2) Gerenciamento de transação (3) Persistência (4) Distribuição de objetos (5) Atribuição de nomes (6) Segurança Serviços adicionais suportados: (i) sistema de mensagens assíncronas e (ii) serviço e temporização
Idéia de escala: Sistema corporativo milhares ou mesmo milhões de objetos em uso simultaneamente Mecanismos para gerenciar beans em execução: Pool de instâncias instâncias carregadas na memória, prontas para serem compartilhadas Ativação conservação de instâncias com estado Gerência de conexões Java EE Connector Architecture
Estados de um bean de sessão sem informações de estado: Sem estado ainda não foi instanciada Pooled foi instanciada pelo contêiner mas ainda não foi associada a uma solicitação EJB Ready (pronto) foi associada a uma solicitação EJB e está pronta para responder a invocações Como não guardam informações de estado podem ser compartilhados
MDBs e Pool de instâncias: Não guardam estado para uma solicitação específica, como os beans de sessão sem informação de estado Na maioria dos contêineres, cada tipo de bean baseado em mensagem tem o seu próprio pool de instâncias JMS-MDBs se inscrevem em um destino específico Um destino equivale a um endereço utilizado para enviar e receber mensagens Ao receber uma mensagem para um destino o contêiner EJB determina que JMS-MDB, que está no pool relativo aquele destino, irá tratar a mensagem
Mecanismo de ativação: Aplicado a beans de sessão com informações de estado manutenção do estado conversacional Se um bean de sessão com informações de estado for retirado da memória, o estado do mesmo é serializado e armazenado em disco passivação O cliente não tem a informação da passivação Ativar um bean é o ato da restauração do estado de uma instância de um bean que sofreu a passivação
Principais serviços gerenciados pelo contêiner: (1) Concorrência (2) Transações (3) Persistência (4) Objetos distribuídos (5) Sistema de mensagens assíncronas (6) EJB Timer Service (7) Atribuição de nomes (8) Segurança
Aspectos da especificação EJB 3.0: Como os servidores EJB tratam a concorrência, os métodos de um bean não precisam ser threadsafe Proíbe o uso da palavra-chave syncronized Proíbe que os beans criem seus próprios threads Os beans de sessão não suportam acesso concorrente
Concorrência com beans de entidade Representam dados que são compartilhados Para tornar possível o acesso concorrente o provedor de persistência precisa bloquear os dados Na especificação JPA é criada uma cópia da instância do bean por transação Concorrência com beans de mensagens Processamento de mais de uma mensagem por vez diferentes instâncias do MDB podem trabalhar simultaneamente
Conjunto atômico (indivisível) de tarefas Exemplo anterior: (a) criação de uma locação e (b) realização do pagamento da referida locação Gerenciadas automaticamente pelo contêiner, sem a necessidade de programação nenhuma Nos beans pode haver a declaração de atributos transacionais, usados em tempo de implantação O EJB provê também um mecanismo para o gerenciamento explícito de transações
Beans de entidade: São implementados como POJOs Tem o seu estado salvo em um banco de dados Podem ser criados fora do contêiner Gerenciados pelo EntityMananer Podem estar acoplados ao gerenciamento do contêiner ou desacoplados Uma vez desacoplados, podem ser novamente acoplados através do método merge alterações sincronizadas com o banco
O cliente tem acesso a um EJB através da interface remota ou interface endpoint Os demais elementos são abstraídos, inclusive o mecanismo de suporte a objetos distribuídos Na especificação EJB 3.0, os beans de sessão podem ser acessados através de RMI-IIOP Também é requerido o suporte ao SOAP 1.2 pela API JAX-RPC
O contêiner EJB rotea de forma confiável mensagens de clientes JMS para JMS-MDBs Mensagens corporativas podem ser serializadas e armazenadas em disco ao em banco de dados até que possam ser adequadamente entregues O armazenamento secundário das mensagens permite a tolerância a falhas, em caso de travamento do servidor EJB O sistema de mensagens assíncronas é transacional
Utilizado para agendar notificações a serem enviadas a beans Serviços de temporização são úteis em vários domínios de problemas: (a) vencimento de prestações, (b) expiração de cadastros de usuários e etc. Temporizadores podem ser configurados em todo o tipo de EJB, exceto beans de sessão com informação de estado
Fornece aos clientes um mecanismo para localizar recursos ou objetos distribuídos Serviços fornecidos: Vinculação de objeto Associação de um objeto distribuídos a um identificador API de pesquisa Fornece ao cliente uma interface para o sistema de atribuição de nomes No EJB é obrigatório o uso da JNDI suporta qualquer tipo de serviços de diretórios e de atribuição de nomes
Exemplo de utilização da API JNDI: javax.naming.context jndicontext = new javax.naming.initialcontext(); Object ref = jndicontext.lookup( AgLocacaoRemote ); AgLocacaoRemote agente = (AgLocacaoRemote) PortableRemoteObject.narrow(ref, AgLocacaoRemote.class); // o método acima não é mais necessário, mas ilustra // o momento da criação da classe Proxy Stub... Locacao locacao = agente.criarlocacao(...);
Os servidores Enterprise JavaBeans suportam três tipos de segurança: Autenticação Validar a identidade do usuário Suporte a várias mecanismos (tela de login, cartões de identificação digital, certificados de segurança, etc.) Autorização Diretivas definem o que os usuários podem, ou não, fazer Comunicação segura Definição de um canal de comunicação seguro