Do que se trata o artigo:

EJB é um dos principais componentes da plataforma Java EE. Eles são executados em um container EJB no lado do servidor. A principal característica do EJB é a rapidez em desenvolver soluções, pois, ele fornece um conjunto de componentes prontos, o que torna o desenvolvimento eficiente. Entretanto, nem sempre foi assim. Antes da versão 3.0 do EJB, existia uma grande dificuldade devido à complexidade na utilização desta tecnologia, com destaque para o uso de configurações em arquivos XML ao invés de anotações. Vamos entender o que melhorou ao passar dos anos e como os EJBs se tornaram nos dias atuais uma das principais referências de desenvolvimento.

Em que situação o tema é útil:

Este artigo será útil para os desenvolvedores que desejam conhecer o universo que há por trás dos EJBs. Aprender o que de fato é um EJB, como ele se divide entre framework e container, quais recursos eles disponibilizam e entender porque os EJBs são usados no desenvolvimento de aplicações corporativas.

Conhecendo o EJB:

Este artigo apresenta o Enterprise JavaBeans, ou apenas EJB, implementação que teve sua última atualização com a JSR 318 – Enterprise JavaBeans 3.1. O EJB fornece poderosas ferramentas que permitem desenvolver aplicações complexas e de alto desempenho, onde o desenvolvedor foca sua atenção na lógica de negócio ao invés de se preocupar tanto com situações periféricas, porém não menos importantes.

Hoje em dia, grandes empresas possuem sistemas corporativos integrando setores, melhorando a produtividade, otimizando processos e agregando valores nas mais variadas áreas de atuação. Tais sistemas são desenvolvidos levando em consideração a segurança, a grande quantidade de acessos simultâneos, a integridade das informações, a estabilidade, entre outros aspectos. Se o sistema não funcionar corretamente por qualquer motivo, todo um processo estará comprometido. Por isso, escolher tecnologias que oferecem mecanismos robustos para desenvolver softwares é fundamental para obter sucesso na construção de uma aplicação.

Pensando nisso, neste artigo aprenderemos a desenvolver soluções para atender às necessidades dos sistemas corporativos utilizando EJB. Vamos entender como funcionam os EJBs, quais são seus componentes e qual é a finalidade do container em uma aplicação EJB. Veremos os recursos disponíveis para otimizar o uso da memória do servidor e quais APIs o EJB integra facilmente, além de conhecer a fundo os beans de sessão e seus três tipos: stateless, stateful e singleton. Finalmente, desenvolveremos uma aplicação, colocando em prática tudo o que aprendemos no artigo.

O que é EJB?

EJB é um dos principais componentes da plataforma Java Enterprise Edition (Java EE) para desenvolvimento de sistemas corporativos. Com ele é possível criar aplicações modulares, separar suas funcionalidades e as reutilizar de forma simples e objetiva. Ao utilizar EJB é possível construir aplicações distribuídas, totalmente seguras e com um eficaz tratamento de transações. Além disso, o EJB oferece serviços de persistência de dados, controle de concorrência, envio de mensagens, serviço de agendamento, chamadas a métodos remotos e a web services.

Já imaginou ter que construir um mecanismo para controlar as transações de uma aplicação? Construir funcionalidades para o controle de memória, liberar um componente quando o mesmo não for mais utilizado ou até disponibilizá-lo para outro usuário? Ou programar dezenas de linhas de código para prover integração com a API de envio de mensagens, a Java Message Service (JMS)? Até mesmo construir um mecanismo para possibilitar acesso remoto a outras aplicações? Além de perder um valioso tempo na construção destes recursos, ainda existe a grande possibilidade de desenvolver soluções vulneráveis a erros, devido às complexidades apresentadas por estes recursos.

Em outras palavras, quais os motivos para reinventar a roda? Existe a necessidade de perder tempo na construção de soluções que já existem, que são constantemente utilizadas, testadas e aprovadas pela comunidade Java?

EJB é isso, um conjunto de soluções integradas e centralizadas para suprir os problemas de desenvolvimento de softwares. Utilizando EJB, o desenvolvedor pode se concentrar mais na regra de negócio e nas exigências do cliente, em vez de se preocupar com códigos de infraestrutura.

Por que utilizar EJB?

Um bom motivo para utilizar EJB é o fato de o desenvolvimento ser simples e rápido, devido aos poderosos recursos disponíveis. Um EJB é basicamente um POJO (Plain Old Java Objects), ou seja, uma simples classe Java que recebe algumas anotações, e com isso se torna um importante componente. Para desenvolver um sistema utilizando EJBs, não existe a necessidade real de entender a fundo o que o EJB faz por trás das anotações, o desenvolvedor precisa saber apenas utilizá-las.

Os componentes EJBs utilizam várias APIs e soluções integradas como, por exemplo, a RMI (Remote Method Invocation), que faz acesso remoto a outros componentes de forma simples, sendo possível acessar componentes que estão em outros containers, em qualquer lugar do mundo. Também utiliza a JTA (Java Transaction API), uma poderosa API responsável por gerenciar as transações de forma transparente. A JAAS (Java Authentication and Authorization Service) é uma API que fornece serviço de segurança a aplicações Java EE, e o EJB também faz uso dela, de forma simples e intuitiva. Com EJB também é possível utilizar a API Java Mail, que pode ser integrada ao servidor de aplicação para simplificar o envio de e-mails. Ademais, os componentes EJBs oferecem uma excelente integração com a camada web.

