corner imagecorner image
IDEPlatformPluginsDocs & SupportCommunityPartners

O tutorial do NetBeans E-commerce: adicionando classes de entidade e beans de sessão

O conteúdo desta página se aplica ao NetBeans IDE, versões 6.8 e 6.9

Esta unidade do tutorial introduz as tecnologias Enterprise JavaBeans (EJB) e Java Persistence (JPA). Nela, você utiliza dois dos assistentes do IDE que são essenciais para o desenvolvimento do Java EE. Dentre eles estão:

  • Classes de entidade do assistente de banco de dados: Cria uma classe de entidade da Java Persistence API para cada tabela de banco de dados selecionada, completa com anotações de consulta nomeadas, campos que representam colunas e relacionamento que representam chaves estrangeiras.
  • Beans de sessão para o assistente de classes de entidade: Cria uma fachada de sessão do EJB para cada classe de entidade com métodos de acesso básicos.

Esses dois assistentes fornecem uma maneira eficaz de configurar rapidamente o modelo para seu aplicativo. Se reexaminar o Diagrama de MVC para o aplicativo que está construindo, poderá ver beans de sessão EJB e classes de entidade JPA adaptarem-se a essa estrutura.

Diagrama MVC do aplicativo AffableBean

Nesta unidade, as classes de entidade criadas formam uma representação baseada em Java do banco de dados affablebean. Enquanto cada classe de entidade representa uma tabela do banco de dados, instâncias de classes de entidade correspondem a registros que podem ser salvos (ou seja, persistidos) no banco de dados. A lógica corporativa do aplicativo é encapsulada por beans de sessão, que podem ser utilizados como classes de fachada que habilitam o CRUD (Create-Read-Update-Delete) às entidades (conforme demonstrado aqui) ou podem conter códigos que implementam ações específicas para seu aplicativo. (Um exemplo disso é fornecido na Unidade 9: Integração da lógica corporativa transacional).

É possível visualizar uma demonstração em funcionamento do aplicativo que construir neste tutorial: Aplicativo demonstração do tutorial do NetBeans E-commerce.



Software ou recurso Versão necessária
NetBeans IDE Pacote Java, 6.8 ou 6.9
Java Development Kit (JDK) versão 6
Servidor GlassFish v3 ou Open Source Edition 3.0.1
Servidor de banco de dados MySQL versão 5.1
Projeto AffableBean instantâneo 3

Notas:

  • O NetBeans IDE requer o Java Development Kit (JDK) para ser executado adequadamente. Caso não tenha nenhum dos recursos listados acima, o JDK deverá ser o primeiro item a ser baixado e instalado.
  • O NetBeans IDE Java Bundle inclui as tecnologias Java Web e EE, que são necessárias para construir o aplicativo deste tutorial.
  • O NetBeans IDE Java Bundle inclui também o servidor do GlassFish, necessário para este tutorial. Seria possível baixar o servidor do GlassFish de maneira independente, mas a versão fornecida com o download do NetBeans tem o benefício adicional de ser automaticamente registrada com o IDE.
  • Você pode seguir esta unidade do tutorial sem ter concluído as unidades anteriores. Para fazê-lo, consulte as instruções de configuração, que descrevem como preparar o banco de dados e estabelecer uma conectividade entre o IDE, o GlassFish e o MySQL.
  • O instantâneo 4 do projeto AffableBean está disponível para download e corresponde ao estado do projeto após a conclusão desta unidade usando o NetBeans IDE 6.9.

O que são as tecnologias EJB e JPA?

Até agora, o projeto que você desenvolveu neste tutorial poderia ser executado em um servidor da Web com um contêiner de servlet, como o Apache Tomcat. Afinal, até agora, só foram utilizadas as tecnologias JSTL e servlet e estão conectadas diretamente ao banco de dados utilizando JDBC. Na realidade, seria possível, teoricamente, continuar a desenvolver o aplicativo utilizando apenas essas tecnologias, codificando manualmente para todos os aspectos do aplicativo, incluindo segurança de thread, transações e segurança. No entanto, utilizar o Enterprise beans com as classes de entidade JPA permite se concentrar na lógica corporativa do aplicativo contando, ao mesmo tempo, com soluções que já foram testadas. As sessões a seguir apresentam as duas tecnologias e definem sua função no desenvolvimento EE.

Enterprise JavaBeans

A página de produto EJB oficial descreve a tecnologia EnterPrise JavaBeans como uma "arquitetura do componente do servidor" que "habilita o desenvolvimento rápido e simplificado de aplicativos distribuídos, transacionais, seguros e portáteis". É possível aplicar EJBs (ou seja. , Enterprise beans) aos projetos, e os serviços fornecidos pela tecnologia permanecem transparentes para você como desenvolvedor, eliminando, assim, a tarefa tediosa e geralmente propensa a erros que é adicionar vários códigos de placa que seriam, caso contrário, necessários. Se for novo no desenvolvimento EE, pode questionar a necessidade de EJBs no aplicativo Web Java. O livro EJB 3 em ação, de Debu Panda, Reza Rahman e Derek Lane, parafraseia muito bem a função da tecnologia EJB:

