4. O serviço web J2EE de agendamentos
Voltemos à arquitetura do aplicativo a ser desenvolvido:
![]() |
Nesta seção, vamos nos concentrar na construção do serviço web J2EE [1] executado em um servidor Sun / Glassfish.
4.1. O banco de dados
O banco de dados, que chamaremos de [dbrdvmedecins] , é um banco de dados MySQL5 com quatro tabelas:

4.1.1. A tabela [MEDECINS]
Ela contém informações sobre os médicos gerenciados pelo aplicativo [RdvMedecins].
![]() | ![]() |
- ID: número que identifica o médico — chave primária da tabela
- VERSION: número que identifica a versão da linha na tabela. Esse número é incrementado em 1 sempre que uma alteração é feita na linha.
- NOM: o sobrenome do médico
- PRENOM: seu nome
- TITRE: seu título (Srta., Sra., Sr.)
4.1.2. A tabela [CLIENTS]
Os clientes dos diferentes médicos estão registrados na tabela [CLIENTS]:
![]() | ![]() |
- ID: número de identificação do cliente — chave primária da tabela
- VERSION: número que identifica a versão da linha na tabela. Esse número é incrementado em 1 sempre que uma modificação é feita na linha.
- NOM: o nome do cliente
- PRENOM: seu nome
- TITRE: seu título (Srta., Sra., Sr.)
4.1.3. A tabela [CRENEAUX]
Ela lista os horários em que os RV são possíveis:
![]() |
![]() |
- ID: número que identifica o intervalo horário — chave primária da tabela (linha 8)
- VERSION: número que identifica a versão da linha na tabela. Esse número é incrementado em 1 sempre que uma alteração é feita na linha.
- ID_MEDECIN: número que identifica o médico ao qual esse horário pertence – chave estrangeira na coluna MEDECINS (ID).
- HDEBUT: hora de início do horário
- MDEBUT: minutos de início do horário
- HFIN: hora de término do horário
- MFIN: minutos de término do intervalo
A segunda linha da tabela [CRENEAUX] (ver [1] acima) indica, por exemplo, que o horário nº 2 começa às 8h20 e termina às 8h40 e pertence à médica nº 1 (Sra. Marie PELISSIER).
4.1.4. A tabela [RV]
Ela lista os RV atribuídos a cada médico:
![]() |
- ID: número que identifica o RV de forma exclusiva – chave primária
- JOUR: dia do RV
- ID_CRENEAU: horário do RV – chave estrangeira no campo [ID] da tabela [CRENEAUX] – define tanto o horário quanto o médico em questão.
- ID_CLIENT: número do cliente para o qual a reserva foi feita – chave estrangeira no campo [ID] da tabela [CLIENTS]
Esta tabela possui uma restrição de unicidade na sobre os valores das colunas associadas (JOUR, ID_CRENEAU):
Se uma linha da tabela [RV] tiver o valor (JOUR1, ID_CRENEAU1) para as colunas (JOUR, ID_CRENEAU), esse valor não pode aparecer em nenhum outro lugar. Caso contrário, isso significaria que dois RV foram registrados ao mesmo tempo para o mesmo médico. Do ponto de vista da programação em Java, o driver JDBC do banco de dados aciona um SQLException quando esse caso ocorre.
A linha de id igual a 3 (ver [1] acima) significa que um RV foi agendado para o horário nº 20 e o cliente nº 4 em 23/08/2006. A tabela [CRENEAUX] nos informa que o horário n.º 20 corresponde ao intervalo das 16h20 às 16h40 e pertence à médica n.º 1 (Sra. Marie PELISSIER). A tabela [CLIENTS] nos informa que o cliente nº 4 é a Srta. Brigitte BISTROU.
4.2. Geração do banco de dados
Crie o banco de dados MySql [dbrdvmedecins] com a ferramenta de sua preferência. Para criar as tabelas e preenchê-las, é possível utilizar o script [createbd.sql], que será fornecido a você. Seu conteúdo é o seguinte:
4.3. Os elementos da arquitetura do lado do servidor
Voltemos à arquitetura do aplicativo a ser desenvolvido:
![]() |
No lado do servidor, a aplicação será composta por:
- de uma camada JPA que permite trabalhar com a BD por meio de objetos
- de um EJB responsável por gerenciar as operações com a camada JPA
- um serviço web encarregado de expor aos clientes remotos a interface do EJB na forma de um serviço web.
Os elementos (b) e (c) implementam a camada [dao] representada no esquema anterior. Sabe-se que uma aplicação pode acessar um EJB remoto por meio dos protocolos RMI e JNDI. Na prática, isso limita os clientes a clientes Java. Um serviço web utiliza um protocolo de comunicação padronizado que é implementado por diversas linguagens: .NET, PHP, C++, etc. É isso que queremos demonstrar aqui, utilizando um cliente .NET.
Para uma breve introdução aos serviços web, consulte o curso [ref1], parágrafo 14, página 109.
Um serviço web pode ser implementado de duas maneiras:
- por meio de uma classe anotada com @WebService que é executada em um contêiner web
![]() |
- por meio de um EJB anotado com @WebService que é executado em um contêiner EJB
![]() |
![]() |
Vamos utilizar aqui a primeira solução:
No curso [ref1], parágrafo 14, página 109, há um exemplo que utiliza a segunda solução.
4.4. Configuração do servidor Glassfish para Hibernate
Dependendo da versão, o servidor Glassfish V2 fornecido com o NetBeans pode não conter as bibliotecas do Hibernate necessárias para a camada JPA/Hibernate. Se, ao longo do tutorial, você perceber que o Glassfish não oferece uma implementação JPA/Hibernate ou que, ao implantar os serviços, uma exceção indicar que as bibliotecas do Hibernate não foram encontradas, você deverá adicionar as bibliotecas à pasta [<glassfish>/domains/domain1/lib/ext] e, em seguida, reiniciar o servidor Glassfish:
![]() |
|
As bibliotecas do Hibernate estão no arquivo zip que acompanha o tutorial.
4.5. As ferramentas de geração automática do NetBeans
Voltemos à arquitetura que precisamos construir:
![]() |
Com o NetBeans, é possível gerar automaticamente a camada [JPA] e a camada [Ejb], que controla o acesso às entidades JPA geradas. É interessante conhecer esses métodos de geração automática, pois o código gerado fornece indicações valiosas sobre como escrever entidades JPA ou o código EJB que as utiliza.
Descreveremos agora algumas dessas ferramentas de geração automática. Para compreender o código gerado, é necessário ter bons conhecimentos sobre as entidades JPA, [ref1] e as EJB, [ref2].
Criação de uma conexão do NetBeans com o banco de dados
- Execute o SGBD e o MySQL 5 para que o BD fique disponível
- Crie uma conexão do NetBeans com o banco de dados [dbrdvmedecins]
![]() |
- na guia [Files], no ramo [Databases] [1], selecionar o driver JDBC MySQL [2]
- e, em seguida, selecione a opção [3] “Connect Using”, que permite criar uma conexão com um banco de dados MySQL
- em [4], forneça as informações solicitadas
- e, em seguida, confirme em [5]
![]() |
- em [6], a conexão é criada. Nela, é possível ver as quatro tabelas do banco de dados conectado.
Criação de um projeto EJB
![]() |
- em [1], crie um novo aplicativo, um módulo EJB
- em [2], selecione a categoria [Java EE] e, em [3], o tipo [EJB Module]
![]() |
- em [4], escolha uma pasta para o projeto e, em [5], dê um nome a ele — em seguida, conclua o assistente
- em [6] o projeto gerado
Adicionando um recurso JDBC ao servidor Glassfish
Vamos adicionar um recurso JDBC ao servidor Glassfish.
![]() |
![]() |
- na guia [Services], inicie o servidor Glassfish [2, 3]
- na guia [Projects], clique com o botão direito do mouse no projeto EJB e, em [5], selecione a opção [New / Other] que permite adicionar um elemento ao projeto.

