Docsity
Docsity

Prepare-se para as provas
Prepare-se para as provas

Estude fácil! Tem muito documento disponível na Docsity


Ganhe pontos para baixar
Ganhe pontos para baixar

Ganhe pontos ajudando outros esrudantes ou compre um plano Premium


Guias e Dicas
Guias e Dicas


Apostila EJB, que fala sobre Enterprise Java Beans., Manuais, Projetos, Pesquisas de Algoritmos

Apostila sobre EJB. Fala sobre Enterprise Java Beans.

Tipologia: Manuais, Projetos, Pesquisas

2019

Compartilhado em 24/08/2019

cleverton-heusner-9
cleverton-heusner-9 🇧🇷

5

(1)

1 documento

1 / 30

Toggle sidebar

Esta página não é visível na pré-visualização

Não perca as partes importantes!

bg1
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17
pf18
pf19
pf1a
pf1b
pf1c
pf1d
pf1e

Pré-visualização parcial do texto

Baixe Apostila EJB, que fala sobre Enterprise Java Beans. e outras Manuais, Projetos, Pesquisas em PDF para Algoritmos, somente na Docsity!

Este tutorial contém material (texto, código, imagens) produzido por Helder da Rocha em outubro de 2013 e poderá ser usado de acordo com os termos da licença Creative Commons BY-SA (Attribution- ShareAlike) descrita em http://creativecommons.org/licenses/by-sa/3.0/br/legalcode. O texto foi elaborado como material de apoio para treinamentos especializados em linguagem Java e explora assuntos detalhados nas especificações e documentações oficiais sobre o tema, utilizadas como principais fontes. A autoria deste texto é de inteira responsabilidade do seu autor, que o escreveu independentemente com finalidade educativa e não tem qualquer relação com a Oracle. O código-fonte relacionado aos tópicos abordados neste material estão em: github.com/helderdarocha/javaee7-course github.com/helderdarocha/CursoJavaEE_Exercicios github.com/helderdarocha/ExercicioMinicursoJMS github.com/helderdarocha/JavaEE7SecurityExamples

www.argonavis.com.br

R672p Rocha, Helder Lima Santos da, 1968- Programação de aplicações Java EE usando Glassfish e WildFly. 360 p. 21cm x 29.7cm. PDF. Documento criado em 16 de outubro de 201 3. Atualizado e ampliado entre setembro e dezembro de 2016. Volumes (independentes): 1: Introdução, 2: Servlets, 3: CDI, 4: JPA, 5: EJB, 6: SOAP, 7: REST, 8: JSF, 9: JMS, 10: Segurança, 11: Exercícios.

  1. Java (Linguagem de programação de computadores). 2. Java EE (Linguagem de programação de computadores). 3. Computação distribuída (Ciência da Computação). I. Título. CDD 005.13’

1 Enterprise JavaBeans

Enterprise JavaBeans são componentes que encapsulam a lógica de negócios de uma aplicação. Implementam serviços síncronos e assíncronos, podem exportar uma interface para clientes locais, mas também para clientes remotos usando protocolos de objetos remotos (IIOP) ou Web Services (SOAP). Instâncias de EJBs têm o ciclo de vida controlado em tempo de execução pelo container no qual ele está instalado, que também disponibiliza o acesso a serviços de segurança, transações, agendamento, concorrência, sincronização de estado, distribuição e outros de forma transparente. O desenho abaixo situa os Enterprise JavaBeans (session beans e message-driven beans) dentre os outros componentes de uma aplicação Java EE Enterprise JavaBeans são JavaBeans, ou POJOs – um objeto Java qualquer contendo um construtor default (sem argumentos), atributos encapsulados (private) e acessíveis através de métodos get/set. Existem dois tipos de EJBs:

  • Session beans
  • Message-driven beans

2 Session Beans