A JPA (Java Persistence API) é uma das mais importantes APIs que integram o framework e faz com que o EJB tenha um forte e poderoso mecanismo de persistência de dados. Além disso, o EJB é mantido pela JCP (Java Community Process), o que torna a API do EJB pública e garante um longo futuro para a tecnologia. Existem ainda grandes empresas que dão apoio ao EJB, por exemplo, IBM, Oracle, JBoss, entre outras. Além do apoio, elas lançam no mercado diversas ferramentas que estimulam a concorrência e aumenta assim o valor do EJB no mundo corporativo.

Histórico das versões do EJB

A primeira versão do EJB foi lançada em março de 1998 durante o Java One, considerado o maior evento de Java do mundo. Em dezembro de 1999 chega a versão 1.1, que já contava com mecanismos de segurança, acesso remoto e descritores de implantação XML. Mas somente a partir da versão 2.0 é que o EJB ganha força com a JCP, que é a comunidade responsável por decidir os rumos das principais tecnologias da plataforma Java. O EJB 2.0 foi lançado em agosto de 2001 e chegou com a especificação JSR 19: Enterprise JavaBeans 2.0, com o objetivo de tornar o desenvolvimento um pouco menos complexo. No final de 2003 é disponibilizada a especificação JSR 153: Enterprise JavaBeans 2.1, que chegou com importantes novidades, entre eles o acesso a Web Service, serviço de agendamento e recursos para o envio de mensagens. Quase três anos depois, em maio de 2006, foi lançada a versão 3.0 com a especificação JSR 220: Enterprise JavaBeans 3.0, e esta sem dúvida foi a maior revolução entre as versões do EJB. Entre as mudanças, pode-se destacar o uso de anotações em substituição aos XMLs, o que tornou o desenvolvimento simples e rápido. Em dezembro de 2009 o EJB chega à versão 3.1, com a especificação JSR 318: Enterprise JavaBeans 3.1, simplificando o desenvolvimento e adicionando novas funcionalidades. Até a publicação deste artigo, a versão atual do EJB é a 3.1.

Container EJB

No desenvolvimento de simples aplicações Java é necessário o uso de uma Máquina Virtual Java. A JVM fornece uma infraestrutura que permite a execução de aplicações, garante o controle do uso de memória e assegura que a aplicação execute em diversos sistemas operacionais. O container EJB segue a mesma linha. Portanto, imagine um container EJB como uma JVM poderosa que fornece diversos serviços para as aplicações EJB.

Um container EJB está disponível no mercado através de vários fornecedores de expressão, como o WebLogic Server Application da Oracle e o WebSphere da IBM. Também existem servidores de software livre como JBoss e o GlassFish; este último será utilizado nos exemplos deste artigo. Eles estão disponíveis em containers EJB ou em containers web, por isso é importante citar que o Apache Tomcat é um servidor web e não é possível utilizá-lo para executar aplicações EJB.

O container EJB é responsável por prover serviços e recursos especiais para seus componentes. A ação de colocar a aplicação EJB dentro de um container é chamada de implantação, ou deploy. Uma vez implantado e o servidor inicializado, os componentes passam a ter acesso aos diversos recursos oferecidos pelo container.

Componentes EJB

Os componentes EJB são classes Java onde são desenvolvidas as lógicas de negócio da aplicação. Estas classes, por sua vez, podem ser corporativas ou de persistência de dados. No EJB, existem três tipos de componentes: Beans de Sessão, MDB (Message-Driven Bean) e Entity. Os beans de sessão e os MDBs são responsáveis por conter as lógicas de negócio corporativas, enquanto as entities possuem toda a lógica de persistência. Este artigo irá abordar os beans de sessão, por serem os componentes mais utilizados e de menor complexidade, e servirá como ponto de partida para estudo futuro dos outros componentes do EJB.

O que é uma anotação?

Antes de abordar os componentes do EJB, vamos entender melhor o que é uma anotação. Como mencionado no início, a grande melhoria que o EJB sofreu a partir de sua versão 3.0, foi a possibilidade de usar anotações ao invés de fazer toda a configuração em arquivos XML. Mas o que seria uma anotação e pra que ela serve? A anotação no EJB é uma forma de dizer para o container para fazer alguma coisa. Sempre que uma classe, interface, método ou atributo possuir alguma anotação, o container irá executar uma série de instruções de forma transparente para atender o seu propósito, lembrando que toda anotação é precedida de ‘@’. Por exemplo, para injetar um componente EJB, utiliza-se a anotação @EJB sobre o componente em questão. Quando o container ler a anotação @EJB, ele irá efetuar uma série de procedimentos como, por exemplo, ir até o pool de beans, obter um bean que esteja disponível e retorná-lo para a aplicação. Isso ficará mais claro com os exemplos demonstrados em breve.

Beans de Sessão

A construção de um sistema corporativo inclui inúmeras regras de negócios que podem e devem ser divididas em funcionalidades específicas, melhorando o desenvolvimento, a clareza e a futura manutenção do código. Os beans de sessão são os componentes mais utilizados no EJB, pois são neles que a maioria da lógica corporativa é desenvolvida.

Os beans de sessão podem ser acessados de duas formas: local ou remota; utilizando as anotações @Local ou @Remote, respectivamente. Quando o bean for anotado como @Local, significa que ele só poderá ser acessado por requisições originárias do próprio container em que o bean é executado. Já a anotação @Remote diz que o bean pode ser acessado de forma remota, ou seja, pode ser acessado por qualquer cliente, em qualquer container de qualquer parte do mundo. Até a versão 3 do EJB, todos os beans de sessão precisavam de uma interface (Local ou Remota) para fazerem o acesso ao componente. A partir da versão 3.1, quando o bean for local, não é mais obrigatório existir uma interface. Nem mesmo a anotação @Local precisa ser colocada de forma explícita, e o acesso pode ser feito diretamente pela classe. Lembrando que, quando o acesso for Remoto, a obrigatoriedade de uma interface continua.