- em [6], selecione a categoria [Glassfish] e, em [7], indique que deseja criar um recurso JDBC, selecionando o tipo [JDBC Resource]
- em [8], indique que esse recurso JDBC utilizará seu próprio pool de conexões
- em [9], atribuir um nome ao recurso JDBC
- em [10], passar para a próxima etapa
![]() |
- em [11], definem-se as características do pool de conexões do recurso JDBC
- em [12], atribua um nome ao pool de conexões
- em [13], selecione a conexão do NetBeans [dbrdvmedecins] criada anteriormente
- em [14], avance para a próxima etapa
- em [15], normalmente não há nada a ser alterado nesta página. As propriedades da conexão com o banco de dados MySQL [dbrdvmedecins] foram extraídas das propriedades da conexão do NetBeans [dbrdvmedecins] criada anteriormente
- em [16], passe para a próxima etapa
![]() |
- em [17], mantenha os valores padrão sugeridos
- em [18], conclua o assistente. Ele cria os arquivos [sun-resources.xml] e [19], cujo conteúdo é o seguinte:
O arquivo acima contém todas as informações inseridas no assistente no formato XML. Ele será utilizado pelo NetBeans para solicitar ao servidor GlassFish que crie o recurso “jdbc/dbrdvmedecins”, definido na linha 4.
Criação de uma unidade de persistência
A unidade de persistência [persistence.xml] configura a camada JPA: ela indica a implementação JPA utilizada (Toplink, Hibernate, ...) e a configura.
![]() |
![]() |
- em [1], clique com o botão direito do mouse no projeto EJB e selecione [New / Other] em [2]
- em [3], selecione a categoria [Persistence] e, em seguida, em [4], indique que deseja criar uma unidade de persistência JPA
![]() |
- em [5], atribua um nome à unidade de persistência criada
- em [6], selecione [Hibernate] como implementação JPA
- em [7], selecione o recurso Glassfish “jdbc/dbrdvmedecins” que acabou de ser criado
- em [8], indicar que nenhuma ação deve ser realizada no banco de dados durante a instanciação da camada JPA
- concluir o assistente
- no [9], o arquivo [persistence.xml] criado pelo assistente
Seu conteúdo é o seguinte:
Mais uma vez, ele retoma, no formato XML, as informações fornecidas no assistente. Esse arquivo é insuficiente para trabalhar com o banco de dados MySQL5 “dbrdvmedecins”. Precisaríamos indicar ao Hibernate o tipo de SGBD a ser gerenciado. Isso será feito posteriormente.
Criação das entidades JPA
![]() |
![]() |
![]() |
- em [1], clique com o botão direito do mouse no projeto e, em [2], selecione a opção [New / Other]
- em [3], selecione a categoria [Persistence] e, em seguida, em [4], indique que deseja criar entidades JPA a partir de um banco de dados existente.
![]() |
- em [5], selecione a fonte JDBC “jdbc/dbrdvmedecins” que criamos
- em [6], as quatro tabelas do banco de dados associado
- em [7,8], inclua todas elas na geração das entidades JPA
- em [9], continuar com o assistente
![]() |
- em [10], as entidades JPA que serão geradas
- em [11], atribuir um nome ao pacote das entidades JPA
- em [12], escolher o tipo Java que irá encapsular as listas de objetos retornadas pela camada JPA
- concluir o assistente
- em [13], as quatro entidades JPA geradas, uma para cada tabela do banco de dados.
Aqui está, por exemplo, o código da entidade [Rv], que representa uma linha da tabela [rv] do banco de dados [dbrdvmedecins].
Criação da camada EJB de acesso às entidades JPA
![]() |
![]() |
- em [1], clique com o botão direito do mouse no projeto e, em [2], selecione a opção [New / Other]
- em [3], selecione a categoria [Persistence] e, em seguida, em [4], o tipo [Session Beans for Entity Classes]
![]() |
- em [5], as entidades JPA criadas anteriormente são apresentadas
- em [6], selecione todas elas
- em [7], elas foram selecionadas
- em [8], continue com o assistente
![]() |
- em [9], atribuir um nome ao pacote dos EJBs que serão gerados
- em [10], indicar que os EJBs devem implementar tanto uma interface local quanto uma distante
- concluir o assistente
- em [11], os EJBs gerados
Aqui está, por exemplo, o código do EJB que gerencia o acesso à entidade [Rv], ou seja, à tabela [rv] do banco de dados [dbrdvmedecins]:
Como já foi mencionado, a geração automática de código pode ser muito útil para dar início a um projeto e se familiarizar com as entidades JPA e EJB. A seguir, reescreveremos as camadas JPA e EJB com nosso próprio código, mas o leitor encontrará nelas informações que acabamos de ver na geração automática das camadas.
4.6. O projeto NetBeans do módulo EJB
Criamos um novo módulo EJB em branco (ver parágrafo 4.5):
![]() |
- o pacote [rdvmedecins.entites] reúne as entidades da camada JPA
- o pacote [rdvmedecins.dao] implementa o EJB da camada [dao]
- o pacote [rdvmedecins.exceptions] implementa uma classe de exceção específica da aplicação
A seguir, partimos do princípio de que o leitor seguiu todas as etapas do parágrafo 4.5. Ele precisará repetir algumas delas.
4.6.1. Configuração da camada JPA
Vamos relembrar a arquitetura do nosso aplicativo cliente/servidor:
![]() |
O projeto NetBeans:
![]() |
A camada [JPA] é configurada pelos arquivos [persistence.xml] e [sun-resources.xml] acima. Esses dois arquivos são gerados por assistentes já apresentados:
- a geração do arquivo [sun-resources.xml] foi descrita no parágrafo 4.5.
- a geração do arquivo [persistence.xml] foi descrita no parágrafo 4.5.
O arquivo [persistence.xml] gerado deve ser modificado da seguinte forma:
- linha 3: o tipo de transações é JTA: as transações serão gerenciadas pelo contêiner EJB3 do GlassFish
- linha 4: é utilizada uma implementação JPA/Hibernate. Para isso, a biblioteca Hibernate foi adicionada ao servidor GlassFish (ver parágrafo 4.4).
- linha 5: a fonte de dados JTA utilizada pela camada JPA tem o nome JNDI “jdbc/dbrdvmedecins”.
- linha 8: esta linha não é gerada automaticamente. Ela deve ser adicionada manualmente. Ela indica ao Hibernate que o SGBD utilizado é o MySQL5.
A fonte de dados “jdbc/dbrdvmedecins” está configurada no seguinte arquivo [sun-resources.xml]:
- linhas 8-10: as características JDBC da fonte de dados (URL do banco de dados, nome e senha do usuário). O banco de dados MySQL dbrdvmedecins é aquele descrito no parágrafo 4.1.
- linha 7: as características do pool de conexões associado a essa fonte de dados
4.6.2. As entidades da camada JPA
Vale lembrar a arquitetura de nossa aplicação cliente/servidor:
![]() |
O projeto NetBeans:
![]() |
O pacote [rdvmedecins.entites] implementa a camada [Jpa].
Vimos no parágrafo 4.5 como gerar automaticamente as entidades JPA de uma aplicação. Aqui, não utilizaremos essa técnica, mas definiremos nós mesmos as entidades. No entanto, elas reterão boa parte do código gerado no parágrafo 4.5. Aqui, queremos que as entidades [Medecin] e [Client] sejam classes filhas de uma classe [Personne].
A classe Pessoa é utilizada para representar médicos e clientes:
- linha 3: observe-se que a classe [Personne] não é, por si só, uma entidade (@Entity). Ela será a classe pai das entidades. A anotação @MappedSuperClass indica essa situação.
A entidade [Client] encapsula as linhas da tabela [clients]. Ela deriva da classe anterior [Personne]:
- linha 3: a classe [Client] é uma entidade JPA
- linha 4: ela está associada à tabela [clients]
- linha 5: ela deriva da classe [Personne]
A entidade [Medecin], que encapsula as linhas da tabela [medecins], segue o mesmo modelo:
A entidade [Creneau] encapsula as linhas da tabela [creneaux]:
- as linhas 15-17 modelam a relação “um para vários” que existe entre a tabela [creneaux] e a tabela [medecins] do banco de dados.
A entidade [Rv] encapsula as linhas da tabela [rv]:
- as linhas 15-17 modelam a relação “um para vários” que existe entre a tabela [rv] e a tabela [clients] do banco de dados, e as linhas 18-20 modelam a relação “um para vários” que existe entre a tabela [rv] e a tabela [creneaux]
4.6.3. A classe de exceção
![]() |
A classe de exceção [RdvMedecinsException] do aplicativo é a seguinte:
- linha 6: a classe deriva da classe [RuntimeException]. Portanto, o compilador não obriga a tratá-la com try/catch.
- linha 5: a anotação @ApplicationException faz com que a exceção não seja “engolida” por uma exceção do tipo [EjbException].
Para entender a anotação @ApplicationException, voltemos à arquitetura utilizada no lado do servidor:
![]() |
A exceção do tipo [RdvMedecinsException] será lançada pelos métodos do EJB da camada [dao] dentro do contêiner EJB3 e interceptada por ele. Sem a anotação @ApplicationException, o contêiner EJB3 encapsula a exceção ocorrida em uma exceção do tipo [EjbException] e a relança. Pode-se não desejar esse encapsulamento e permitir que uma exceção do tipo [RdvMedecinsException] saia do contêiner Ejb3. É isso que a anotação @ApplicationException permite. Além disso, o atributo (rollback=true) dessa anotação indica ao contêiner EJB3 que, se a exceção do tipo [RdvMedecinsException] ocorrer dentro de um método executado em uma transação com um SGBD, essa transação deve ser revertida. Em termos técnicos, isso é chamado de realizar um rollback na transação.
4.6.4. O EJB da camada [dao]
![]() |
![]() |
A interface Java [IDao] da camada [dao] é a seguinte:
A interface local [IDaoLocal] do EJB limita-se a derivar da interface [IDao] anterior:
O mesmo se aplica à interface remota [IDaoRemote]:
O EJB [DaoJpa] implementa ambas as interfaces, a local e a remota:
- a linha 3 indica que o EJB remoto tem o nome “rdvmedecins.dao”
- a linha 4 indica que todos os métodos do EJB são executados dentro de uma transação gerenciada pelo contêiner EJB3.
- a linha 5 mostra que o EJB implementa as interfaces local e remota.
O código completo do EJB é o seguinte:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | |
- linha 8: o objeto EntityManager, que gerencia o acesso ao contexto de persistência. Ao instanciar a classe, esse campo será inicializado pelo contêiner EJB por meio da anotação @PersistenceContext da linha 7.
- linha 15: consulta JPQL que retorna todas as linhas da tabela [clients] na forma de uma lista de objetos [Client].
- linha 22: consulta análoga para os médicos
- linha 32: uma consulta JPQL que realiza uma junção entre as tabelas [creneaux] e [medecins]. Ela é configurada pelo ID do médico.
- linha 43: uma consulta JPQL que realiza uma junção entre as tabelas [rv], [creneaux] e [medecins] e possui dois parâmetros: o ID do médico e o dia da consulta.
- linhas 55-57: criação de uma consulta e, em seguida, seu armazenamento no banco de dados.
- linha 67: exclusão de uma consulta do banco de dados.
- linha 76: realiza uma consulta no banco de dados para localizar um determinado cliente
- linha 85: o mesmo para um médico
- linha 94: o mesmo para uma consulta
- linha 103: o mesmo para um horário
- Todas as operações com o contexto de persistência em da linha 9 podem apresentar um problema com o banco de dados. Por isso, todas elas estão envoltas por um try/catch. A eventual exceção é encapsulada na exceção “própria” RdvMedecinsException.
O módulo EJB, uma vez compilado, gera um arquivo .jar :
![]() |
4.7. Implantação do EJB da camada [dao] com o NetBeans
O NetBeans permite implantar de forma simples no servidor GlassFish o EJB criado anteriormente.
![]() |
- Nas propriedades do projeto EJB, verifique as opções de execução [1].
- em [2], o nome do servidor no qual o EJB será implantado
- na guia [Services] [3], inicie-o [4].
![]() |
- em [5], o servidor GlassFish, uma vez iniciado. Ele ainda não possui nenhum módulo EJB.
- Inicie o servidor MySQL e verifique se o banco de dados [dbrdvmedecins] está online. Para isso, você pode usar a conexão do NetBeans criada no parágrafo 4.5.
- Na guia [Projects] [6], implante o módulo EJB [7]: é necessário que o SGBD MySQL5 esteja em execução para que o recurso JDBC “jdbc/dbrdvmedecins”, utilizado pelo EJB, esteja acessível.
- No [8], o EJB implantado aparece na árvore de diretórios do servidor GlassFish
![]() |
- No [9], remove-se o EJB implantado
- em [10], o EJB não aparece mais na árvore de diretórios do servidor GlassFish.
4.8. Implantação do EJB da camada [dao] com o GlassFish
Mostramos aqui como implantar um EJB no servidor GlassFish a partir de seu arquivo .jar.
- Inicie o servidor MySQL e certifique-se de que o banco de dados [dbrdvmedecins] esteja ativo. Para isso, você pode usar a conexão do NetBeans criada no parágrafo 4.5.
Vamos relembrar a configuração JPA do módulo EJB que será implantado. Essa configuração é feita no arquivo [persistence.xml]:
A linha 5 indica que a camada JPA utiliza uma fonte de dados JTA, c.a.d, gerenciada pelo contêiner EJB3, denominada “jdbc/dbrdvmedecins”.
Vimos no parágrafo 4.5 como criar esse recurso JDBC a partir do NetBeans. Mostramos aqui como fazer isso diretamente com o GlassFish. Seguimos aqui um procedimento descrito no parágrafo 13.1.2, página 79 do [ref1].
Começamos excluindo o recurso para poder recriá-lo. Fazemos isso a partir do NetBeans:
![]() |
- em [1], os recursos JDBC do servidor GlassFish
- para [2]; o recurso “jdbc/dbrdvmedecins” do nosso EJB
- em [3], o pool de conexões desse recurso JDBC
![]() |
- em [4], excluímos o pool de conexões. Isso terá como efeito a exclusão de todos os recursos JDBC que o utilizam, portanto, o recurso “jdbc/dbrdvmedecins”.
- Em [5] e [6], o recurso JDBC e o pool de conexões foram excluídos.
Agora, usamos o console de administração do servidor GlassFish para criar o recurso JDBC e implantar o EJB.
![]() |
- na guia [services] [1] do NetBeans, inicie o servidor GlassFish [2] e, em seguida, acesse [3] sua console de administração
- em [4], faça login como administrador (senha: adminadmin, caso não tenha alterado essa senha durante a instalação ou posteriormente).
![]() |
- em [5], selecione o ramo [Connection Pools] dos recursos do GlassFish
- em [6], crie um novo pool de conexões. Vale lembrar que um pool de conexões é uma técnica para limitar o número de aberturas/fechamentos de conexões com um SGBD. Ao iniciar o servidor, N — um número definido na configuração — conexões são abertas com o SGBD. Essas conexões abertas são, em seguida, disponibilizadas aos EJBs que as solicitam para realizar uma operação com o SGBD. Assim que a operação for concluída, o EJB devolve a conexão ao pool. A conexão nunca é fechada. Ela é compartilhada entre as diferentes threads que acessam o SGBD
- em [7]; atribua um nome ao pool
- em [8]; a classe que modela a fonte de dados é a classe [javax.sql.DataSource]
- em [9]; o SGBD que contém a fonte de dados é, neste caso, o MySQl.
- em [10], passe para a próxima etapa
![]() |
- no [11], o atributo “Connection Validation Required” faz com que, antes de fornecer uma conexão, o pool verifique se ela está operacional. Caso contrário, ele cria uma nova. Isso permite que um aplicativo continue funcionando após uma interrupção momentânea com o SGBD. Durante a interrupção, nenhuma conexão está disponível e exceções são reportadas ao cliente. Quando a interrupção termina, os clientes que continuam solicitando conexões passam a obtê-las novamente: graças ao atributo “Connection Validation Required”, todas as conexões do pool serão recriadas. Sem esse atributo, o pool constataria que as conexões iniciais foram interrompidas, mas não tentaria recriar novas conexões.
- No [12], solicita-se o nível de isolamento “Read Committed” para as transações. Esse nível garante que uma transação T2 não possa ler dados modificados por uma transação T1 enquanto esta última não estiver totalmente concluída.
- No [13], solicita-se que todas as transações utilizem o nível de isolamento especificado no [12]
![]() |
- em [14] e [15], especifique a URL da transação BD cujo pool gerencia as conexões
- no [16], o usuário será root
- no [17], adicione uma propriedade
- no [18], adicione a propriedade “Password” com o valor () no [19]. Embora a captura de tela [19] não mostre isso, não se deve inserir a string vazia, mas sim () (parêntese de abertura, parêntese de fechamento) para indicar uma senha vazia. Se o usuário root do seu SGBD MySQL tiver uma senha que não seja vazia, insira essa senha.
- no [20], conclua o assistente de criação do pool de conexões para o banco de dados MySQL [dbrdvmedecins].
![]() |
- em [21], o pool foi criado. Clique no link correspondente.
- em [22], o botão [Ping] permite criar uma conexão com o banco de dados [dbrdvmedecins]
- em [23], se tudo correr bem, uma mensagem indicará que a conexão foi bem-sucedida
Depois que o pool de conexões for criado, é possível criar um recurso JDBC:
![]() |
- em [1], seleciona-se o ramo [JDBC Resources] da árvore de objetos do servidor
- em [2], cria-se um novo recurso JDBC
- em [3], atribui-se um nome à recurso JDBC. Esse nome deve corresponder ao nome utilizado no arquivo [persistence.xml]:
- no [4], especifica-se o pool de conexões que a nova recurso JDBC deve utilizar: aquele que acabou de ser criado
- no [5], conclui-se o assistente de criação
![]() |
- em [6], o novo recurso JDBC
Agora que o recurso JDBC foi criado, podemos implantar o arquivo jar do EJB:
![]() |
- em [1], selecione o ramo [Enterprise Applications]
- em [2], com o botão [Deploy], indique que deseja implantar uma nova aplicação
- em [3], indique que a aplicação é um módulo EJB
- em [4], selecione o arquivo JAR do EJB [serveur-ejb-dao-jpa-hibernate.jar] que lhe foi fornecido para o TP.
- em [5], você pode alterar o nome do módulo EJB, se desejar
- em [6], conclua o assistente de implantação do módulo EJB
![]() |
- No [7], o módulo EJB foi implantado. Agora ele já pode ser utilizado.
4.9. Testes do EJB da camada [dao]
Agora que o EJB da camada [dao] do nosso aplicativo foi implantado, podemos testá-lo. Faremos isso por meio do seguinte cliente Java:
![]() |
A classe [MainTestsDaoRemote] [1] é uma classe de teste JUnit 4. As bibliotecas em [2] são constituídas, por um lado:
- do arquivo JAR do EJB da camada [dao] [3] (ver parágrafo 4.6.4).
- das bibliotecas GlassFish [4] necessárias para os clientes remotos dos EJBs.
A classe de teste é a seguinte:
- linha 13: observe a instanciação do proxy do EJB remoto. Utiliza-se seu nome JNDI “rdvmedecins.dao”.
- Os métodos de teste utilizam os métodos expostos pelo EJB (ver parágrafo 4.6.4).
Se tudo correr bem, os testes devem ser aprovados:
![]() |
Agora que o EJB da camada [dao] está operacional, podemos prosseguir com sua exposição pública por meio de um serviço web.
4.10. O serviço web da camada [dao]
Para uma breve introdução ao conceito de serviço web, consulte o parágrafo 14, página 111 de [ref1].
Voltemos à arquitetura do servidor de nossa aplicação cliente/servidor:
![]() |
Estamos nos interessando, acima, pelo serviço web da camada [dao]. A única função desse serviço é disponibilizar a interface do EJB da camada [dao] para clientes multiplataforma capazes de se comunicar com um serviço web.
Vale lembrar que há duas maneiras de implementar um serviço web:
- por meio de uma classe anotada com @WebService que é executada em um contêiner web
![]() |
- por meio de um EJB anotado com @WebService que é executado em um contêiner EJB
![]() |
Aqui, utilizamos a primeira solução. No NetBeans, precisamos criar um projeto de empresa com dois módulos:
- o módulo EJB que será executado no contêiner EJB: o EJB da camada [dao].
- o módulo web, que será executado no contêiner web: o serviço web que estamos criando.
Vamos desenvolver esse projeto empresarial de duas maneiras.
4.10.1. Projeto NetBeans - Versão 1
Primeiramente, criamos um projeto NetBeans do tipo “Aplicativo Web”:
![]() |
- em [1], criamos um novo projeto na categoria “Java Web” [2] do tipo “Aplicação Web” [3].
![]() |
- em [4], atribui-se um nome ao projeto e, em [5], especifica-se a pasta na qual ele deve ser gerado
- no [6], define-se o servidor de aplicativos que executará o aplicativo web
- em [7], define-se o contexto da aplicação
- em [8], valida-se a configuração do projeto.
![]() |
- em [9], o projeto gerado. O serviço web que estamos desenvolvendo utilizará o EJB do projeto anterior [10]. Portanto, ele precisa referenciar o arquivo .jar do módulo EJB [10].
- No [11], adicionamos um projeto do NetBeans às bibliotecas do projeto web [12]
![]() |
- no [13], seleciona-se a pasta do módulo EJB no sistema de arquivos e confirma-se.
![]() |
- em [14], o módulo EJB foi adicionado às bibliotecas do projeto web.
Em [15], implementamos o serviço web com a seguinte classe [WsDaoJpa]:
- Na linha 4, a classe [WsdaoJpa] implementa a interface [IDao]. Vale lembrar que essa interface está definida no arquivo do EJB da camada [dao] da seguinte forma:
- linha 3: a anotação @WebService transforma a classe [WsDaoJpa] em um serviço web.
- linhas 6-7: a referência do EJB da camada [dao] será injetada pelo servidor de aplicativos no campo da linha 7. Vale lembrar que é sempre a implementação local (IDaoLocal, neste caso) que é injetada dessa forma. Essa injeção é possível porque o serviço web é executado na mesma JVM que o EJB.
- Todos os métodos do serviço web são marcados com a anotação @WebMethod para torná-los visíveis aos clientes remotos. Um método não marcado com a anotação @WebMethod seria interno ao serviço web e não visível aos clientes remotos. Cada método M do serviço web se limita a chamar o método M correspondente do EJB injetado na linha 7.
A criação desse serviço web é refletida por um novo branch no projeto do NetBeans:
![]() |
Em [1], vemos o serviço web WsDaoJpa e, em [2], os métodos que ele expõe aos clientes remotos.
Vale lembrar a arquitetura do serviço web em desenvolvimento:
![]() |
Os componentes do serviço web que vamos implantar são:
- [1]: o módulo web que acabamos de construir
- [2]: o módulo EJB que criamos em uma etapa anterior e do qual o serviço web depende
Para implantá-los juntos, é preciso reunir os dois módulos em um projeto do NetBeans denominado “corporativo”:
![]() |
No [1], criamos um novo projeto corporativo [2, 3].
![]() |
- No [4,5], nomeia-se o projeto e define-se a pasta de criação
- em [6], escolhe-se o servidor de aplicativos no qual a aplicação empresarial será implantada
- em [7], um projeto corporativo pode ter três componentes: aplicativo web, módulo EJB e aplicativo cliente. Aqui, o projeto é criado sem nenhum componente. Estes serão adicionados posteriormente.
![]() |
- em [8], a aplicação corporativa recém-criada.
![]() |
- em [9], clique com o botão direito do mouse em [Java EE Modules] e adicione um novo módulo
- em [10], apenas os módulos do NetBeans atualmente abertos no IDE são exibidos. Aqui, selecionamos o módulo web [serveur-webservice-1-ejb-dao-jpa-hibernate] e o módulo EJB [serveur-ejb-dao-jpa-hibernate] que criamos.
- No [11], os dois módulos adicionados ao projeto corporativo.
Resta-nos implantar essa aplicação corporativa no servidor GlassFish. Em seguida, o SGBD e o MySQL devem ser iniciados para que a fonte de dados JDBC “jdbc/dbrdvmedecins”, utilizada pelo módulo EJB, fique acessível.
![]() |
- no [1], inicia-se o servidor Glassfish
- se o módulo EJB [serveur-ejb-dao-jpa-hibernate] estiver implantado, ele é desimplantado [2]
- em [3], a aplicação de e-business é implantada
![]() |
- em [4], ela está implantada. Percebe-se que ela contém os dois módulos: Web e EJB.
4.10.2. Projeto NetBeans - versão 2
Mostraremos agora como implantar o serviço web quando não se dispõe do código-fonte do módulo EJB, mas apenas de seu arquivo .jar.
O novo projeto NetBeans do serviço web será o seguinte:
![]() |
Os elementos dignos de nota do projeto são os seguintes:
- [1]: o serviço web é implementado por um projeto NetBeans do tipo [Web Application].
- [2]: o serviço web é implementado pela classe [WsDaoJpa], já estudada
- [3]: o arquivo EJB da camada [dao], que permite que a classe [WsDaoJpa] tenha acesso às definições das diferentes classes, interfaces e entidades das camadas [dao] e [jpa].
Em seguida, elaboramos o projeto empresarial necessário para a implantação do serviço web:
![]() |
- [1], criamos um aplicativo corporativo [ea-rdvmedecins], inicialmente sem nenhum módulo.
- em [2], adicionamos o módulo web [serveur-webservice-ejb-dao-jpa-hibernate] anterior
- em [3], o resultado.
Da forma como está, a aplicação corporativa [ea-rdvmedecins] não pode ser implantada no servidor Glassfish a partir do NetBeans. Ocorre um erro. Portanto, é necessário implantar manualmente o arquivo EAR da aplicação [ea-rdvmedecins]:
![]() |
- o arquivo [ea-rdvmedecins.ear] está localizado na pasta [dist] [2] da guia [Files] do NetBeans.
- Nesse arquivo [3], encontram-se os dois elementos do aplicativo corporativo:
- o arquivo do EJB [serveur-ejb-dao-jpa-hibernate]. Esse arquivo está presente porque fazia parte das bibliotecas referenciadas pelo serviço web.
- o arquivo do serviço web [serveur-webservice- ejb-dao-jpa-hibernate].
- O arquivo [ea-rdvmedecins.ear] é composto por um simples Build e [4] da aplicação corporativa.
- No [5], a operação de implantação falha.
Para implantar o arquivo [ea-rdvmedecins.ear] do aplicativo corporativo, procedemos da mesma forma que foi mostrado durante a implantação do arquivo do EJB [serveur-ejb-dao-jpa-hibernate.jar] no parágrafo 4.2. Utilizamos novamente o cliente web de administração do servidor GlassFish. Não repetiremos as etapas já descritas.
Primeiramente, começaremos por “desinstalar” a aplicação corporativa implantada no parágrafo 4.10.1:
![]() |
- [1]: selecione o ramo [Enterprise Applications] do servidor Glassfish
- em [2], selecione o aplicativo corporativo a ser desinstalado e, em seguida, em [3], desinstale-o
- em [4], a aplicação corporativa foi descarregada
![]() |
- em [1], escolha o ramo [Enterprise Applications] do servidor Glassfish
- em [2], implante um novo aplicativo corporativo
- em [3], selecione o tipo [Enterprise Application]
- em [4], especifique o arquivo .ear do projeto NetBeans [ea-rdvmedecins]
- em [5], implante esse arquivo
![]() |
- em [6]; o aplicativo foi implantado
- em [7]; o serviço web [WsDaoJpa] aparece no ramo [Web Services] do servidor GlassFish. Selecione-o.
- em [8], temos diversas informações sobre o serviço web. A mais interessante para um cliente é a informação [9]: a URI do serviço web.
- Em [10], é possível testar o serviço web
![]() |
- em [11], a URI do serviço web, à qual foi adicionado o parâmetro ?tester. Essa URI exibe uma página de teste. Todos os métodos (@WebMethod) expostos pelo serviço web são exibidos e podem ser testados. Aqui, testamos o método [13], que solicita a lista de clientes.
![]() |
- No [14], apresentamos apenas uma visão parcial da página de resposta. Mas dá para ver que o método getAllClients realmente retornou a lista de clientes. A captura de tela mostra que ele envia sua resposta no formato XML.
Um serviço web é descrito na íntegra por um arquivo XML denominado arquivo WSDL:
![]() |
- em [1] na ferramenta de administração web do servidor Glassfish, selecione o serviço web [WsDaoJpa]
- em [2], siga o link [View WSDL]
![]() |
- em [3]: a URI do arquivo WSDL. É importante conhecer essa informação. Ela é necessária para configurar os clientes desse serviço web.
- em [4], a descrição XML do serviço web. Não faremos comentários sobre esse conteúdo complexo.
4.10.3. Testes JUnit do serviço web
Criamos um projeto no NetBeans para “executar” os testes já realizados com um cliente EJB, desta vez utilizando um cliente para o serviço web recentemente implantado. Seguimos aqui um procedimento semelhante ao descrito no parágrafo 14.2.1, página 115 do [ref1].
![]() |
- em [1], um projeto Java clássico
- em [2], a classe de teste
- em [3], o cliente utiliza o arquivo do EJB para acessar as definições da interface da camada [dao] e das entidades JPA. Vale lembrar que esse arquivo está na subpasta [dist] da pasta do módulo EJB.
Para acessar o serviço web remoto, é necessário gerar classes proxy:
![]() |
No esquema acima, a camada [2] [C=Client] se comunica com a camada [1] [S=Serveur]. Para se comunicar com a camada [S], o cliente [C] precisa estabelecer uma conexão de rede com a camada [S] e se comunicar com ela de acordo com um protocolo específico. As conexões de rede são do tipo TCP e o protocolo de transporte é HTTP. A camada [S], que representa o serviço web, é implementada por um servlet Java executado pelo servidor Glassfish. Não escrevemos essa servlet. Sua geração é automatizada pelo Glassfish a partir das anotações @Webservice e @WebMethod da classe [WsDaoJpa] que escrevemos. Da mesma forma, automatizaremos a geração da camada [C] do cliente. Às vezes, a camada [C] é chamada de camada proxy do serviço web remoto, sendo que o termo proxy designa um elemento intermediário em uma cadeia de software. Aqui, o proxy C é o intermediário entre o cliente que vamos escrever e o serviço web que implantamos.
Com o NetBeans 6.5, o proxy C pode ser gerado da seguinte maneira (para prosseguir, é necessário que o serviço web esteja ativo no servidor GlassFish):
![]() |
- em [1], adicione um novo elemento ao projeto Java
- em [2], selecione o ramo [Web services]
- em [3], selecione [Web Service Client]
![]() |
- em [4], forneça a URI do arquivo WSDL do serviço web. Essa URI foi apresentada no parágrafo 4.10.2.
- em [5], mantenha o valor padrão [JAX-WS]. O outro valor possível é [JAX-RPC]
- Após confirmar o assistente de criação do proxy do serviço web, o projeto do NetBeans foi ampliado com um ramo [Web Service References] [6]. Esse ramo mostra os métodos expostos pelo serviço web remoto.
![]() |
- na guia [Files] [7], foram adicionados códigos-fonte Java [8]. Eles correspondem ao proxy C gerado.
- Em [9], o código de uma das classes. Percebe-se em [10] que elas foram colocadas em um pacote [rdvmedecins.ws]. Não comentaremos o código dessas classes, que, mais uma vez, é bastante complexo.
Para o cliente Java que estamos construindo, o proxy C gerado atua como intermediário. Para acessar o método M do serviço web remoto, o cliente Java chama o método M do proxy C. Assim, o cliente Java chama métodos locais (executados na mesma JVM) e, de forma transparente para ele, essas chamadas locais são traduzidas em chamadas remotas.
Resta-nos saber como chamar os métodos M do proxy C. Voltemos à nossa classe de teste JUnit:
![]() |
Em [1], a classe de teste [MainTestsDaoRemote] é a mesma já utilizada no teste do EJB da camada [dao]:
- na linha [13], o teste test1 é mantido exatamente igual.
- na linha [9], o conteúdo do método [init] foi excluído.
Nesta fase, o projeto apresenta erros, pois o método de teste [test1] utiliza as entidades [Client], [Medecin], [Creneau], [Rv], que não estão mais nos mesmos pacotes de antes. Elas estão no pacote do proxy C gerado. Removemos as instruções import em questão e as regeneramos por meio da operação “Fix Imports”.
![]() |
Voltemos ao código da classe de teste [MainTestsDaoRemote]:
O método [init] da linha 10 deve inicializar a referência da camada [dao] da linha 7. Precisamos saber como utilizar o proxy C gerado em nosso código. O NetBeans nos ajuda nesse processo.
![]() |
- Selecione, no [1], o método [getAllClients] do serviço web com o mouse e, em seguida, arraste esse método para soltá-lo dentro do método [init] da classe de teste.
O resultado obtido é [2]. Esse esboço de código mostra como usar o proxy C gerado:
- A linha [5] mostra que o método [getAllClients] é um método do objeto do tipo [WsDaoJpa] definido na linha 3. O tipo [WsDaoJpa] é uma interface que apresenta os mesmos métodos que aqueles expostos pelo serviço web remoto.
- Na linha [3], o objeto [WsDaoJpa port] é obtido a partir de outro objeto do tipo [WsDaoJpaService], definido na linha 2. O tipo [WsDaoJpaService] representa o proxy C gerado localmente.
- O acesso ao serviço web remoto pode falhar; por isso, todo o código está envolto por um try/catch.
- Os objetos do proxy C estão no pacote [rdvmedecins.ws]
Depois de entender esse código, percebe-se que a referência local do serviço web remoto pode ser obtida por meio do código:
O código da classe de teste JUnit passa a ser o seguinte:
Agora estamos prontos para os testes:
![]() |
No [1], o teste JUnit é executado. No [2], ele é aprovado. Se observarmos as mensagens exibidas no console do NetBeans, encontraremos linhas como as seguintes:
Liste des clients :
rdvmedecins.ws.Client@1982fc1
rdvmedecins.ws.Client@676437
rdvmedecins.ws.Client@1e4853f
rdvmedecins.ws.Client@1e808ca
No lado do servidor, a entidade [Client] possui um método toString que exibe os diversos campos de um objeto do tipo [Client]. Durante a geração automática do proxy C, as entidades são criadas no proxy C, mas apenas com os campos privados acompanhados de seus métodos get/set. Assim, o método toString não foi gerado na entidade [Client] do proxy C. Isso explica a exibição anterior. Isso não prejudica o teste JUnit: ele foi bem-sucedido. Consideraremos, a partir de agora, que temos um serviço web operacional.






























































