Session beans são componentes de negócios que exportam uma interface de serviços. Eles representam uma sessão de comunicação com um cliente (que não necessariamente corresponde a uma sessão Web). Um session bean deve ser criado quando houver interesse em fornecer uma interface de serviços. Esta interface pode ser local (acessível dentro da mesma aplicação) ou remota (acessível de outras aplicações ou mesmo de outras máquinas). É possível ainda exportar uma interface para clientes SOAP. A interface é definida por uma coleção de métodos. Existem diversas formas de declarar uma interface para um session bean:

  • Interface local usando no-interface view: o bean é acessível localmente, apenas para clientes da mesma aplicação. A interface de serviços consiste de todos os métodos do bean (inclusive os herdados de suas superclasses).
  • Interface local declarada usando @Local: o bean implementa uma ou mais interfaces Java que contém todos os métodos de sua interface de serviços que podem ser acessadas localmente por clientes da mesma aplicação.
  • Interface remota (para clientes IIOP) declarada usando @Remote: o bean implementa uma ou mais interfaces que contém todos os métodos de sua interface de serviços que acessíveis por clientes locais e clientes em outras aplicações, servidores ou máquinas.
  • Interface remota (para clientes SOAP) declarada usando @WebService: o bean implementa uma interface Java que declara os métodos exportados ou marca-os com @WebMethod no próprio bean.

2.1 Tipos de session beans

Existem três tipos de session beans:

  • Stateful Session Beans – usado para comunicação que precisa preservar o estado do cliente entre chamadas de métodos do bean.
  • Stateless Session Beans – usado para comunicação que não precisa manter o estado do cliente.
  • Singleton Session Beans – usado para comunicação que precisa compartilhar o estado entre diversos clientes.

Se esse cliente está continuando um diálogo iniciado anteriormente, o estado anterior do bean que ele usou é recuperado. Se houver um método anotado como @PostActivate ele é chamado após a ativação. 2.1.2 Stateless Session Beans Stateless session beans modelam diálogos que consistem de apenas uma requisição. Como não mantém estado do diálogo, todas as instâncias da mesma classe são equivalentes e indistinguíveis. Qualquer instância disponível de um session bean pode servir a qualquer cliente. Session Beans podem ser guardados em pool, reutilizados e passados de um cliente para outro em cada chamada. A forma mais simples de criar um stateful session bean é usando o estilo no-interface view, anotando a classe com @Stateless: @Stateless public class VitrineVirtual { ... } 2.1.3 Singleton Session Beans Singleton session beans foram projetados para compartilhar informação entre beans. São instanciados uma única vez por aplicação, e têm escopo de aplicação. Por terem estado compartilhado, precisam lidar com questões relacionadas ao acesso concorrente. Só pode haver uma instância do bean por aplicação (mas se uma aplicação for distribuída por várias máquinas virtuais, haverá uma instância em cada JVM). A forma mais simples de criar um stateful session bean é usando o estilo no-interface view, anotando a classe com @Singleton: @Singleton public class ServicosGlobais { ... } É comum instruir o container a carregar o bean durante a inicialização da aplicação anotando-o com @Startup: @Startup @Singleton public class ServicosGlobais { ... }

Às vezes um singleton depende da inicialização prévia de outros singletons. Isto pode ser configurado usando @DependsOn: @DependsOn("ServicosGlobais") @Singleton public class EstatisticasDeAcesso { ... } O acesso concorrente a um Singleton session bean é controlado pelo container (default) e todos os seus métodos tem (por default) acesso exclusivo. Isto significa que apenas um cliente de cada vez pode ter acesso ao método. Esse comportamento pode ser alterado para maior eficiência (ex: permitir que métodos que não alteram o estado sejam acessados simultaneamente.)

2.2 Interfaces e acesso