Embora muitas pessoas pensem que EJBs são um exagero para desenvolvimento de aplicativos Web relativamente simples e de tamanho moderado, isso não é verdade. Quando se constroi uma casa, não constroi tudo desde o início. Em vez disso, se compra materiais ou até mesmo serviços terceirizados, conforme precisa. Também não é muito prático construir um aplicativo empresarial desde o início. A maioria dos aplicativos de servidor tem muito em comum, incluindo a rotatividade da lógica corporativa, gerenciamento do estado do aplicativo, armazenamento e recuperação de informações de um banco de dados relacional, gerenciamento de transações, implementação de segurança, execução de processamento assíncrono, integração de sistemas, e assim por diante.

Como estrutura, o contêiner do EJB fornece esses tipos de funcionalidade comum como serviços de fábrica, de modo que os componentes EJB podem utilizá-los nos aplicativos sem reinventar a roda. Por exemplo, vamos dizer que quando se constroi um módulo de cartão de crédito no aplicativo Web, você escreve muito código complexo e propenso ao erro para gerenciar transações e controle de acesso de segurança. Isso poderia ser evitado utilizando os serviços de transação declarativa e segurança fornecidos pelo contêiner EJB. Esses serviços, bem como muitos outros, estão disponíveis para componentes EJB quando eles são implementados em um contêiner EJB. Isso significa aplicativos de alta qualidade e ricos em recursos muito mais rápidos do que você poderia pensar.
[1]

É possível pensar no EJB tanto como componentes ou classes Java que são incorporadas no projeto, bem como uma estrutura que fornece vários serviços relacionados à empresa. Alguns dos serviços que aproveitamos neste tutorial estão descritos em EJB 3 em ação como se segue:

  • Criação de pool: Para cada componente EJB, a plataforma EJB cria um pool de instâncias do componente que são compartilhadas pelos clientes. Em qualquer ponto no tempo, cada instância do pool tem permissão de ser utilizada apenas por um único cliente. Assim que uma instância termina de atender a um cliente, ela é retornada para o pool para reutilização, em vez de ser frivolamente descartada na lixeira para ser coletada novamente depois.
  • Segurança de thread: O EJB torna todos os componentes seguros para thread e com alto desempenho, de maneira que sejam completamente invisíveis. Isso significa que é possível escrever os componentes do servidor como se estivesse desenvolvendo um aplicativo desktop de uma única thread. Não importa a complexidade do componente em si, o EJB se certificará de que ele seja seguro para thread.
  • Transações: O EJB oferece suporte a gerenciamento de transações declarativas que o ajuda a adicionar comportamento transacional aos componentes utilizando a configuração simples em vez do código. Na realidade, é possível designar qualquer método de componente como sendo transacional. Se o método for concluído normalmente, o EJB confirmará a transação e tornará as alterações de dados feitas pelo método permanentes. Caso contrário, a transação será desfeita. As transações EJB gerenciadas por contêiner são demonstradas na Unidade 9, Integrando a lógica administrativa transacional.
  • Segurança: o EJB suporta a integração com a API Authorization Service (JAAS) e Java Authentication, portanto, é fácil externalizar por completo a segurança e proteger o aplicativo usando uma configuração simples em vez de encher seu aplicativo com códigos de segurança.[2] Na Unidade 11, Dando segurança ao aplicativo, a demonstração da anotação @RolesAllowed do EJB é fornecida.

Java Persistence

No contexto do Java Enterprise, persistência refere-se ao ato de armazenar automaticamente os dados contidos em objetos Java em um banco de dados relacional. A Java Persistence API (JPA) é uma tecnologia de mapeamento relacional de objeto (ORM) que habilita aos aplicativos o gerenciamento de dados entre objetos Java e um banco de dados relacional, de maneira transparente para o desenvolvedor. Isso significa que o JPA pode ser aplicado aos projetos criando e configurando um conjunto de classes Java (entidades) que espelham seu modelo de dados. O aplicativo poderá, em seguida, acessar essas entidades, como se estivesse acessando diretamente o banco de dados.

Existem várias vantagens em utilizar o JPA nos projetos:

  • O JPA tem sua própria linguagem rica e semelhante à SQL para consultas estáticas e dinâmicas. Utilizando o Java Persistence Query Language (JPQL), os aplicativos permanecem portáteis em diferentes fornecedores de banco de dados.
  • É possível evitar a tarefa de escrever código JDBC/SQL prolixo e propenso a erro.
  • O JPA fornece, de maneira transparente, serviços para cache de dados e otimização de desempenho.

O que são beans de sessão?

Beans de sessão Enterprise são chamados por um cliente para realizar uma operação de negócio específica. O nome sessão implica que uma instância do bean está disponível pela duração de uma "unidade de trabalho". A especificação do EJB 3.1 descreve um objeto de sessão típico como tendo as seguintes características:

  • É executado em nome de um único cliente
  • Pode ser consciente da transação
  • Atualiza dados compartilhados em um banco de dados subjacente
  • Não representa dados compartilhados diretamente no banco de dados, embora possa acessar e atualizar esses dados
  • Tem vida relativamente curta
  • É removido quando o contêiner EJB trava. O cliente tem que restabelecer um novo objeto de sessão para continuar o cálculo.

O EJB fornece três tipos de beans de sessão: com estado, sem estado e singleton. As seguintes descrições são adaptadas do Tutorial do Java EE 6.

  • Com estado: O estado do bean é mantido em vários chamados de método. O "estado" se refere aos valores das variáveis de instância. Como o cliente interage com o bean, esse estado é normalmente chamado de estado conversacional.
  • Sem estado: Beans sem estado são utilizados para operações que podem ocorrer em um único chamado de método. Quando o método termina o processamento, o estado do bean específico do cliente não é retido. Um bean de sessão sem estado não mantém, portanto, um estado conversacional com o cliente.
  • Singleton: Um bean de sessão singleton é instanciado uma vez por aplicativo e existe durante o ciclo de vida do aplicativo. Beans de sessão singleton são projetados para circunstâncias em que uma única instância do enterprise bean é compartilhada e acessada ao mesmo tempo pelos clientes.

Para obter mais informações sobre beans de sessão EJB, consulte o Tutorial do Java EE 6: O que é um bean de sessão?.

Com a finalidade de desenvolver o aplicativo de e-commerce neste tutorial, trabalharemos apenas com beans de sessão sem estado.


Sobre especificações e implementações

As tecnologias EJB e JPA são definidas pelas seguintes especificações:

Essas especificações definem as tecnologias. Para aplicar uma tecnologia ao projeto, no entanto, será necessário utilizar uma implementação da especificação. Quando uma especificação se torna finalizada, ela inclui uma implementação de referência, que é uma implementação gratuita da tecnologia. Caso ache este conceito confuso, considere a seguinte analogia: Uma composição musical (ou seja, as notas em uma página) define uma peça musical. Quando um músico a aprende a composição e grava sua performance, ele cria uma interpretação da peça. Dessa maneira, a composição musical é semelhante à especificação técnica e a interpretação do músico corresponde à implementação da especificação.

Consulte O que é o processo da comunidade Java? para obter uma explicação das especificações técnicas Java e como elas são formalmente padronizadas.

Se examinar as páginas de download para as versões finais das especificações do EJB e do JPA, encontrará links para as seguintes implementações de referência:

Implementações da especificação do JPA são chamados de provedores de persistência e o provedor de persistência que foi escolhido como a implementação de referência da especificação do JPA 2.0 é chamado de EclipseLink.

Se examinar o link para a implementação de referência do EJB, chegará em uma página que lista não apenas a implementação para o EJB, mas para todas as implementações de referência fornecidas pelo Projeto GlassFish. O motivo para isso é que o Projeto GlassFish forma uma implementação de referência da especificação da plataforma Java EE 6 (JSR 316). O servidor de aplicativo GlassFish v3 (ou a edição de código-fonte aberto), que você está utilizando para construir o projeto de e-commerce neste tutorial, contém as implementações de referência de todas as tecnologias desenvolvidas pelo Projeto GlassFish. Assim, ele é referido como um contêiner Java EE 6.

Um contêiner Java EE 6 contém três componentes essenciais: um contêiner da Web (ou seja, servlet), um contêiner EJB e um provedor de persistência. O cenário de implantação para o aplicativo de e-commerce é exibido no diagrama a seguir. As classes de entidade criadas nesta unidade são gerenciadas pelo provedor de persistência. Os beans de sessão criados nesta unidade são gerenciados pelo contêiner EJB. As visualizações são exibidas nas páginas JSP, que são gerenciadas pelo contêiner Web.

Contêiner GlassFish v3 Java EE

Adicionando classes de entidade

Comece utilizando classes de entidade do IDE do Assistente de banco de dados para gerar classes de entidade com base no esquema affablebean. O assistente conta com o provedor de persistência subjacente para realizar essa tarefa.

  1. Abra o instantâneo do projeto no IDE. No IDE, pressione Ctrl-Shift-O (âŚ�-Shift-O no Mac) e navegue até o local do seu computador onde você descompactou o arquivo baixado.
  2. Pressione Ctrl-N (⌘-N no Mac) para abrir o assistente de arquivo.
  3. Selecione a categoria Persistência e, em seguida, selecione Classes de entidade de banco de dados. Clique em Próximo.
  4. Na Etapa 2: Tabelas de banco de dados, escolha jdbc/affablebean na lista suspensa Fonte de dados. A lista suspensa é preenchida por fontes de dados registradas no servidor de aplicativo.

    Quando você escolhe a fonte de dados jdbc/affablebean, o IDE varre o banco de dados e lista as tabelas de banco de dados no painel Tabelas disponíveis.
    Classes de entidade do Assistente de banco de dados
  5. Clique no botão Adicionar tudo e, em seguida, em Próximo.
  6. A Etapa 3 do assistente Classes de identidade do banco de dados difere um pouco entre o NetBeans IDE 6.8 e o 6.9. Dependendo de qual versão do IDE você estiver usando, execute as seguintes etapas.

    NetBeans IDE 6.8

    Assistente Classes de entidade do banco de dados, Etapa 3: Classes de entidade
    1. Digite entity (entidade) no campo Pacote. O assistente criará um novo pacote para as classes de entidade depois da conclusão.
    2. Clique no botão Criar unidade de persistência. A caixa de diálogo Criar unidade de persistência se abre.
      Caixa de diálogo Criar unidade de persistência
      Uma unidade de persistência se refere a uma coleção de classes de entidade que existem no aplicativo. A caixa de diálogo acima gera um arquivo persistence.xml, que é usado por seu provedor de persistência para especificar as definições de configuração da unidade de persistência. Note que "EclipseLink (JPA 2. 0)" é a seleção padrão para o servidor associado ao projeto. Deixe "Estratégia de geração de tabela" definido como "Nenhum". Isso impede o provedor de persistência de afetar o banco de dados. (Por exemplo, se desejar que o provedor de persistência exclua e, em seguida, recrie o banco de dados com base nas classes de entidade existentes, seria possível definir a estratégia como "Soltar e criar". Essa ação seria, em seguida, executada toda vez que o projeto fosse implementado).
    3. Clique em Criar.
    4. De volta na Etapa 3: Classes de entidade, note que os nomes de classes para as entidades são baseados em tabelas de banco de dados. Por exemplo, a entidade CustomerOrder é mapeada para a tabela de banco de dados customer_order. Além disso, note que a opção "Gerar anotações de consulta nomeadas para campos persistente" está selecionada por padrão. Começaremos utilizando várias consultas nomeadas posteriormente neste tutorial.
    5. Prossiga para a etapa 7 abaixo.

    NetBeans IDE 6.9

    Assistente Classes de entidade do banco de dados, Etapa 3: Classes de entidade
    1. Digite entity (entidade) no campo Pacote. O assistente criará um novo pacote para as classes de entidade depois da conclusão.
    2. Observe o seguinte:
      • Os nomes das classes para as entidades são baseados em tabelas do banco de dados. Por exemplo, a entidade CustomerOrder será mapeada para a tabela de banco de dados customer_order.
      • A opção "Gerar anotações de consulta nomeadas para campos persistentes" é selecionada por padrão. Começaremos utilizando várias consultas nomeadas posteriormente neste tutorial.
      • A opção 'Criar unidade de persistência" é selecionada por padrão. Uma unidade de persistência é uma coleção de classes de entidade que existem no aplicativo. A unidade de persistência é definida por um arquivo de configuração persistence.xml, que é lido pelo seu provedor de persistência. Portanto, ativar esta opção significa que o assistente também gerará um arquivo persistence.xml é irá preenchê-lo com as configurações padrão.
  7. Clique em Terminar. As classes de entidade JPA são geradas com base nas tabelas de banco de dados affablebean. Você pode examinar as classes de entidade na janela Projetos, expandindo o pacote entidade recém-criado. Observe também que a nova unidade de persistência existe sob o nó Arquivos de configuração.
    Janela Projetos: classes de entidade exibidas no projeto

    Note que o assistente gerou uma classe de entidade adicional, OrderedProductPK. Lembre-se de que a tabela produto_pedido do modelo de dados utiliza uma chave primária composta que incluem as chaves primárias das tabelas pedido_cliente e produto. (Consulte Criação de modelo de dados: criando relacionamentos Muitos para muitos). Por esse motivo, o provedor de persistência cria uma classe de entidade separada para a chave composta e incorpora-a na entidade OrderedProduct. É possível abrir OrderedProduct no editor para inspecioná-lo. O JPA utiliza a anotação @EmbeddedId para significar que a classe que pode ser incorporada é uma chave primária composta.
    public class OrderedProduct implements Serializable {
        private static final long serialVersionUID = 1L;
        @EmbeddedId
        protected OrderedProductPK orderedProductPK;

    Pressione Ctrl-Espaço na anotação @EmbeddedId para chamar a janela da documentação da API.

    Documentação da API chamada em @EmbeddedId
  8. Abra a unidade de persistência (persistence. xml) no editor. O IDE fornece uma visualização do Desenho das unidades de persistência, em adição à visualização XML. A visualização do Desenho fornece uma maneira conveniente de fazer mudanças na configuração para o gerenciamento do projeto do provedor de persistência.
    Visualização do Desenho da unidade de persistência AffableBeanPU
  9. Clique na aba XML na parte superior da unidade de persistência AffableBeanPU para abrir a visualização XML. Adicione a seguinte propriedade ao arquivo.
    <persistence-unit name="AffableBeanPU" transaction-type="JTA">
      <jta-data-source>jdbc/affablebean</jta-data-source>
      <properties>
        <property name="eclipselink.logging.level" value="FINEST"/>
      </properties>
    </persistence-unit>
    Defina a propriedade de nível de registro como FINEST para que possa visualizar toda a saída possível produzida pelo provedor de persistência quando o aplicativo é executado. Isso habilita ver o SQL que o provedor de persistência está utilizando no banco de dados, e pode facilitar em qualquer depuração necessária.

    Consulte a documentação oficial do EclipseLink para obter uma explicação do registro e uma lista de todos os valores de registro: Como configurar o registro


Adição de beans de sessão

Nesta seção, utilizamos os beans de sessão do IDE para o Assistente de classes de entidade gerar uma fachada de sessão do EJB para cada uma das classes de entidade que foram criadas. Cada bean de sessão conterá métodos de acesso básicos para sua respectiva classe de entidade.

Uma fachada de sessão é um padrão de desenho anunciado no programa Enterprise BluePrints. Conforme informado no Catálogo de padrões do J2EE principal, ele tenta resolver problemas comuns que surgem em um ambiente de aplicativo de várias camadas, como:

  • Acoplamento rígido, que leva à dependência direta entre clientes e objetos de negócio
  • Muitas invocações de método entre cliente e servidor, que levam a problemas de desempenho da rede
  • Falta de uma estratégia de acesso de cliente uniforme, expondo os objetos do negócio a mau uso

Uma fachada de sessão abstrai as interações do objeto do negócio e fornece uma camada de serviço que expõe apenas a funcionalidade necessária. Assim, ela oculta, da visualização do cliente, as interações complexas entre os participantes. Portanto, o bean de sessão (que representa a fachada da sessão) gerencia os relacionamentos entre os objetos do negócio. O bean de sessão também gerencia o ciclo de vida desses participantes criando-os, localizando-os, modificando-os e excluindo-os, conforme necessário, pelo fluxo de trabalho.

  1. Pressione Ctrl-N (⌘-N no Mac) para abrir o assistente de arquivo.
  2. Selecione a categoria Persistência e selecione Beans de sessão para Classes de entidade.
    Assistente de arquivo: categoria Persistência, tipo de arquivo Beans de sessão para classes de entidade
  3. Clique em Próximo.
  4. Na Etapa 2: Classes de entidade, note que todas as classes de entidade contidas no projeto estão listadas à esquerda, em Classes de entidade disponíveis. Clique em Adicionar tudo. Todas as classes de entidade são movidas para a direita, em Classes de entidade selecionadas.
  5. Clique em Próximo.
  6. Na Etapa 3: Beans de sessão gerados, digite session no campo Pacote.
    Assistente Beans de sessão para classes de entidade: Etapa 3: beans de sessão gerados

    Nota: É possível utilizar o assistente para gerar interfaces locais e remotas para os beans de sessão. Embora haja benefício em programar beans de sessão para interfaces (por exemplo, ocultar interações de objetos de negócio atrás de uma interface habilita desacoplar ainda mais o cliente de sua lógica corporativa. Isso também significa que é possível codificar várias implementações da interface para o aplicativo, se necessário for) isso está fora do escopo do tutorial. Note que as versões do EJB anteriores a 3.1 requerem a implementação de uma interface para cada bean de sessão.

  7. Clique em Terminar. O IDE gera beans de sessão para cada uma das classes de entidade contidas no projeto. Na janela Projetos, expanda o novo pacote sessão para examinar os beans de sessão.

    NetBeans 6.8 NetBeans 6.9
    Janela Projetos: beans de sessão exibidos no projeto Janela Projetos: beans de sessão exibidos no projeto

    Observação: Como mostrado acima, o NetBeans IDE 6.9 fornece alguns aprimoramentos na maneira como o assistente Beans de sessão para classes de entidade gera classes de fachadas. Ou seja, o código "boiler-plate” que é comum a todas as classes é desconsiderado em uma classe abstrata denominada AbstractFacade. Caso esteja trabalhando na versão 6.9, abra qualquer uma das classes de fachada que foram geradas (sem ser a AbstractFacade). Você verá que a classe estende a AbstractFacade.

  8. Abra uma fachada de sessão no editor, por exemplo, ProductFacade. Todas as fachadas de sessão geradas instanciam um EntityManager usando a anotação @PersistenceContext.
    @PersistenceContext(unitName = "AffableBeanPU")
    private EntityManager em;
    A anotação @PersistenceContext é usada para injetar um EntityManager gerenciado por contêiner na classe. Em outras palavras, nós confiamos no contêiner EJB do GlassFish para abrir e fechar os EntityManagers, quando necessário. O elemento unitName especifica a unidade de persistência AffableBeanPU, que foi definida no arquivo persistence.xml do aplicativo.

    O EntityManager é um componente integrante da Java Persistence API e é responsável por executar ações de persistência no banco de dados. O livro EJB 3 em ação descreve o EntityManager como se segue:
    A interface EntityManager do JPA gerencia entidades em termos de fornecer, realmente, serviços de persistência. Enquanto as entidades dizem a um provedor JPA como são mapeadas para o banco de dados, elas não persistem elas próprias. A interface EntityManager lê os metadados ORM para uma entidade e executa operações de persistência.

Seu aplicativo contém, agora, um modelo de persistência do banco de dados affablebean na forma de classes de entidade JPA. Também contém uma fachada de sessão que consiste em Enterprise beans que podem ser utilizados para acessar as classes de entidade. A próxima seção demonstra como é possível acessar o banco de dados utilizando os beans de sessão e as classes de entidade.


Acessando dados com EJBs

Na unidade anterior do tutorial, vimos como acessar o banco de dados do aplicativo configurando uma fonte de dados no GlassFish, adicionando uma referência da fonte ao descritor de deplyment do aplicativo e utilizando marcações JSTJ <sql> nas páginas JSP do aplicativo. Essa técnica é valiosa, pois permite configurar, rapidamente, protótipos que incluem dados do banco de dados. No entanto, não é um cenário realista para aplicativos médios ou grandes, ou para aplicativos gerenciados por uma equipe de desenvolvedores, já que seria difícil de mantê-lo ou ampliá-lo. Além disso, se estiver desenvolvendo o aplicativo em várias camadas ou estiver aderindo ao padrão MVC, não seria aconselhável manter o código de acesso de dados no front-end. Utilizar Enterprise beans com um modelo de persistência habilita uma conformidade melhor com o padrão MVC, desacoplando, de maneira eficaz, a apresentação e os componentes do modelo.

As instruções a seguir demonstram como começar a utilizar os beans de sessão e de entidade no projeto AffableBean. Você removerá a lógica de acesso a dados JSTL que configurou anteriormente para as páginas de índice e de categoria. No lugar dela, utilizará os métodos de acesso de dados fornecidos pelos beans de sessão e armazenará os dados em variáveis de escopo para que possam ser recuperados das visualizações de páginas do front-end. Trataremos da página de índice primeiro e, em seguida, iremos para a página de categoria, mais complicada.

página de índice

A página de índice requer dados para as quatro categorias de produtos. Na atual configuração, as marcações JSTL <sql> consultam o banco de dados por detalhes da categoria toda vez que a página de índice for solicitada. Como essas informações são raramente modificadas, faz mais sentido do ponto de vista do desempenho executar a consulta apenas uma vez após a implementação do aplicativo, e armazenar os dados em um atributo de escopo de aplicativo. Podemos realizar isso adicionando esse código ao método init do ControllerServlet.

  1. Na janela Projetos, clique duas vezes no nó Pacotes de código-fonte > controlador > ControllerServlet para abrí-lo no editor.
  2. Declare uma instância de CategoryFacade e aplique a anotação @EJB à instância.
    public class ControllerServlet extends HttpServlet {
    
        @EJB
        private CategoryFacade categoryFacade;
    
        ...
    }
    A anotação @EJB instrui o contêiner EJB a instanciar a variável categoryFacade com o EJB nomeado CategoryFacade.
  3. Utilize as dicas do IDE para adicionar declarações de importação para:
    • javax.ejb.EJB
    • session.CategoryFacade

    Pressionar Ctrl-Shift-I (⌘-Shift-I no Mac) adiciona, automaticamente, importações necessárias à classe.

  4. Adicione o seguinte método init à classe. O contêiner da Web inicializa o servlet chamando seu método init. Isso ocorre apenas uma vez, após o servlet carregar e antes de ele começar a atender solicitações.
    public class ControllerServlet extends HttpServlet {
    
        @EJB
        private CategoryFacade categoryFacade;
    
        public void init() throws ServletException {
    
            // armazena a lista de categorias no contexto do servlet
            getServletContext().setAttribute("categories", categoryFacade.findAll());
        }
    
        ...
    }
    Aqui, aplica-se o método findAll da classe de fachada para consultar o banco de dados de todos os registros de Categoria. Em seguida, define-se a Lista resultante de objetos de Categoria como um atributo que pode ser referenciado pela string "categorias". Colocar a referência no ServletContext significa que a referência existe em um escopo que abrange todo o aplicativo.

    Para determinar rapidamente a assinatura de método do método findAll, mantenha o mouse sobre o método enquanto pressiona a tecla Ctrl (⌘ no Mac). (A imagem abaixo exibe a mensagem pop-up que aparece ao usar o NetBeans IDE 6.8.)

    Editor que exibe assinatura de método em um pop-up
    Clicar no hiperlink habilita a navegação diretamente para o método.
  5. Utilize a dica do IDE para adicionar a anotação @Overrides. O método init é definido pela superclasse do HttpServlet, GenericServlet.
    Dica exibida no editor
    Adicionar a anotação não é necessário, mas oferece várias vantagens:
    • Habilita utilizar a verificação do compilador para garantir que você está, realmente, sobrescrevendo o método que supõe estar sobrescrevendo.
    • Melhora a legibilidade, já que se torna claro quando os métodos do código-fonte estão sendo sobrescritos.

    Para obter mais informações sobre anotações, consulte Tutoriais Java: Anotações.

  6. Agora que configurou um atributo de escopo do aplicativo que contém uma lista de categorias, modifique a página de índice para acessar o atributo recém-criado.

    Clique duas vezes no nó Páginas da Web > index.jsp na janela Projetos para abrir o arquivo no editor.
  7. Comente (ou exclua) a declaração <sql:query> que está listada na parte superior do arquivo. Para comentar código no editor, realce o código e pressione Ctrl-/ (⌘-/ no Mac).
    Trecho de código comentado exibido no editor
  8. Modifique a marcação <c:forEach> de abertura para que o atributo items faça referência ao novo atributo categories de escopo do aplicativo.
    <c:forEach var="category" items="${categories}">
  9. Abra o descritor de deployment Web do projeto. Pressione Alt-Shift-O (Ctrl-Shift-O no Mac) e na caixa de diálogo Ir para arquivo, digite "web" e clique em OK.
    Caixa de diálogo Ir para arquivo
  10. Comente (ou exclua) a entrada <resource-ref>. A entrada foi necessária para as marcações <sql>, a fim de identificar a fonte de dados registrada no servidor. Agora contamos com o JPA para acessar o banco de dados e a fonte de dados jdbc/affablebean já foi especificada na unidade de persistência. (Consulte Visualização de Desenho da unidade de persistência do projeto acima).

    Realce toda a entrada <resource-ref> e pressione Ctrl-/ (⌘-/ no Mac).
    <!-- <resource-ref>
             <description>Connects to database for AffableBean application</description>
             <res-ref-name>jdbc/affablebean</res-ref-name>
             <res-type>javax.sql.DataSource</res-type>
             <res-auth>Container</res-auth>
             <res-sharing-scope>Shareable</res-sharing-scope>
         </resource-ref> -->
  11. Executar o projeto. Clique no botão Executar projeto (botão Executar projeto ). A página de índice do projeto é aberta no navegador, e verá que todos os nomes e imagens das quatro categorias são exibidos.
    Página de índice exibindo detalhes da categoria

página de categoria

A página de categoria requer três partes de dados para ser exibida adequadamente:

  1. dados da categoria: para botões de categoria da coluna esquerda
  2. categoria selecionada: a categoria selecionada é realçada na coluna esquerda e o nome da categoria selecionada é exibido acima da tabela de produtos
  3. dados de produto para a categoria selecionada: para produtos exibidos na tabela de produtos

Vamos abordar cada uma das três partes de dados individualmente.

dados da categoria

Para explicar os dados da categoria, podemos reutilizar o atributo categories criado para a página de índice.

  1. Abra category.jsp no editor e comente (Ctrl-/; ⌘-/ no Mac) as declarações JSTL <sql> listadas na parte superior do arquivo.
    Declarações <sql> comentadas no editor
  2. Modifique a marcação <c:forEach> de abertura para que o atributo items faça referência ao atributo categories de escopo do aplicativo. (Isso é idêntico ao que foi feito acima para index.jsp).
    <c:forEach var="category" items="${categories}">
  3. Execute o projeto para examinar o estado atual da página da categoria. Clique no botão Executar projeto (botão Executar projeto ). Quando a página de índice do projeto abrir no navegador, clique em qualquer uma das quatro categorias. Os botões de categoria na coluna esquerda são exibidos e funcionam como esperado.
    Página de categoria que exibe os botões de categoria na coluna esquerda

categoria selecionada

Para recuperar a categoria selecionada, podemos utilizar a categoryFacade que já criamos para encontrar a Category cuja ID corresponde à sequência de caracteres de consulta.

  1. Abra o ControllerServlet no editor. (Se já estiver aberto, pressione Ctrl-Tab e escolha na lista pop-up).
  2. Inicie a implementação da funcionalidade para adquirir a categoria selecionada. Localize o comentário A FAZER: Implementar solicitação de categoria, exclua o mesmo e adicione o seguinte código (em negrito).
    // if category page is requested
    if (userPath.equals("/category")) {
    
        // get categoryId from request
        String categoryId = request.getQueryString();
    
        if (categoryId != null) {
    
        }
    
    // if cart page is requested
    } else if (userPath.equals("/viewCart")) {
    Você recupera a ID da categoria solicitada chamando getQueryString() na solicitação.

    Nota: A lógica para determinar a categoria selecionada nos botões de categoria da coluna esquerda já está implementada em category. jsp utilizando uma expressão EL, o que é comparável a chamar getQueryString() no servlet. A expressão EL é: pageContext.request.queryString.

  3. Adicione a seguinte linha de código na declaração se.
    // obter categoryId da solicitação
    String categoryId = request.getQueryString();
    
    if (categoryId != null) {
    
        // obter categoria selecionada
        selectedCategory = categoryFacade.find(Short.parseShort(categoryId));
    }
    Você utiliza o método find da CategoryFacade para recuperar o objetoCategory (categoria) com base na ID da categoria solicitada. Observe que é necessário difundir categoryId para um Short, já que é o tipo utilizado para o campo id na classe de entidade Category.
  4. Clique no emblema ( Emblema de dica ) na margem esquerda para utilizar a dica do editor para declarar selectedCategory como uma variável local no método doGet.
    Dicas do editor
    Como a selectedCategory é um tipo de Category (Categoria), que ainda não foi importada para a classe, o IDE adiciona automaticamente uma declaração de importação para entity.Category no topo do arquivo.
  5. Adicione a seguinte linha para colocar o objeto Categoria recuperado no escopo solicitado.
    // obter categoryId da solicitação
    String categoryId = request.getQueryString();
    
    if (categoryId != null) {
    
        // obter categoria selecionada
        selectedCategory = categoryFacade.find(Short.parseShort(categoryId));
    
        // colocar categoria selecionada no escopo solicitado
        request.setAttribute("selectedCategory", selectedCategory);
    }
  6. No editor, mude para category. jsp. (Pressione Ctrl-Tab e escolha na lista pop-up).
  7. Localize <p id="categoryTitle"> e faça a seguinte alteração.
    <p id="categoryTitle">
        <span style="background-color: #f5eabe; padding: 7px;">${selectedCategory.name}</span>
    </p>
    Agora você está utilizando o atributo selectedCategory, que acabou de colocar no escopo de solicitação do ControllerServlet. Utilizar '.name' na expressão EL chama o método getName no objeto Category determinado.
  8. Retorne ao navegador e atualize a página de categoria. O nome da categoria selecionada é exibido, agora, na página.
    Página da categoria exibindo o nome da categoria selecionada

dados de produto para a categoria selecionada

Para recuperar todos os produtos de uma categoria selecionada, faremos uso do método getProductCollection() da entidade Category. Comece por chamar este método em selectedCategory para obter uma coleção de todos os Produtos associados à selectedCategory. A seguir, armazene a coleção de produtos como um atributo no escopo da solicitação e, finalmente, referencie o atributo com escopo da visualização da página category.jsp.

  1. No ControllerServlet, adicione a seguinte declaração ao código que gerencia a solicitação de categoria.
    // se a página de categoria for solicitada
    if (userPath.equals("/category")) {
    
        // obter categoryId da solicitação
        String categoryId = request.getQueryString();
    
        if (categoryId != null) {
    
            // obter categoria selecionar
            selectedCategory = categoryFacade.find(Short.parseShort(categoryId));
    
            // colocar a categoria selecionada no escopo de solicitação
            request.setAttribute("selectedCategory", selectedCategory);
    
             // obter todos tos produtos da categoria selecionanda
            categoryProducts = selectedCategory.getProductCollection(); 
        }
    Chamar getProductCollection() aqui permite obter uma coleção de todos os Produtos associados à selectedCategory.
  2. Utilize as dicas do editor para definir categoryProducts como uma variável local para o método doGet.
    Dicas do editor
  3. Coloque a coleção de Produtos no escopo da solicitação, de modo que possa ser recuperada do front-end do aplicativo.
    // se a página de categoria for solicitada
    if (userPath.equals("/category")) {
    
        // obter categoryId da solicitação
        String categoryId = request.getQueryString();
    
        if (categoryId != null) {
    
            // obter categoria selecionada
            selectedCategory = categoryFacade.find(Short.parseShort(categoryId));
    
            // colocar categoria selecionada no escopo da solicitação
            request.setAttribute("selectedCategory", selectedCategory);
    
            // obter todos os produtos da categoria selecionada
            categoryProducts = selectedCategory.getProductCollection();
    
            // colocar produtos da categoria no escopo da solicitação
            request.setAttribute("categoryProducts", categoryProducts);
        }
  4. Abra o arquivo category.jsp no editor e faça a seguinte alteração à tabela de produtos.
    <table id="productTable">
    
        <c:forEach var="product" items="${categoryProducts}" varStatus="iter">
    O identificador <c:forEach> agora faz referência à coleção categoryProducts. O ciclo c:forEach agora interagirá sobre cada objeto de Produto contido na lista e extrairá os dados de acordo.
  5. Pressione F6 (fn-F6 no Mac) para executar o projeto. Navegue para a página da categoria no navegador e note que todos os produtos agora são exibidos para cada categoria.
    Página da categoria que exibe produtos na tabela

Esta unidade do tutorial forneceu uma breve introdução às tecnologias JPA e EJB. Também descreveu a função das especificações JAVA e como suas implementações de referência são utilizadas pelo servidor de aplicativo GlassFish. Em seguida, demonstrou como criar um conjunto de classes de entidade JPA que fornecem uma implementação Java do banco de dados do projeto. Em seguida, seguindo o padrão fachada de sessão, exibiu como criar um conjunto de beans de sessão EJB que existem na parte superior das classes de entidade e habilitar acesso conveniente a eles. Finalmente, você modificou o projeto AffableBean para utilizar os novos beans de sessão e entidades para acesso a banco de dados necessários nas páginas de índice e de categoria.

É possível baixar o instantâneo 4 do projeto AffableBean, que corresponde ao estado do projeto após a conclusão desta unidade usando o NetBeans IDE 6.9.

Na próxima unidade exploraremos o gerenciamento de sessão e como habilitar o aplicativo para lembrar a ação de um usuário, conforme ele ou ela clica pelo site. Essa é a chave para implementar um mecanismo de carrinho de compra em um aplicativo de e-commerce.



Consulte também

Recursos do NetBeans

Recursos EJB

Recursos JPA

Recursos do GlassFish

Artigos técnicos

Livros


Referências

  1. ^ Adaptado de EJB 3 em ação Capítulo 1, seção 1.1.2: EJB como estrutura.
  2. ^ Há muitos outros serviços fornecidos pelo EJB. Para obter uma lista mais abrangente, consulte EJB 3 em ação, Capítulo 1, seção 1.3.3: Como ganhar funcionalidade com serviços EJB.