Nas listagens de código apresentadas no decorrer do artigo, será utilizado sempre as funcionalidades da versão 3.1 do EJB.

Injetando Componentes

No desenvolvimento de aplicações Java, uma simples classe é instanciada com a utilização da palavra reservada new, como a seguir:

  Calculadora calculadora = new Calculadora();

No EJB é diferente! Não é necessário instanciar nenhum componente. Este trabalho pertence ao container EJB, que cria algumas instâncias de forma transparente e as deixa disponíveis no pool de beans, como já citado anteriormente. É necessário apenas injetar a instância no código, com a anotação @EJB:

  @EJB
  Calculadora calculadora; 

A partir do momento em que um componente é injetado, a aplicação pode usufruir-se, de forma transparente, de vários recursos importantes do EJB, como por exemplo, o controle de transações, concorrência, controle de memória, entre outros.

Os beans de sessão são divididos em três subtipos: stateless, stateful e singleton, analisados a seguir.

Beans de Sessão Stateless

Os beans de sessão do tipo stateless são responsáveis por conter operações que não necessitam durar mais do que uma chamada. Eles devem ser invocados, processados e, se necessário, retornar o resultado para o chamador. Em outras palavras, como chamado no EJB, um bean de sessão sem estado.

O container EJB controla a quantidade de instâncias do componente do tipo stateless automaticamente conforme a necessidade. As instâncias ficam em um pool de beans e são invocadas sempre que há uma solicitação. Após sua utilização ela volta para o pool e fica disponível para uma próxima chamada. É importante dizer que, uma vez que a instância do bean stateless esteja em uso, ela não pode ser utilizada ao mesmo tempo por outro usuário. Assim, somente após voltar para o pool, é que ela pode ser usada em outra solicitação.

No dia a dia os beans de sessão stateless podem ser utilizados para o desenvolvimento de componentes úteis de conversão de dados, componentes que possuem métodos para manipulação de Strings, e componentes que executem chamadas para inserir ou realizar uma busca no banco de dados, por exemplo. Estas são algumas das funcionalidades que se encaixam nas características do bean de sessão Stateless, pois não precisam durar mais do que uma única chamada. Veja na Listagem 1 um exemplo de um bean de sessão Stateless.

Listagem 1. Implementando um bean de sessão @Stateless.

  import java.text.SimpleDateFormat;
  import java.util.Date;
   
  import javax.ejb.LocalBean;
  import javax.ejb.Stateless;
   
  @Stateless
  @Local
  public class ConversorBean {
   
         public String formatarData(Date data){
               
               SimpleDateFormat formata = new SimpleDateFormat("MM/dd/yyyy");            
               return formata.format(data);                          
         }
  }

A anotação @Stateless indica o tipo do bean e a anotação @Local diz que o bean só poderá ser acessado por componentes que estejam no mesmo container EJB. Como pode ser notado na Listagem 1, o bean não implementa uma interface, pois a partir da versão 3.1 do EJB, quando o bean é do tipo @Local, não existe mais essa obrigatoriedade.

A Figura 1 ilustra o ciclo de vida de um bean de sessão stateless dentro do container EJB.

Figura 1. Ciclo de vida do bean de sessão Stateless.

Beans de Sessão Stateful

Os beans de sessão do tipo stateful são responsáveis por conter operações que necessitam durar mais do que uma chamada, ou seja, que após a execução do componente o estado dos objetos modificados seja mantido. Em outras palavras, como é chamado no EJB, um bean de sessão com estado.

A exemplo dos beans de sessão sem estado, o container EJB também controla as instâncias do bean com estado, porém com algumas diferenças. A primeira é que uma vez criada uma instância para um usuário, ela não é em nenhum momento utilizada por outras requisições de usuários diferentes, pelo simples motivo que o estado do componente é mantido, e se outro usuário tivesse acesso às mesmas instâncias, logo teria acesso também aos dados contidos nelas. E isso não seria legal, certo? Por isso cada usuário tem sua instância exclusiva do componente, o que aumenta o consumo de memória dependendo da quantidade de usuários. No entanto, o EJB dispõe de um recurso que permite que o desenvolvedor libere a instância do componente ligado ao usuário, quando esta não for mais utilizada. Para fazer isso, basta colocar a anotação @Remove em um método. Assim, quando este método for invocado e concluído, a instância em questão será excluída pelo container EJB.

Em situações reais para o uso do componente stateful, pode-se listar um site de compras, onde o usuário pode adicionar itens ao seu carrinho de compras e depois voltar a navegar pelo site e efetuar várias requisições que os itens escolhidos permanecem salvos no carrinho do usuário. Sem o uso do bean Stateful este recurso de salvar o item na memória não seria simples de ser desenvolvido.

A Listagem 2 mostra um componente Stateful.

Listagem 2. Implementando um bean de sessão @Stateful.

  import javax.ejb.Local;
  import javax.ejb.Stateful;
  import javax.ejb.Remove;
   
  @Stateful
  @Local
  public class ItensBean {
    
    public void addItensNoCarrinho(String item) {  
      //Lógica para adicionar itens no carrinho
    }
   
     @Remove
     public void finalizarCompra(){
       //Após a execução deste método, a instancia será destruída pelo container
    }
  }

A Figura 2 ilustra o ciclo de vida de um bean de sessão stateful dentro do container EJB.

Figura 2. Ciclo de vida do bean de sessão Stateful.

Beans de Sessão Singleton

O bean de sessão do tipo Singleton foi uma das novidades da versão 3.1 do EJB. Como já citado, os beans do tipo Stateless duram apenas uma requisição e os Stateful duram várias requisições de um mesmo usuário. Já o tipo Singleton é criado apenas uma vez e disponível para todos os usuários do container EJB. Deste modo, qualquer alteração feita em um componente Singleton estará visível para todos os usuários da aplicação.