2.2.1 Interfaces para clientes locais A forma mais simples de exportar a interface de um SessioBean é usar a configuração default (no-interface view), que considera todos os métodos do bean (inclusive os herdados) como parte da interface. A forma mais simples (e recomendada) de obter acesso a este bean em uma classe cliente da mesma aplicação é usando injeção de dependências (ou CDI): @EJB BibliotecaBean bean; A estratégia no-interface view expõe todos os métodos, o que pode não ser desejável se a classe contém métodos que não devem ser expostos. Pode-se ter mais controle criando uma interface Java anotada com @Local e contendo apenas os métodos que deverão ser exportados. @Local public interface Biblioteca { void emprestar(Livro livro); void devolver(Livro livro); } O bean só precisa implementar a interface: @Stateless public class BibliotecaBean implements Biblioteca { ... } Os clientes de um bean @Local devem pertencer à mesma aplicação e podem usar CDI ou injeção de dependências (com @EJB) para injetar a interface (não o bean): @SessionScoped public class Administrador {

Dentro de um container EJB é possível obter a referência para um bean remoto via injeção de dependências (chamando pela interface, sempre): @EJB BibliotecaRemote biblioteca; Dependendo da configuração e do servidor, às vezes é possível usar injeção de dependências em containers localizados em máquinas diferentes, mas nesses casos o mais garantido é usar JNDI: Context ctx = new InicialContext(); BibliotecaRemote biblioteca = (BibliotecaRemote)ctx.lookup("java:global/libraryapp/Biblioteca"); Em clientes RMI/IIOP que não estão usando um container ainda é possível obter acesso a um EJB via acesso ao JNDI global proprietário do servidor. Em alguns servidores (ex: WebSphere 7) o proxy obtido via JNDI é um objeto CORBA que precisa ser convertido. Nesse caso, é recomendado usar o método PortableRemoteObject.narrow() para converter o proxy do objeto: java.lang.Object stub = ctx.lookup("java:app/BibliotecaRemote "); BibliotecaRemote biblioteca = (BibliotecaRemote) javax.rmi.PortableRemoteObject.narrow(stub, BibliotecaRemote.class); Chamadas remotas tem uma natureza diferente de chamadas locais. Os parâmetros dos métodos e os tipos de retorno são sempre passados por valor (são proxies de rede), portanto não é possível fazer operações que alteram propriedades de um bean remoto por referência (é necessário alterar o bean localmente e depois sincronizar). Proxies de beans remotos e seus parâmetros precisam ser transferidos pela rede. É geralmente mais eficiente transferir objetos maiores em poucas chamadas, portanto interfaces remotas devem usar o padrão Data-Transfer Objects (DTOs) e transferir objetos de baixa granularidade, para reduzir o número de chamadas.

3 Message Driven Beans (MDB)

Message-driven beans (MDB) são processadores assíncronos. São usados para modelar eventos, notificações e outras tarefas assíncronas. Um MDB não possui uma interface e não pode ser chamado diretamente por um cliente. Mas um MDB pode agir como cliente e chamar outros beans, iniciar contextos transacionais e injetar e usar serviços disponíveis à aplicação. MDBs são listeners de mensageria. São geralmente usados para processar mensagens JMS e implementam a interface MessageListener. São anotados com @MessageDriven informando o nome da fila à qual o bean está registrado como listener. A menos que seja

configurado com um filtro de mensagens, todas as mensagens recebidas na fila serão recebidas pelo metodo onMessage() do bean, que poderá processá-las. @MessageDriven(mappedName="pagamentos") public class ProcessadorCartaoDeCredito implements MessageListener { @Override public void onMessage(Message message) { try { // processa a mensagem } catch (JMSException ex) { ... } } } O atributo mappedName é uma forma portável de informar o nome da fila, mas de acordo com a especificação é de implementação opcional. Funciona na implementação de referência (Glassfish) mas pode não funcionar em outros servidores. Nesses casos a fila precisa ser informada usando propriedades de ativação (que podem variar entre fabricantes). A propriedade activationConfig de @MessageListener recebe uma lista propriedades de configuração em anotações @ActivationConfigProperty. No WildFly/JBoss e WebSphere é obrigatório usar a propriedade destination, que informa a fila ao qual o bean deve ser registrado: @MessageDriven( activationConfig={ @ActivationConfigProperty(propertyName="destination", propertyValue="pagamentos")} ) public class ProcessadorCartaoDeCredito implements MessageListener { @Override public void onMessage(Message message) { try { // processa a mensagem } catch (JMSException ex) { ... } } } Existem outras propriedades que podem ser configuradas. Uma delas é messageSelector que permite filtrar as mensagens que serão recebidas pelo bean. O filtro atua sobre os cabeçalhos e propriedades da mensagem. Cabeçalhos são gerados automaticamente pelo sistema, e incluem dados como data de validade, id da mensagem, etc. Propriedades são definidas pelo remetente da mensagem, que pode gravar uma propriedade em uma mensagem JMS usando: mensagem.setIntProperty("quantidade", 10);

4.1 Stateful Session Bean

4.2 Stateless Session Bean

4.3 Singleton Session Bean

4.4 Message-driven Bean

4.5 Callbacks

Existem cinco anotações EJB para marcar métodos de callback, que são chamados automaticamente em eventos do ciclo de vida de um bean. Quatro delas são usadas em session beans: @PostConstruct é usada para anotar um método que deve ser chamado após a execução do construtor default do bean e injeção das dependências, e antes que qualquer método da interface do bean seja chamado: @Stateless public class Biblioteca { @Inject ServicoIsbn servico; @PostConstruct private void inicializar() { servico.login(); } ... } @PreDestroy é usada para anotar um método que deve ser chamado antes do bean ser removido. O bean pode ser removido explicitamente pelo cliente (ex: através de um método anotado com @Remove em stateful session beans) ou pelo container (a qualquer momento para stateless beans, e na finalização da aplicação para singletons). @Stateless public class Biblioteca { ... @PreDestroy

especificação Java EE define três formas padrão de acesso JNDI que podem ser usadas independente do servidor: global, no contexto de uma aplicação (se o bean estiver em modulo empacotado em um EAR), e no contexto de um módulo. Um nome JNDI global tem a forma mínima: java:global/aplicacao/bean para beans armazenados em EJB JARs ou WARs. A aplicação é (por default) o nome do arquivo sem a extensão (aplicacao.war ou aplicacao.jar) Se o WAR ou EJB JAR estiver dentro de um arquivo EAR, ele é considerado um módulo da aplicação que é representada pelo EAR. Nesse caso, é preciso incluir o EAR no caminho global: java:global/ aplicacao / modulo / bean Onde o nome da aplicação (geralmente) é o arquivo EAR sem a extensão (ex: aplicacao.ear) e os nomes dos módulos, se não forem o nome do arquivo (default), estão definidos no /META-INF/application.xml do EAR. Se o bean tiver mais de uma interface e houver necessidade de identificar especificamente uma delas, o nome (qualificado) da interface pode ser incluído depois do nome do bean, separado por uma exclamação: java:global/ aplicacao / modulo / bean! pacote.Interface Se o acesso ao bean ocorrer entre módulos instaladas na mesma aplicação (EAR), pode-se usar o acesso no escopo do container com prefixo java:app: java:app/ modulo / bean Se a comunicação ocorrer no contexto do módulo, ou se a aplicação não estiver empacotada em um EAR, pode-se usar qualquer uma das duas formas: java:app/ bean java:module/ bean Por exemplo, se um bean @Remote chamado LivroBean é empacotado em um WAR biblioteca.war. Ele pode ser chamado localmente (ex: por um managed bean ou servlet no mesmo WAR) usando: public class LivroClientServlet extends HttpServlet { public void init() { try { Context ctx = new InitialContext(); // inicialização do JNDI LivroBean bean = (LivroBean)ctx.lookup("java:app/LivroBean"); bean.inicializar(); ...

E por um cliente remoto usando: public class LivroRemoteTest extends TestCase { @Test public void testLookup() { Context ctx = new InitialContext(); LivroBean bean = (LivroBean)ctx.lookup("java:global/biblioteca/LivroBean"); ... Mas para o primeiro caso, que executa dentro do container, talvez seja mais prático simplesmente injetá-lo usando @EJB (ou @Inject, se configurado com CDI): public class LivroClientServlet extends HttpServlet { @EJB LivroBean bean; public void init() { try { bean.inicializar(); ...

6 Concorrência, chamadas assíncronas e agendamento

A especificação EJB explicitamente proíbe beans de criar threads (além de não recomendar que EJBs não abram sockets ou streams de I/O). Embora a proibição esteja apenas na especificação (e não seja verificada pelo container), e uma má idéia criar threads porque eles podem interferir com o controle do ciclo de vida dos componentes realizado pelo container. Também não é recomendado o uso de travas e sincronização, que podem interferir no controle de transações e causar deadlocks. Mas existem várias aplicações de threads, como notificações e agendamento que podem ser realizadas em EJB usando recursos como MDB, timers e métodos assíncronos. A sincronização de dados compartilhados é automática em singletons, mas existem várias opções de configuração.

6.1 Acesso concorrente em singletons

Por default, todo singleton bean tem controle de acesso concorrente, que impede acesso simultâneo a seus métodos. Esse acesso pode ser configurado através da anotação @ConcurrencyManagement a nível de classe e com travas de leitura/gravação em cada método usando a anotação @Lock. 6.1.1 Concorrência gerenciada belo bean Por default, a gerência de concorrência e feita pelo container. Mas anotando-se a classe do Singleton com:

individualmente) informando quantos milissegundos o cliente pode esperar. Quando o timeout acabar, o container lança uma exceção (ConcurrentAccessTimeoutException): @Singleton @AccessTimeout(value= 60000 ) public class MySingletonBean { ... }

6.2 Chamadas assíncronas

Uma das maneiras de executar uma operação assíncrona usando session beans é implementá-lo como cliente JMS. O método deve criar uma mensagem, empacotar os dados necessários para que a operação assíncrona seja executada, e enviar a mensagem para uma fila JMS mapeada por um MDB. Ao receber a mensagem, o MDB desempacota os parâmetros e chama a operação. Embora esta possa ser uma solução eficiente, ela requer a criação de bastante código extra, além da necessidade de empacotar e desempacotar dados em uma mensagem. Uma outra forma de realizar operações assíncronas é usando métodos assíncronos. Métodos assíncronos podem ser usados em qualquer session bean e precisam ou retornar void ou Future. A primeira solução já é uma substituição adequada para a solução com MDB, que também não retorna valor. A segunda utiliza um objeto Future, do pacote java.util.concurrent, que permite monitorar chamadas assíncronas. É preciso também anotar o método com @Asynchronous (que também pode ser usado na classe, se todos os métodos da classe forem assíncronos). O exemplo abaixo ilustra um bean contendo um método assíncrono: @Stateless public class Tradutor { @Asynchronous public Future traduzir(String texto) { StringBuilder textoTraduzido; // ... realiza a tradução (demorada) return new AsyncResult(textoTraduzido.toString()); } } O cliente pode chamar o método e receber de volta um objeto Future. O resultado pode ser extraído quando estiver pronto usando o método get(). O método isDone() pode ser usado para monitorar o estado do objeto e descobrir quando o resultado pode ser extraído: @SessionScoped @Named public class ManagedBean {

@EJB private Tradutor tradutor; private Future future; public void solicitarTraducao(String texto) { future = tradutor.traduzir(texto); } public String receberTraducao() { while (!future.isDone()){ Thread.sleep(1000); // fazer outras coisas } return (String)future.get(); } }

6.3 Timers

Timers são serviços de agendamento que podem ser configurados em stateless e singleton session beans. Permitem que métodos sejam chamados periodicamente, ou uma única vez em data e hora marcada, ou depois de um intervalo especificado. Timers automáticos são configurados anotando métodos com @Schedule (ou @Schedules para múltiplos timers), que recebe como parâmetros as regras de agendamento. Os parâmetros são hour, minute, second, dayOfWeek, dayOfMonth, timezone, year, que podem receber expressões (para timers periódicos) ou valores fixos (para timers que executam apenas uma vez): Exemplo @Stateless public class MyTimer { @Schedule(hour="", minute="", second="*/10") public void printTime() { ... } ... } A seguir alguns exemplos de expressões:

  • hour=" 7 , 19 , 23 ", dayOfWeek=" 1 - 5 " – executa as 7, 19 e 23 horas, de segunda a sexta
  • minute="30", hour=" 5 " - executa uma vez às 5 horas e 30 minutos
  • hour="", minute="", second="*/10" - toda hora e minuto a cada 10 segundos Timers também podem ser criados programaticamente usando os métodos de TimerService em beans que implementam a interface TimedObject e seu método ejbTimeout(Timer). Neste caso o timer geralmente é configurado na inicialização do bean: