Introdução ao EJB 3.0 e o Enterprise Beans Components - Parte I Está na hora de fazer um test drive da especificação do EJB 3.0.

Rod Coffin

Embora a especificação EJB 3.0 ainda está aguardando liberação, já está gerando muito interesse na comunidade de desenvolvimento de software tanto por proponentes quanto por oponentes. Todos reconhecem a necessidade de achar métodos mais produtivos para o desenvolvimento de software; o debate centra-se em até que ponto e até onde, o EJB 3.0 terá um papel nesta nova paisagem.

Mais ainda: o debate da liberação do projeto público do EJB 3.0 e o suporte preliminar do JBoss, significa que esta é uma boa hora para explorar esta influente tecnologia. Na realidade, já estão surgindo relatórios do uso do EJB 3.0 em sistemas de produção.

Este artigo é o primeiro de uma séries de três, que irão explorar o EJB 3.0, tal como definido no projeto público. Cada artigo apresenta conceitos particulares da especificação e encaminha pela implementação das técnicas que usam o JBoss. Este primeiro artigo introduz o EJB 3.0 e os fundamentos dos Enterprise Beans Components.

O que é necessário:

  • Java 2 SDK 1.5
  • Maven 2.0
  • JBoss Application Server 4.0.3
  • JBoss AOP 1.3.4

Introduzindo o EJB 3.0

Aplicações empresariais constituem uma classe de aplicações de software que executam funções empresariais e tipicamente envolvem grandes quantidades de dados que são simultaneamente acessados por muitos usuários. Estas aplicações raramente executam isoladamente. Ao invés disto, cada uma é normalmente apenas um pedaço do quebra-cabeças da paisagem do TI de uma companhia, e tem que interagir com as pessoas e com outros sistemas. Resumindo, o desenvolvimento de aplicações empresariais é um trabalho difícil. Aspectos como o desempenho, escalabilidade, concorrência e segurança devem ser contemplados em quase todas as aplicações empresariais, para que as mesmas cumpram adequadamente o seu papel na empresa.

Em resposta a estes desafios, a especificação do EJB foi introduzida em março de 1998, para tornar mais fácil a confecção de sistemas empresariais distribuídos orientados a objeto. A especificação e os servidores de aplicação que implementam a maior parte de estas funcionalidades, tiveram sucesso em atingir estes objetivos. Porém através dos anos, as falhas do EJB, junto com o advento de alternativas mais simples, fizeram com que muitos questionassem se o EJB oferece a melhor solução para o desenvolvimento produtivo de aplicações empresariais.

Falhas do EJB freqüentemente citadas incluem o seguinte:

  • Componentes que queiram tirar vantagem dos serviços empresariais fornecidos estarão ligados à API EJB.
  • É uma proposta do tipo tudo ou nada. Mesmo que quisermos apenas um serviço do EJB, temos que aceitar tudo o que vem com ele.
  • Componentes do EJB requerem um recipiente (container) e são difíceis de testar.
  • Cada EJB requer vários artefatos (interfaces, classes e descritores).
  • Arquiteturas EJB tradicionais são menos orientadas a objeto e introduzem "falsos objetos" que têm só estados e nenhum comportamento.

Alternativas populares para o EJB incluem o seguinte:

  • Programação Orientada a Aspecto (Aspect Oriented Programming)
  • Recipientes de peso leve tais como Spring, Pico Container e Hivemind
  • Ferramentas de mapeamento objeto-relacional (Object Relational Mapping - ORM) tais como Hiberne JDO e iBatis
  • .NET Serviced Components

A especificação do projeto público do EJB 3.0, objetiva facilitar o desenvolvimento e tornar mais simples a alavancagem dos serviços empresariais. Estas melhorias são influenciadas até certo ponto pelo sucesso das alternativas relacionadas acima. Alguns aspectos das ferramentas acima que deixaram sua marca no EJB 3.0 incluem:

  • O modelo de programação POJO (Plain Old Java Object – Antigo Objeto Java Simples)
  • O framework de persistência leve ORM
  • Injeção de dependência
  • Comentários Metadata

Outros aspectos notáveis da especificação EJB 3.0 incluem:

  • Configuração por exceção
  • Eliminação de interfaces de componente
  • Eliminação de interfaces home
  • Redução do uso de exceções verificadas

Este artigo assume que o leitor já está familiarizado com o EJB 2.x e focalizará nas mudanças introduzidas no projeto público da especificação 3.0. O resto desta discussão abordará estas melhorias e trilhará o processo de construir uma aplicação 3.0 que usa os servidores de aplicação Maven e o JBoss para um EJB. Exemplo de Aplicação — Uma Loja de Música On-line

As técnicas discutidas neste artigo são ilustradas pela aplicação de exemplo, uma loja de música on-line. Esta loja permite aos usuários folhear e comprar música, vídeos e livros auditivos. A Figura 1 mostra uma tela da interface (podemos descarregar o código fonte via link na parte inferior ou na coluna esquerda de qualquer página).

Esta aplicação de exemplo demonstra todos os três tipos de componentes beans empresariais em ação: isto é, beans de sessão sem estado, beans de sessão com estado e beans orientados a mensagem. Notar que na especificação de entidade EJB 3.0, os beans não são mais considerados componentes beans empresariais da mesma forma que o são os beans de sessão e orientados a mensagem. Ao invés disto, eles são considerados entidades persistentes (a persistência será abordada no próximo artigo sobre o EJB 3.0). O diagrama de classe da Figura 2, ilustra em alto-nível como a aplicação de loja de música é implementada com EJB.

A aplicação de exemplo incluída com este artigo, foi projetada e testada com o JBoss Application Server 4.0.3 e o JBoss AOP 1.3.4, e utiliza o Maven 2.0 para construir a aplicação. O código vinculado fornece instruções para montar o JBoss, construir a fonte com o Maven e distribuir a aplicação.

Loja de música
Figura 1. Loja de música: a loja de música permite que os produtos sejam folheados, adicionados a um carrinho de compra e eventualmente comprados.

Beans de Sessão sem estado

Junto com a especificação dos outros componentes beans empresariais no EJB 3.0, beans de sessão sem estado são POJOs que implementam uma interface empresarial. Considerando o exemplo de loja de música: a loja de música é consultada por vários tipos de áudio e vídeo na medida em que os usuários folheiam. Uma interface simples para implementar esta funcionalidade da aplicação de loja de música, poderia ter o seguinte aspecto:


public interface IMusicStore
{
    public List<GENRE> listGenres();

    public Genre findGenreById(int id);

    public Artist findArtistById(int id);

    public Product findProductById(int id);
    
    public void checkOut(IShoppingCart cart);
}

E esta é uma implementação simples:


public class MusicStore implements IMusicStore
{
    public List<GENRE> listGenres()
    {
        return MusicStoreDAO.getInstance().listGenres();
    }

    public Genre findGenreById(int id)
    {
        return MusicStoreDAO.getInstance().findGenreById(id);
    }

    public Artist findArtistById(int id)
    {
        return MusicStoreDAO.getInstance().findArtistById(id);
    }

    public Product findProductById(int id)
    {
        return MusicStoreDAO.getInstance().findProductById(id);
    }

    public void checkOut(IShoppingCart cart)
        {
        ...
    }
}

No EJB 2.x, se quiséssemos tirar proveito dos serviços empresariais tais como a administração de transação declarativa ou da distribuição de objetos, teríamos que modificar a loja de música para que implementasse a interface javax.ejb.SessionBean bem como os métodos definidos nela e criar os beans locais e remotos e as interfaces home.

No EJB 3.0, uma classe que for planejada como uma sessão beans sem estado, tem que satisfazer duas exigências básicas:

Implementar ao menos uma interface empresarial.

  • Ser marcada com a marca @javax.ejb.Stateless.

    Uma interface empresarial é simplesmente uma interface Java simples. As interfaces java.io.Serializable e java.io.Externalizable são ignoradas automaticamente neste contexto, assim como o são todas as interfaces no pacote javax.ejb. Se só uma interface for especificada, então será assumido que é uma interface local. Este é só um exemplo da configuração da especificação através do paradigma de exceção. Se o beans tiver mais de uma interface empresarial, então cada uma terá que ser definida explicitamente como local ou remota, designando a classe beans ou as próprias interfaces.

    Projeto de Loja de música
    Figura 2. Projeto de Loja de música: neste projeto web, os pedidos são tratados por uma ação Struts que usa dois EJBs (um sem estado e o outro com estado) para atender ao pedido. A saída do carrinho do cliente é passada via JMS para um processador de ordens implementado como um MDB para preenchimento.

    Assim, para converter a classe MusicStore em um bean de sessão sem estado, apenas uma mudança é requerida: é preciso usar a designação @Stateless.

    
    
    @Stateless
    public class MusicStore implements IMusicStore
    {
        ...
    }
    

    A próxima alteração importante associada com o EJB 3.0, é de fato uma alteração na especificação do J2EE 1.5: a injeção de dependência. A especificação J2EE 1.5 requer que os clientes de aplicação J2EE, os beans empresariais e os componentes web, tenham acesso a um ambiente nomeado JNDI. O ambiente nomeando pode ser acessado por chamadas de lookup JNDI explícitas ou por designações que especificam que o recipiente injeta a dependência automaticamente. Isto quer dizer que podemos declarar agora uma dependência em um o EJB ou em outros recursos gerenciados por recipiente, via uma designação simples tal como:

    
    import com.devx.musicstore.IMusicStore;
    
    public abstract class AbstractStoreAction extends Action
    {
        @EJB
        protected IMusicStore store;
    
        ...
    }
    

    Isso é tudo! O recipiente injetará uma implementação da interface de IMusicStore na ação e a ação pode usar o objeto de loja como se fosse um POJO simples.

    Nota do autor: na versão 4.0.3 do JBoss, a injeção de recursos não é implementado para componentes web, embora este suporte esteja vindo (http://jira.jboss.com/jira/browse/EJBTHREE-212). O código de exemplo contém um aspecto escrito com JBoss AOP, que executa a injeção de dependência.

    O que está de fato acontecendo nos bastidores, é que esta designação especifica de uma referência do EJB de tipo IMusicStore seja injetado no campo de loja. O objetivo da dependência não é especificado e deve ser provido pelo distribuidor, da mesma maneira que com referências de recurso tradicionais. Se o nome da dependência não for especificado (como no exemplo anterior), então será assumido o nome totalmente qualificado da classe. No exemplo anterior, este seria java:comp/env/com.devx.musicstore.IMusicStore.

    Nota do autor: há alguma ambigüidade nas especificações EJB 3.0 e J2EE 1.5, no que diz respeito a se usar o nome não qualificado ou totalmente qualificado da classe, quando omitido o nome da referência do EJB. O projeto público EJB 3.0 especifica o nome não qualificado de classe beans, enquanto que o projeto J2EE 1.5, mostra um nome totalmente qualificado como exemplo. A implementação do JBoss usa o nome totalmente qualificado.

    Alternativamente, podemos refinar a declaração desta dependência mais adiante como ilustrado abaixo:

    
    public abstract class AbstractStoreAction extends Action
    {
        @EJB(
                name = "ejb/musicStore", 
                beanName = "store1", 
                businessInterface = com.devx.musicstore.IMusicStore.class
        )
        protected IMusicStore store;
    
        ...
    }

    Neste caso a referência do EJB está acessível por JNDI em java:comp/env/ejb/musicStore.

    Leia a Parte II.