Outra funcionalidade disponível nos beans de sessão Singleton são as anotações @ReadOnly e @ReadWrite, que dizem ao container se o bean é imutável ou se ele pode sofrer alterações, respectivamente.

Imagine um sistema online, onde o administrador em determinadas ocasiões tem a necessidade de exibir mensagens para todos os usuários logados no sistema. Ao utilizar um componente singleton que contém uma lista de Strings, por exemplo, o administrador pode inserir as mensagens e todos os usuários terão acesso, pois haverá sempre uma única instância presente no container EJB.

A Listagem 3 mostra um componente Singleton.

Listagem 3. Implementando um bean de sessão @Singleton.

  import javax.ejb.Local;
  import javax.ejb.Singleton;
   
  @Singleton
  @Local
  public class MensagemBean {
   
        public String exibirMensagem(){
              //Lógica para recuperar a mensagem
        }
  }

A Figura 3 ilustra o ciclo de vida de um bean de sessão singleton dentro do container EJB.

Figura 3. Ciclo de vida do bean de sessão Singleton.

Métodos callback

Os métodos callback do EJB são um grande aliado na construção de componentes distribuídos, pois permite ao desenvolvedor tomar ações em determinados momentos de seu ciclo de vida. Eles são invocados pelo container em situações específicas durante o ciclo de vida de um componente. Com eles é possível implementar lógicas de negócio em determinadas fases do componente, como por exemplo, abrir uma conexão com o banco de dados sempre que um componente for criado ou liberar um recurso sempre que uma instância for destruída pelo container. Para declarar um método callback a única coisa necessária é colocar uma anotação no método desejado. Os métodos callback são analisados a seguir.

@PostConstruct

O método que possuir a anotação @PostConstruct será invocado sempre que o container criar uma nova instância do componente EJB. Este método pode ser usado para abrir uma conexão com o banco ou inicializar determinado processo.

@PreDestroy

O método anotado com @PreDestroy será invocado pelo container EJB momentos antes da instância do componente ser destruída. Assim, é possível criar lógicas para liberação de recursos ou mesmo fechar uma conexão com o banco de dados.

Os callbacks @PostConstruct e @PreDestroy podem ser usados para os três tipos de componentes do EJB: stateless, stateful e singleton.

Conforme mencionado anteriormente, uma instância de componente Stateful atende somente a um usuário e armazena todas as informações de sua sessão. Com isso, é acumulada uma grande quantidade de instâncias no servidor, o que sobrecarregará a memória. Para amenizar este problema, o container EJB, de forma totalmente transparente e automática, aplica um recurso chamado de passivação, que consiste em retirar um componente da memória que não esteja em uso e guardá-lo em disco, liberando memória no servidor. Se o usuário invocar qualquer método deste componente que se encontra passivado, o container imediatamente recupera a instância e a coloca de volta na memória.

Os dois tipos de métodos callbacks a seguir são invocados durante este processo de passivação.

@PrePassivate

O método anotado com @PrePassivate será invocado antes do componente EJB sofrer o processo de passivação. Assim é possível implementar lógicas para liberar recursos ou executar alguma funcionalidade propícia.

@PostActivate

O método que possuir a anotação @PostActivate será invocado após um componente EJB ser resgatado do disco e voltar para a memória. Este processo também é chamado de ativação.

Os callbacks @PrePassivate e @PostActivate podem ser usados somente para componentes do tipo stateful.

Confira na Listagem 4 como ficará a implementação de cada um dos métodos callback seguida de um breve comentário.

Listagem 4. Implementação dos métodos Callback.

  import javax.annotation.*;
  import javax.ejb.*;
   
  @Stateless
  public class Callbacks {
   
  @PostConstruct
  public void instanciaCriada(){
    //Este método será invocado pelo container sempre que uma nova instância for criada
  }
   
  @PreDestroy
  public void instanciaDestruida(){
    //Este método será invocado pelo container antes que uma instância seja destruída
  }
   
  @PrePassivate
  public void instanciaPassivada(){
    //Este método será invocado pelo container momentos antes de sofrer o processo de passivação
  }
   
  @PostActivate
  public void instanciaAtivada(){
    //Este método será invocado pelo container logo após o componente ser ativado
  }
  }

EJB na prática

Esta seção será destinada à construção de exemplos dos três tipos de beans de sessão (stateless, stateful e singleton), de forma simples, prática e objetiva. O mais importante neste ponto é entender em quais situações os beans de sessão devem ser utilizados. Com isso aumentam-se as chances de acerto na escolha do componente a ser utilizado.

Tecnologias envolvidas

Para a construção do exemplo, será utilizado o JDK na versão 6 e o IDE Eclipse com o servidor de aplicação GlassFish na sua versão 3.1. A camada de apresentação será construída com JSF 2.0, que servirá como entrada de dados para nossos componentes EJB. Por fim, será utilizado o EJB para a construção das nossas regras de negócio em sua versão mais recente, a 3.1.

Uma das maiores mudanças disponibilizadas a partir da versão 3.1 do EJB foi a possibilidade de incluir componentes EJB dentro de projetos web e empacotá-los em um WAR. Até a versão 3.0 era necessária a criação de um projeto a parte com todos os componentes EJB e depois gerar um JAR com estes componentes e empacotá-los em um EAR, e então executá-lo no servidor de aplicação. No exemplo, essa nova funcionalidade será utilizada, com o uso de apenas um projeto web.

Configurando o ambiente

O primeiro passo é a instalação do servidor de aplicação GlassFish, que será o container responsável por executar nossos exemplos no servidor. Para realizar a instalação básica do GlassFish basta seguir os passos do assistente de instalação até o fim. Após a conclusão, abra o Eclipse na perspectiva Java EE e adicione o servidor GlassFish na view Server. Em seguida, clique com o botão direito sobre o GlassFish e selecione a opção Start para iniciar seu servidor pela primeira vez. Feito isto, inicie um navegador e teste se o servidor está em funcionamento através da URL http://localhost:8080. Se tudo ocorreu bem, será exibida uma página do GlassFish.

Criando o projeto

Após a instalação e configuração do servidor, o segundo passo é a criação do projeto no Eclipse. O projeto será do tipo Dynamic Web Project, que já oferece um ambiente configurado para aplicações web. Vamos aos passos para realizar a criação do projeto.

Abra a IDE Eclipse e clique em File | New > Dynamic Web Project. No campo Project Name, informe o nome “EjbEasyWeb”. No combo Dynamic web module version, selecione a versão 3.0, responsável por dizer qual a versão do Java Servlet que será utilizada no projeto. Marque esta opção, pois esta é a versão suportada pelo Java 6. Por último, na opção Configuration, selecione JavaServer Faces v2.0 Project, que habilitará o JSF no projeto, inclusive com a criação do arquivo faces-config.xml, responsável por conter as configurações necessárias do JSF. Depois, clique em Next e em Next novamente até a tela Web Module. Nesta tela a opção Generate web.xml deployment descriptor deve ser checada. Isto significa que o arquivo web.xml, responsável pelas configurações do projeto web, deve ser criado automaticamente. Em seguida clique em Next novamente. Com isso, chegamos à última tela de configuração para a criação do projeto. Na opção JSF Implementation Library, selecione Disable Library Configuration, que desabilitará as configurações de bibliotecas do JSF que podem ser adicionadas posteriormente, porém, para nosso exemplo, não será necessário, por se tratar de uma aplicação simples. Finalmente, no campo URL Mapping Patterns, deixe somente uma opção, com *.xhtml, indicando que nossas páginas possuem a extensão xhtml. Após realizar as configurações acima descritas clique em Finish e o projeto será criado no Eclipse. Para melhor compreensão, examine os diretórios para se familiarizar com a estrutura criada pelo projeto.

Este projeto será utilizado para criar os três exemplos dos beans de sessão: Stateless, Stateful e Singleton.

Módulo Conversor de Graus, utilizando Stateless

Conforme citado anteriormente, cada um dos beans de sessão tem um comportamento específico e deve ser utilizado levando em consideração suas funcionalidades para atender bem o propósito desejado, sem comprometer desnecessariamente o uso da memória do servidor ou até mesmo a lógica de negócio da aplicação.

Os beans de sessão stateless duram apenas uma requisição, por isso são mais leves e causam menos impacto no uso da memória do servidor. Logo, devem ser utilizados sempre que não houver a necessidade de guardar o estado do bean entre as requisições. Um componente Stateless deve conter operações que são executadas e concluídas em uma única chamada.

O exemplo a seguir é um componente que executa uma simples conversão de graus Celsius para Fahrenheit. O componente recebe uma informação e retorna o grau convertido. Feita a conversão, não existe a necessidade de guardar nenhuma informação. Assim, o componente pode voltar para o pool de beans até ser invocado novamente para executar outra conversão.

Dando andamento na construção do módulo de conversão de graus, vamos criar dois pacotes para separar as funcionalidades da nossa aplicação. O primeiro pacote será criado com o nome de mb, onde ficarão os Managed Beans do JSF e o segundo com o nome de beans, onde os beans de sessão do EJB serão salvos.

Em um projeto, os fontes Java ficam dentro de um pacote chamado source; no Eclipse, geralmente é apresentado como src. A partir do source é permitido criar uma estrutura de pacotes para fazer uma separação clara dos fontes e de suas respectivas funcionalidades. Para criar o primeiro pacote, clique com o botão direito sobre o source do projeto EjbEasyWeb, selecione New > Package, dê o nome de “beans” e clique em Finish para que o pacote seja criado.

Com o pacote criado, vamos codificar nossa primeira classe Java. Assim, clique com o botão direito no pacote beans, acesse a opção New > Class, digite o nome “GrausBean” e clique em Finish, para criar a nova classe. Posteriormente, adicione o código da Listagem 5 na classe GrausBean. Esta classe é nosso bean de sessão EJB do tipo stateless, que contém as anotações que indicam o tipo do bean de sessão e o modo de acesso, que neste exemplo será local, além de um método responsável por realizar a conversão de graus.

Listagem 5. Conversor de graus, @Stateless.

  package beans;
   
  import javax.ejb.Local;
  import javax.ejb.Stateless;
   
  @Stateless
  @Local
  public class GrausBean {
      
      public double converterParaFahrenheit(double c) {
        return c * 1.8 + 32;
      }
  }

Com o primeiro bean de sessão criado, vamos adicionar o segundo pacote de fontes, onde serão criados os Managed Beans do JSF, que são classes gerenciadas pelo container que fazem o meio de campo entre as páginas JSF e o modelo de dados, como por exemplo, um bean de sessão do EJB. Para criar o pacote, clique com o botão direito sobre o source do projeto EjbEasyWeb, acesse New > Package, dê o nome de “mb” e clique em Finish para que o pacote seja criado. Vamos agora criar nossa segunda classe Java. Para isso, clique com o botão direito nesse pacote, acesse New > Class, informe o nome “GrausMB” e clique em Finish. A classe será criada e deverá receber o código contido na Listagem 6. Esta classe é um Managed Bean, que em nosso projeto será o responsável por receber as instruções da tela e realizar a injeção do componente EJB para efetuar a conversão de graus. Esse comportamento é feito através do uso da anotação @EJB. Como já aprendemos anteriormente, quando o container encontra esta anotação, ele buscará no pool uma instância disponível e a disponibilizará para o usuário de forma transparente. Após realizar a injeção do componente no código, os métodos que se encontram no bean podem ser acessados normalmente.

Listagem 6. Graus ManagedBean, JSF.

  package mb;
   
  import javax.ejb.EJB;
  import javax.faces.bean.ManagedBean;
   
  import beans.GrausBean;
   
  @ManagedBean
  public class GrausMB {
        
        @EJB
        GrausBean grausBean;
   
        double c;    
        double resultadoF;  
            
      public void converterParaFahrenheit() {
        this.resultadoF = this.grausBean.converterParaFahrenheit(c);
      }
   
        public double getC() {
              return c;
        }
        public void setC(double c) {
              this.c = c;
        }
        public double getResultadoF() {
              return resultadoF;
        }
        public void setResultadoF(double resultadoF) {
              this.resultadoF = resultadoF;
        }   
  }

Com as classes prontas, é a vez de criar os arquivos web. Em um projeto web, todos os arquivos que serão apresentados no navegador, sejam estes páginas ou imagens, têm que estar dentro de uma pasta, chamada WebContent. Ao acessar a aplicação pelo navegador, ele busca dentro desta pasta a página a ser exibida. Baseado nisso, vamos criar uma pasta chamada view dentro de WebContent para armazenar as páginas usadas neste projeto. Para tanto, clique com o botão direito sobre a pasta WebContent, acesse New > Folder, digite o nome “view” e clique em Finish. Após a criação da pasta, vamos criar a primeira página deste projeto. Deste modo, clique sobre a pasta view com o botão direito, navegue em New > XHTML Page, dê o nome de “graus.xhtml” e clique em Finish. Após a criação do arquivo graus.xhtml, vamos adicionar os namespaces do JSF e a lógica para a entrada de dados para realizar a conversão de graus conforme o código da Listagem 7.

Listagem 7. Página Graus Web.

  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   
  <html xmlns="http://www.w3.org/1999/xhtml"
   xmlns:h="http://java.sun.com/jsf/html">
   
  <h:head>
   <title>Converter Graus - Stateless</title>
  </h:head>
   
   <h:body> 
    <h:form>
     <h:outputLabel value="Conversão de Graus utilizando um bean Stateless"/>
     <hr/>
     <h:outputLabel value="Grau em Celsius: "/>
     <h:inputText value="#{grausMB.c}" ></h:inputText>
     <h:commandButton action="#{grausMB.converterParaFahrenheit}" value="Converter"/><br/>
     <h:outputLabel value="Em Fahrenheit: "/>
     <h:outputText value="#{grausMB.resultadoF}"/>
    </h:form> 
   </h:body>
   </html>

Com os devidos arquivos criados, é necessário adicionar o projeto EjbEasyWeb no servidor de aplicação GlassFish para que possa ser executado no container Java EE. Para fazer isto, clique com o botão direito sobre o servidor na view Serves e selecione Add and Remove. Em seguida clique sobre o projeto que estará no quadrante à esquerda e depois em Add, fazendo com que o projeto passe para a direita.

Finalmente, inicie o servidor e acesse a URL http://localhost:8080/EjbEasyWeb/view/graus.xhtml para conferir as funcionalidades. Ao digitar os valores e clicar em converter, o componente EJB é injetado na aplicação, recebe o valor digitado por parâmetro, efetua a conversão e em seguida retorna o resultado convertido. Feito isso, o componente volta para o pool e ficará disponível para efetuar as conversões de quem o invocar. A Figura 4 explica como a URL é montada para ser acessada no navegador.

Figura 4. Detalhamento da URL de acesso ao módulo de conversão de graus.

Como exercício opcional, desenvolva uma nova conversão de graus Fahrenheit para Celsius.

Módulo Controle de Visitas, utilizando Stateful

O próximo exemplo será com os beans de sessão stateful, que possuem como principal característica a preservação do estado dos componentes, mesmo após sofrer várias requisições. Com isso o consumo de memória é elevado e por isso estes beans devem ser utilizados com cuidado para evitar uma sobrecarga do servidor. Cada sessão de um bean do tipo Stateful permanece ligada sempre ao mesmo usuário, provendo serviços exclusivos a ele, ou seja, se o sistema estiver com mil usuários, existirão mil instâncias do componente stateful na memória. Um importante aliado no controle do uso da memória já mencionado neste artigo é o recurso chamado de passivação, que é executado de forma transparente, porém possui métodos callback que permitem criar seu próprio mecanismo de liberação de recursos, utilizando as anotações @PrePassivate e @PostActivate. A anotação @Remove também deve ser usada sempre que possível para excluir o bean quando o mesmo não for mais usado.

O exemplo com um bean de sessão com estado será um sistema de controle de visitas de um hospital, o qual registra a entrada das pessoas. Ao chegar para realizar a visita, o nome da pessoa é incluído na lista. Se chegar mais um visitante, este também é incluído na listagem. Porém, os nomes dos visitantes que já estão no local obviamente devem ser mantidos. Se o componente que armazena os nomes na listagem for do tipo stateful, este comportamento de manter os nomes salvos, mesmo sofrendo várias requisições, se dá de maneira automática, poupando um grande esforço e economizando um valioso tempo de desenvolvimento.

Como já temos o pacote beans criado, vamos apenas adicionar um novo bean de sessão, desta vez do tipo stateful. Portanto, clique com o botão direito sobre o pacote beans, acesse New > Class, digite o nome “VisitasBean” e clique em Finish. A classe será criada e deverá receber o código contido na Listagem 8. Esta classe é o nosso bean de sessão EJB do tipo stateful. Observe que não existe a anotação indicando se o bean é Local ou Remoto, sendo assim, prevalece a opção default, que é Local. Além disso, temos um método responsável por adicionar os nomes dos visitantes na lista e outro método para recuperar os nomes para serem exibidos na aplicação.

Listagem 8. Controle de Visitas, @Stateful.

  package beans;
   
  import java.util.HashSet;
  import java.util.Set;
   
  import javax.ejb.Local;
  import javax.ejb.Stateful;
   
  @Stateful
  public class VisitasBean {
    
    private Set<String> listaVisitantes = new HashSet<String>();
    
    public Set<String> getListaVisitantes() {
          return listaVisitantes;
    }
    
    public void entrouVisita(String visitante) {
          listaVisitantes.add(visitante);
    }
  }

Vamos agora criar nosso Managed Bean do módulo de visitas. Deste modo, clique com o botão direito sobre o pacote mb, acesse New > Class, informe o nome “VisitasMB” e clique em Finish. Feito isso a classe será criada e deverá receber o código da Listagem 9. Esta classe é um Managed Bean que no módulo de visitas será responsável por receber as instruções da tela e realizar a injeção do componente EJB através da anotação @EJB, para salvar o nome do visitante e também para obter a lista dos visitantes junto ao componente e exibir para o usuário.

Listagem 9. Visitas ManagedBean, JSF.

  package mb;
   
  import java.util.ArrayList;
  import java.util.List;
   
  import javax.ejb.EJB;
  import javax.faces.bean.ManagedBean;
   
  import beans.VisitasBean;
  import javax.faces.bean.SessionScoped;
   
  @ManagedBean
  @SessionScoped
  public class VisitasMB {
        
        @EJB
        VisitasBean visitasBean;
        
        private String visitante;
   
        public void entrouVisita() {
              visitasBean.entrouVisita(visitante);           
        }      
        
        public List<String> getVisitas(){
               return new ArrayList<String>(visitasBean.getListaVisitantes());
        }
        
        public String getVisitante() {
              return visitante;
        }
   
        public void setVisitante(String visitante) {
              this.visitante = visitante;
        }
  }

Agora, vamos criar a página para realizar o cadastro dos visitantes. Como já dissemos, toda página web deve ser criada dentro da pasta WebContent. Assim sendo, clique com o botão direito sobre a pasta view, acesse New > XHTML Page, dê o nome de “visitas.xhtml” e clique em Finish. O arquivo visitas.xhtml será criado, restando adicionar os namespaces do JSF e a lógica para a entrada de dados para realizar o cadastro e a visualização dos visitantes. Faça isso conforme o código da Listagem 10.

Listagem 10. Página Visitas Web.

  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   
  <html xmlns="http://www.w3.org/1999/xhtml"
   xmlns:h="http://java.sun.com/jsf/html"
   xmlns:f="http://java.sun.com/jsf/core">
   
  <h:head>
   <title>Controle de Visitas - Stateful</title>
  </h:head>
   
   <h:body>
   <h:form>
   <h:outputLabel value="Cadastro de Visitas utilizando um bean Stateful"/>
   <hr/>
   <h:outputLabel value="Nome de Visitante: "/>
   <h:inputText value="#{visitasMB.visitante}"/>
   <h:commandButton action="#{visitasMB.entrouVisita}" value="Incluir"/>
   
   <br/>      
   <h:dataTable value="#{visitasMB.visitas}" var="v" border="1">
         <h:column>
                <f:facet name="header" >
                       <h:outputText value="Visitantes"/>
                </f:facet>
                 <h:outputText value="#{v}"/>
         </h:column>
   </h:dataTable>
   </h:form>
   </h:body>
   </html>

Após a criação dos arquivos necessários para a execução do módulo de controle de visitas, certifique-se que o projeto EjbEasyWeb esteja adicionado no servidor de aplicação GlassFish clicando com o botão direito sobre o servidor na view Serves > Add and Remove. O projeto deve estar no quadrante à direita. Se existirem mais projetos criados no Eclipse, é através desta opção que devemos dizer ao servidor de aplicação qual projeto queremos que seja implantado e qual projeto não queremos. Todos os projetos que estiverem no quadrante da direita serão implantados.

Feito isso, inicie o servidor e acesse a URL http://localhost:8080/EjbEasyWeb/view/visitas.xhtml. Ao digitar os nomes e clicar em incluir, o componente EJB é injetado na aplicação, recebe o nome digitado por parâmetro e, de maneira transparente, mantém os nomes na sessão. Cadastre mais nomes e observe que eles serão acumulados e não substituídos. Isto mostra que todo e qualquer valor de atributo ou lista de um componente stateful será preservado na sessão.

Como exercício opcional, crie a opção para remover os nomes da lista de visitas.

Para comprovar os efeitos de um bean de sessão Stateful, use diferentes navegadores. É importante lembrar que ao usar várias abas de um mesmo navegador, elas compartilham da mesma sessão. Ao cadastrar uma visita, pode-se atualizar a página diversas vezes, ou até mesmo abrir a aplicação em outra aba do mesmo navegador, que as informações não serão perdidas. Porém, ao abrir a aplicação em outro navegador, consequentemente será criada uma nova sessão, e as informações cadastradas anteriormente não serão exibidas.

Módulo Contador de Acessos, utilizando Singleton

O último bean de sessão que será apresentado é o singleton, que foi incorporado ao EJB na versão 3.1. Sabe-se que os stateless são beans de sessão sem estado e os stateful são beans de sessão com estado. Já os beans de sessão singleton são criados apenas uma vez e todos os usuários acessam exatamente a mesma instância do componente. Logo, eles têm acesso às mesmas informações contidas nela. Para ilustrar um exemplo do bean de sessão singleton, imagine um simples contador de usuários logados. O primeiro usuário que acessar a aplicação iniciará o contador, fazendo com que ele receba o acesso de número 1, e este valor será salvo em um componente singleton. Dessa forma, quando um novo usuário entrar no sistema e, como uma única instância do bean está disponível em toda a aplicação, o contador adicionará mais um acesso, marcando assim dois acessos.

Iniciando a construção do módulo contador de acessos, vamos criar um bean de sessão do tipo singleton a partir do pacote beans. Para isto, clique com o botão direito sobre esse pacote, acesse New > Class, informe o nome “ContadorBean” e clique em Finish. A classe será criada e deverá receber o código apresentado na Listagem 11. Esta classe é o bean de sessão EJB do tipo singleton, que contém as anotações que indicam o tipo do bean de sessão e o modo de acesso, que neste exemplo será local. Além disso, temos um método responsável por incrementar o número de acessos sempre que uma nova requisição for feita e outro método para obter a quantidade de acessos para serem exibidos na aplicação.

Listagem 11. Contador de Usuários, @Singleton.

  package beans;
   
  import javax.ejb.Local;
  import javax.ejb.Singleton;
   
  @Singleton
  @Local
  public class ContadorBean {
   
      int contador;
   
        public int getContador() {
              return contador;
        }
        
        public void incrementar(){
              contador++;
        }
  }

Vamos agora criar nosso Managed Bean do módulo contador de acessos. Para isso, clique com o botão direito sobre o pacote mb, acesse New > Class, digite o nome “ContadorMB” e clique em Finish. A classe será criada e deverá receber o código contido na Listagem 12. Esta classe é o Managed Bean que no módulo contador de acessos será responsável por receber cada requisição da aplicação e realizar a injeção do componente EJB através a anotação @EJB. A partir do momento que o componente for injetado, é possível realizar a contagem dos acessos ao sistema e também obter a quantidade total de acessos e exibir para o usuário.

Listagem 12. Contador ManagedBean, JSF.

  package mb;
   
  import javax.ejb.EJB;
  import javax.faces.bean.ManagedBean;
  import javax.faces.bean.SessionScoped;
   
  import beans.ContadorBean;
   
  @ManagedBean
  @SessionScoped
  public class ContadorMB {
        
        @EJB
        ContadorBean contadorBean;
        
        public void incrementar() {
              contadorBean.incrementar();
        }
        
        public int getContador() {
              return contadorBean.getContador();
        }
  }

Por último, vamos criar a página para realizar a contagem de acessos. Esta página será criada dentro da pasta view, que por sua vez está dentro da pasta WebContent. Então, clique com o botão direito sobre a pasta view, selecione New > XHTML Page, dê o nome de “contador.xhtml” e clique em Finish. Em seguida, adicione os namespaces do JSF e a lógica para a contagem de acessos ao sistema conforme o código da Listagem 13.

Listagem 13. Contador Web.

  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   
  <html xmlns="http://www.w3.org/1999/xhtml"
   xmlns:h="http://java.sun.com/jsf/html">
   
  <h:head>
   <title>Contador de Acesso - Singleton</title>
  </h:head>
   
   <h:body onload="#{contadorMB.incrementar()}"> 
   <h:form>
   <h:outputLabel value="Contador de Acesso utilizando um bean Singleton"/>
   <hr/>
    <h:outputLabel value="Quantidade: "/>
    <h:outputText value="#{contadorMB.contador}"/>
   </h:form>
   </h:body>
   </html>

Agora, inicie o servidor e acesse a URL http://localhost:8080/EjbEasyWeb/view/contador.xhtml. Cada vez que atualizar a pagina, será adicionado um registro ao contador do componente singleton.

Para comprovar os efeitos de um bean de sessão Singleton, acesse a aplicação em um navegador para incrementar o contador, inicie a aplicação em um navegador diferente e verifique que o número de acessos será incrementado. Isto deve acontecer independentemente do navegador, pois apenas uma instância do componente é criada, e ela é compartilhada com todos os usuários da aplicação.

Conclusões

Este artigo apresentou uma introdução ao EJB, uma das mais importantes tecnologias de desenvolvimento da plataforma Java EE, que permite desenvolver aplicações corporativas de alta complexidade, oferecendo valiosos recursos ao desenvolvedor. A versão mais recente do EJB é a 3.1, que foi lançada através da especificação JSR 318. Esta foi a versão utilizada nos exemplos apresentados neste artigo. Também foi abordado em detalhes os beans de sessão, seus três subtipos (stateless, stateful e singleton) e seus métodos callback. Vimos ainda conceitos sobre a tecnologia, vantagens no uso de EJBs, entendemos a diferença entre componentes e containers EJB e construímos uma simples aplicação exemplo com o que foi abordado.

O conhecimento adquirido neste artigo pode ser usado como ponto de partida para estudos avançados sobre EJBs e o universo que há por trás deles. No mercado de trabalho, a tecnologia EJB é bastante utilizada pelas empresas de desenvolvimento de softwares, e isso faz com que o EJB seja praticamente um item obrigatório no currículo de um bom desenvolvedor Java.

Links

Site oficial do EJB.
http://www.oracle.com/technetwork/java/javaee/ejb/index.html

Site oficial da JSR 318: Enterprise JavaBeans 3.1.
http://jcp.org/en/jsr/detail?id=318

Site para download do servidor de aplicação GlassFish 3.1.
http://glassfish.java.net/downloads/3.1-final.html