Skip to content

7. Versão 3: Portar a aplicação PAM para um servidor de aplicações GlassFish

Propomos colocar os EJBs das camadas [business] e [DAO] da arquitetura OpenEJB/EclipseLink no contentor de um servidor de aplicações GlassFish.

A implementação atual com OpenEJB / EclipseLink

Acima, a camada [ui] utiliza a interface remota da camada [business].

Testámos dois contextos de execução: local e remoto. No último modo, a camada [ui] atuou como cliente da camada [business], que é implementada por EJBs. Para operar no modo cliente/servidor, em que o cliente e o servidor são executados em duas JVMs separadas, iremos implementar as camadas [business, DAO, JPA] no servidor Java EE GlassFish. Este servidor está incluído no NetBeans.

A implementação a ser construída com o servidor GlassFish

  • a camada [ui] será executada num ambiente Java SE (Standard Edition)
  • As camadas [lógica de negócio, DAO, JPA] serão executadas num ambiente Java EE (Enterprise Edition) num servidor GlassFish v3
  • O cliente comunicará com o servidor através de uma rede TCP/IP. A comunicação de rede é transparente para o programador, embora este deva estar ciente de que o cliente e o servidor trocam objetos serializados para comunicar, e não referências a objetos. O protocolo de rede utilizado para esta comunicação denomina-se RMI (Remote Method Invocation), um protocolo utilizável apenas entre duas aplicações Java.
  • A implementação JPA utilizada no servidor GlassFish será o EclipseLink.

7.1. A parte server- e da aplicação cliente/servidor PAM

7.1.1. A arquitetura da aplicação

Aqui, estamos a examinar o componente do lado do servidor que será hospedado pelo contentor EJB3 do servidor GlassFish:

O objetivo é portar para o servidor GlassFish o que já foi desenvolvido e testado com o contentor OpenEJB. Esta é a vantagem do OpenEJB e, de forma mais geral, dos contentores EJB incorporados: permitem-nos testar a aplicação num ambiente de execução simplificado. Depois de a aplicação ter sido testada, basta portá-la para um servidor de destino, neste caso o servidor GlassFish.

7.1.1.1. O Projeto NetBeans

Vamos começar por criar um novo projeto NetBeans:

  • em [1], novo projeto
  • Em [2], selecione a categoria «Maven» e, em [3], selecione o tipo de módulo «EJB». O objetivo é compilar um projeto que será hospedado e executado por um contentor EJB, nomeadamente o servidor GlassFish.
  • Utilizando o botão [4a], selecione a pasta pai para a pasta do projeto ou digite o seu nome diretamente em [4b].
  • Em [5], atribua um nome ao projeto
  • Em [6], selecione o servidor de aplicações no qual será executado. O servidor selecionado aqui é um dos que estão visíveis no separador [Runtime / Servers], neste caso o GlassFish v3.
  • Em [7], selecione a versão do Java EE.
  • Em [1], o novo projeto. Este difere de um projeto Java padrão em alguns aspetos:
    • é criada automaticamente uma ramificação [Outras Fontes] [2]. Esta irá conter, em particular, o ficheiro [persistence.xml] que configura a camada JPA,
    • Se compilar o projeto (Build), surge uma dependência [javaee-api-6.0] [3]. É do tipo «provided» porque é fornecida em tempo de execução pelo contentor EJB Glassfish.

7.1.1.2. Configurar a camada de persistência

Por «configuração da camada de persistência», entendemos a criação do ficheiro [persistence.xml], que define:

  • a implementação JPA a utilizar
  • a definição da fonte de dados utilizada pela camada JPA. Esta será uma fonte JDBC gerida pelo servidor GlassFish.

Podemos proceder da seguinte forma. Primeiro, no separador [Runtime / Databases], iremos criar [1] uma ligação à base de dados MySQL5 / dbpam_eclipselink:

Depois de fazer isso, podemos passar à criação do recurso JDBC utilizado pelo módulo EJB:

  • Em [1], crie um novo ficheiro — certifique-se de que o projeto EJB está selecionado antes de realizar esta operação
  • Em [2], selecione o projeto EJB
  • Em [3], selecione a categoria [Glassfish]
  • em [4], selecione «Criar um recurso JDBC»
  • em [5], especifique que o recurso JDBC utilizará um novo conjunto de ligações. Note que um conjunto de ligações é um conjunto de ligações abertas utilizado para acelerar as interações da aplicação com a base de dados.
  • em [6], atribua um nome JNDI ao recurso JDBC criado. Este nome pode ser qualquer coisa, mas geralmente assume a forma jdbc/nome. Este nome JNDI será utilizado no ficheiro [persistence.xml] para designar a fonte de dados que a implementação JPA deve utilizar.
  • Em [7], atribua qualquer nome ao conjunto de ligações que será criado
  • Na lista suspensa [8], selecione a ligação JDBC criada anteriormente para a base de dados MySQL / dbpam_eclipselink.
  • Em [9], um resumo das propriedades do conjunto de ligações — deixe tudo como está
  • Em [10], pode especificar várias propriedades do conjunto de ligações — mantenha os valores predefinidos
  • Em [11], após concluir o assistente para criar um recurso JDBC para o módulo EJB, foi criado um ficheiro [glassfish-resources.xml] na ramificação [Outras Fontes]. O conteúdo deste ficheiro é o seguinte:
// it's okay - you can ask for the payslip in the [metier] layer
    IMetierRemote metier = null;
    FeuilleSalaire feuilleSalaire = null;
    try {
       // configure the embedded Open EJB container
...
       // remote business layer instantiation
      metier = (IMetierRemote) initialContext.lookup("MetierRemote");
       // wage sheet calculation
      feuilleSalaire = metier.calculerFeuilleSalaire(args[0], nbHeuresTravaillées, nbJoursTravaillés);
    } catch (PamException ex) {
...
    } catch (Exception ex) {
...
    }

O ficheiro [glassfish-resources.xml] é um ficheiro XML que contém todos os dados recolhidos pelo assistente. Será utilizado pelo NetBeans para solicitar a criação do recurso JDBC necessário a este módulo ao implementar o módulo EJB no servidor GlassFish.

Pode agora criar o ficheiro [persistence.xml], que irá configurar a camada JPA do módulo EJB:

  • Em [1], crie um novo ficheiro — certifique-se de que o projeto EJB está selecionado antes de realizar esta operação
  • em [2], selecione o projeto EJB
  • em [3], selecione a categoria [Persistência]
  • em [4], crie uma unidade de persistência
  • em [5], atribua um nome à unidade de persistência
  • Em [6], são apresentadas várias implementações JPA. Aqui, selecione [EclipseLink]. Podem ser utilizadas outras implementações, desde que inclua as bibliotecas que as implementam juntamente com as do servidor GlassFish.
  • Na lista suspensa [7], selecione a fonte de dados JDBC [jdbc/dbpam_eclipselink] que acabou de ser criada.
  • Em [8], especifique que as transações são geridas pelo contentor EJB
  • Em [9], especifique que nenhuma operação deve ser realizada na fonte de dados ao implementar o módulo EJB no servidor. Isto porque o módulo EJB utilizará uma base de dados [dbpam_eclipselink] que já foi criada.
  • No final do assistente, foi criado um ficheiro [persistence.xml] [10]. O seu conteúdo é o seguinte:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE resources PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Resource Definitions//EN" "http://glassfish.org/dtds/glassfish-resources_1_5.dtd">
<resources>
  <jdbc-resource enabled="true" jndi-name="jdbc/dbpam_eclipselink" object-type="user" pool-name="dbpamEclipselinkConnectionPool">
    <description/>
  </jdbc-resource>
  <jdbc-connection-pool allow-non-component-callers="false" associate-with-thread="false" connection-creation-retry-attempts="0" connection-creation-retry-interval-in-seconds="10" connection-leak-reclaim="false" connection-leak-timeout-in-seconds="0" connection-validation-method="auto-commit" datasource-classname="com.mysql.jdbc.jdbc2.optional.MysqlDataSource" fail-all-connections="false" idle-timeout-in-seconds="300" is-connection-validation-required="false" is-isolation-level-guaranteed="true" lazy-connection-association="false" lazy-connection-enlistment="false" match-connections="false" max-connection-usage-count="0" max-pool-size="32" max-wait-time-in-millis="60000" name="dbpamEclipselinkConnectionPool" non-transactional-connections="false" pool-resize-quantity="2" res-type="javax.sql.DataSource" statement-timeout-in-seconds="-1" steady-pool-size="8" validate-atmost-once-period-in-seconds="0" wrap-jdbc-objects="false">
    <property name="URL" value="jdbc:mysql://localhost:3306/dbpam_eclipselink"/>
    <property name="User" value="root"/>
    <property name="Password" value=""/>
  </jdbc-connection-pool>
</resources>
  • linha 3: o nome da unidade de persistência [mv-pam-ejb-metier-dao-eclipselinkPU] e o tipo de transação (JTA para um contentor EJB)
  • linha 5: o nome JNDI da fonte de dados utilizada pela camada de persistência: jdbc/dbpam_eclipselink
  • linha 6: as entidades JPA não estão especificadas. Serão procuradas no classpath do módulo EJB.
  • O nome da implementação JPA (Hibernate, EclipseLink, etc.) utilizada não está especificado. Neste caso, o GlassFish v3 utiliza o EclipseLink por predefinição.

7.1.1.3. Inserção das camadas [JPA, DAO, Business]

Agora que o ficheiro [persistence.xml] foi definido, podemos prosseguir com a inserção das camadas [business, DAO, JPA] da aplicação empresarial [pam] no projeto:

Estas três camadas são idênticas às que existiam no OpenEJB. Podemos simplesmente copiar e colar entre os dois projetos. É isso que estamos a fazer agora:

  • em [1], o resultado da cópia dos pacotes [jpa, dao, business, exception] do projeto [mv-pam-openejb-eclipselink] para o módulo EJB [mv-pam-ejb-business-dao-jpa-eclipselink]

7.1.1.4. Configurar o servidor GlassFish

Ainda precisamos de configurar o servidor GlassFish em duas áreas:

  • A camada JPA é implementada pelo EclipseLink. Temos de garantir que o servidor GlassFish possui as bibliotecas necessárias para esta implementação JPA.
  • A fonte de dados é uma base de dados MySQL. Temos de garantir que o servidor GlassFish possui o controlador JDBC para este sistema de gestão de bases de dados.

Poderá verificar que estas bibliotecas estão em falta ao implementar o módulo EJB. Aqui está uma das várias formas de adicionar as bibliotecas em falta ao servidor GlassFish:

  • Em [1], visualize as propriedades do servidor GlassFish
  • Em [2], anote a pasta de domínios do servidor. Vamos referir-nos a ela como <domains>
  • Na pasta <domains>\domain1\lib, coloque as bibliotecas em falta. No exemplo, foram adicionadas as bibliotecas Hibernate (lib/hibernate-tools) e o controlador JDBC do MySQL (lib/misc). Por predefinição, o servidor GlassFish inclui as bibliotecas EclipseLink. Por isso, iremos adicionar apenas o controlador JDBC do MySQL.
  • Em [1], no separador [Serviços], iniciamos o servidor GlassFish v3
  • Em [2], ele está ativo

7.1.1.5. Implementação do módulo EJB

Vamos agora implementar o módulo EJB no servidor GlassFish:

  • Em [1], o módulo EJB é implementado
  • Em [2], a árvore do servidor GlassFish é atualizada
  • em [3], após a implementação, o módulo EJB aparece no ramo [Applications] do servidor GlassFish
  • em [4], o recurso JDBC [jdbc / dbpam_eclipselink] foi criado no servidor GlassFish. Recorde-se que o definimos na Secção 7.1.1.2.

Durante a implementação, o servidor GlassFish regista as seguintes informações na consola:


<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
  <persistence-unit name="mv-pam-ejb-metier-dao-eclipselinkPU" transaction-type="JTA">
    <jta-data-source>jdbc/dbpam_eclipselink</jta-data-source>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <properties/>
  </persistence-unit>
</persistence>

Note que as linhas

  • 3, 6, 8 e 11: os nomes JNDI portáteis dos EJBs implementados. O Java EE 6 introduziu o conceito de nomes JNDI portáteis. Isto denota um nome JNDI reconhecido por todos os servidores Java EE 6. Com o Java EE 5, os nomes JNDI são específicos do servidor que está a ser utilizado.
  • 4, 7, 9, 12: os nomes JNDI dos EJBs implementados num formato específico do GlassFish v3.

Estes nomes serão úteis para a aplicação de consola que vamos escrever para utilizar o módulo EJB implementado.

7.2. Cliente de Consola - Versão 1

Agora que implementámos o lado do servidor da nossa aplicação cliente/servidor, vamos examinar o lado do cliente [1]:

7.2.1. O projeto do cliente

Criamos um novo projeto Maven do tipo [Aplicação Java] com o nome [mv-pam-client-ejb-metier-dao-eclipselink]:

  • em [1], o projeto cliente

No ficheiro [pom.xml], adicionamos as seguintes dependências:

INFO: Realm admin-realm of classtype com.sun.enterprise.security.auth.realm.file.FileRealm successfully created.
....
INFO: Portable JNDI names for EJB IndemniteDao : [java:global/pam-serveur-metier-dao-jpa-eclipselink/IndemniteDao!DAO.IIndemniteDaoLocal, java:global/pam-serveur-metier-dao-jpa-eclipselink/IndemniteDao!DAO.IIndemniteDaoRemote]
INFO: Glassfish-specific (Non-portable) JNDI names for EJB IndemniteDao : [DAO.IIndemniteDaoRemote#DAO.IIndemniteDaoRemote, DAO.IIndemniteDaoRemote]
...
INFO: Portable JNDI names for EJB CotisationDao : [java:global/pam-serveur-metier-dao-jpa-eclipselink/CotisationDao!DAO.ICotisationDaoLocal, java:global/pam-serveur-metier-dao-jpa-eclipselink/CotisationDao!DAO.ICotisationDaoRemote]
INFO: Glassfish-specific (Non-portable) JNDI names for EJB CotisationDao : [DAO.ICotisationDaoRemote, DAO.ICotisationDaoRemote#DAO.ICotisationDaoRemote]
INFO: Portable JNDI names for EJB Metier : [java:global/pam-serveur-metier-dao-jpa-eclipselink/Metier!metier.IMetierRemote, java:global/pam-serveur-metier-dao-jpa-eclipselink/Metier!metier.IMetierLocal]
INFO: Glassfish-specific (Non-portable) JNDI names for EJB Metier : [metier.IMetierRemote#metier.IMetierRemote, metier.IMetierRemote]
...
INFO: Portable JNDI names for EJB EmployeDao : [java:global/pam-serveur-metier-dao-jpa-eclipselink/EmployeDao!DAO.IEmployeDaoLocal, java:global/pam-serveur-metier-dao-jpa-eclipselink/EmployeDao!DAO.IEmployeDaoRemote]
INFO: Glassfish-specific (Non-portable) JNDI names for EJB EmployeDao : [DAO.IEmployeDaoRemote#DAO.IEmployeDaoRemote, DAO.IEmployeDaoRemote]
INFO: pam-serveur-metier-dao-jpa-eclipselink was successfully deployed in 12 891 milliseconds.
  • linhas 31–35: a dependência da biblioteca [gf-client], que permite que um cliente Glassfish comunique com um servidor remoto,
  • linhas 36–41: a dependência do projeto Maven do módulo EJB. Aqui, pretendemos recuperar as definições das entidades JPA e das várias interfaces, bem como a da classe de exceção [PamException],

Do projeto [mv-pam-openejb-eclipselink], copiamos a classe [MainRemote]:

A classe [MainRemote] deve obter uma referência ao EJB na camada [business]. O código da classe [MainRemote] é alterado da seguinte forma:


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
 
  <groupId>istia.st</groupId>
  <artifactId>mv-pam-client-ejb-metier-dao-eclipselink</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>
 
  <name>mv-pam-client-ejb-metier-dao-eclipselink</name>
  <url>http://maven.apache.org</url>
  <repositories>
    <repository>
      <url>http://download.eclipse.org/rt/eclipselink/maven.repo/</url>
      <id>eclipselink</id>
      <layout>default</layout>
      <name>Repository for library Library[eclipselink]</name>
    </repository>    
    <repository>
      <url>http://repo1.maven.org/maven2/</url>
      <id>swing-layout</id>
      <layout>default</layout>
      <name>Repository for library Library[swing-layout]</name>
    </repository>
  </repositories>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
 
  <dependencies>
    <dependency>
      <groupId>org.glassfish.appclient</groupId>
      <artifactId>gf-client</artifactId>
      <version>3.1.1</version>
    </dependency>    
    <dependency>
      <groupId>${project.groupId}</groupId>
      <artifactId>mv-pam-ejb-metier-dao-eclipselink</artifactId>
      <version>${project.version}</version>
      <type>ejb</type>
    </dependency>
    <dependency>
      <groupId>org.swinglabs</groupId>
      <artifactId>swing-layout</artifactId>
      <version>1.0.3</version>
    </dependency>
  </dependencies>
</project>
  • Linha 6: Inicialização do contexto JNDI do servidor GlassFish.
  • linha 8: este contexto JNDI é consultado para obter uma referência à interface remota da camada [business]. De acordo com os registos do GlassFish, sabemos que a interface remota da camada [business] tem dois nomes possíveis:

// it's OK - we can ask for the payslip
    FeuilleSalaire feuilleSalaire = null;
    IMetierRemote metier = null;
    try {
      // context JNDI of Glassfish server
      InitialContext initialContext = new InitialContext();
      // business layer instantiation
      metier = (IMetierRemote) initialContext.lookup("java:global/istia.st_mv-pam-ejb-metier-dao-eclipselink_ejb_1.0-SNAPSHOT/Metier!metier.IMetierRemote");
      // wage sheet calculation
      feuilleSalaire = metier.calculerFeuilleSalaire(args[0], nbHeuresTravaillées, nbJoursTravaillés);
    } catch (PamException ex) {
      System.err.println("L'erreur suivante s'est produite : "
              + ex.getMessage());
      return;
    } catch (Exception ex) {
      System.err.println("L'erreur suivante s'est produite : "
              + ex.toString());
      return;
    }

Linha 1: o nome JNDI que pode ser utilizado com qualquer servidor de aplicações Java EE 6. Linha 2: o nome JNDI específico do GlassFish. No código, na linha 9, utilizamos o nome JNDI portátil.

  • O resto do código permanece inalterado

Em [1], configuramos o projeto para executar a classe [MainRemote] com argumentos. Se tudo correr bem, a execução do projeto produz o seguinte resultado:

Infos: EJB5181:Portable JNDI names for EJB Metier: [java:global/istia.st_mv-pam-ejb-metier-dao-eclipselink_ejb_1.0-SNAPSHOT/Metier!metier.IMetierLocal, java:global/istia.st_mv-pam-ejb-metier-dao-eclipselink_ejb_1.0-SNAPSHOT/Metier!metier.IMetierRemote]
Infos: EJB5182:Glassfish-specific (Non-portable) JNDI names for EJB Metier: [metier.IMetierRemote#metier.IMetierRemote, metier.IMetierRemote]

Se for introduzido um número de segurança social incorreto nas propriedades, obtém-se o seguinte resultado:

run:
Valeurs saisies :
N° de sécurité sociale de l'employé : 254104940426058
Nombre d'heures travaillées : 150
Nombre de jours travaillés : 20

Informations Employé : 
Nom : Jouveinal
Prénom : Marie
Adresse : 5 rue des oiseaux
Ville : St Corentin
Code Postal : 49203
Indice : 2

Informations Cotisations : 
CSGRDS : 3.49 %
CSGD : 6.15 %
Retraite : 7.88 %
Sécurité sociale : 9.39 %

Informations Indemnités : 
Salaire horaire : 2.1 euro
Entretien/jour : 2.1 euro
Repas/jour : 3.1 euro
Congés Payés : 15.0 %

Informations Salaire : 
Salaire de base : 362.25 euro
Cotisations sociales : 97.48 euro
Indemnités d'entretien : 42.0 euro
Indemnités de repas : 62.0 euro
Salaire net : 368.77 euro

BUILD SUCCESSFUL (total time: 2 seconds)

7.3. Consola do cliente - versão 2

Nas versões anteriores, o ambiente JNDI do servidor Glassfish era configurado utilizando um ficheiro [jndi.properties] localizado algures nos arquivos do projeto. O seu conteúdo padrão é o seguinte:

1
2
3
run:
L'erreur suivante s'est produite : L'employé de n°[254104940426058x] est introuvable
BUILD SUCCESSFUL (total time: 2 seconds)

As linhas 7 e 8 especificam a máquina do serviço JNDI e a sua porta de escuta. Este ficheiro não permite consultar um servidor JNDI que não seja o localhost ou que esteja a ser executado numa porta diferente da porta 3700. Se pretender alterar estas duas definições, pode criar o seu próprio ficheiro [jndi.properties] ou utilizar uma configuração Spring. Iremos demonstrar esta última técnica.

Começamos por criar um novo projeto com base no projeto inicial [pam-client-metier-dao-jpa-eclipselink].

  • Em [1], o novo projeto
  • em [2], o ficheiro de configuração do Spring [spring-config-client.xml]. O seu conteúdo é o seguinte:

O ficheiro de configuração do Spring é o seguinte:


# accès JNDI à Sun Application Server
java.naming.factory.initial=com.sun.enterprise.naming.SerialInitContextFactory
java.naming.factory.url.pkgs=com.sun.enterprise.naming
# Required to add a javax.naming.spi.StateFactory for CosNaming that
# supports dynamic RMI-IIOP.
java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl
org.omg.CORBA.ORBInitialHost=localhost
org.omg.CORBA.ORBInitialPort=3700

Aqui estamos a utilizar uma tag <jee> (linha 14) introduzida no Spring 2.0. A utilização desta tag requer a definição do esquema ao qual pertence, linhas 4, 10 e 11.

  • Linha 14: A tag <jee:jndi-lookup> é utilizada para obter uma referência de objeto a partir de um serviço JNDI. Aqui, associamos o bean denominado «metier» ao recurso JNDI associado ao EJB [Metier]. O nome JNDI utilizado aqui é o nome portátil (Java EE 6) do EJB.
  • O conteúdo do ficheiro [jndi.properties] torna-se o conteúdo da tag <jee:environment> (linha 15), que é utilizada para definir os parâmetros de ligação para o serviço JNDI.

A classe principal [MainRemote] é alterada da seguinte forma:


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:jee="http://www.springframework.org/schema/jee"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
       http://www.springframework.org/schema/jee
       http://www.springframework.org/schema/jee/spring-jee-2.0.xsd">
 
  <!-- business -->
  <jee:jndi-lookup id="metier" jndi-name="java:global/istia.st_mv-pam-ejb-metier-dao-eclipselink_ejb_1.0-SNAPSHOT/Metier!metier.IMetierRemote">
    <jee:environment>
      java.naming.factory.initial=com.sun.enterprise.naming.SerialInitContextFactory
      java.naming.factory.url.pkgs=com.sun.enterprise.naming
      java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl
      org.omg.CORBA.ORBInitialHost=localhost
      org.omg.CORBA.ORBInitialPort=3700
    </jee:environment>
  </jee:jndi-lookup>
</beans>

Linhas 7–8: Solicita-se ao Spring a referência do tipo [IMetierRemote] na camada [business]. Esta solução confere flexibilidade à nossa arquitetura. De facto, se o EJB na camada [business] se tornasse local — ou seja, executado na mesma JVM que o nosso cliente [MainRemote] —, o código do cliente permaneceria inalterado. Apenas o conteúdo do ficheiro [spring-config-client.xml] mudaria. Teríamos então uma configuração semelhante à arquitetura Spring/JPA discutida na Secção 5.11.

Convidamos os leitores a testar esta nova versão.

7.4. O Cliente Swing

Vamos agora criar o cliente Swing para a nossa aplicação cliente/servidor EJB.

O ficheiro [pom.xml] deve incluir as dependências necessárias para aplicações Swing:

...
     // it's okay - we can ask for the payslip
    FeuilleSalaire feuilleSalaire = null;
    IMetierRemote metier=null;
    try {
       // instantiation layer [metier]
      ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-config-client.xml");
      metier = (IMetierRemote) ctx.getBean("metier");
       // wage sheet calculation
      feuilleSalaire = metier.calculerFeuilleSalaire(args[0], nbHeuresTravaillées, nbJoursTravaillés);
    } catch (PamException ex) {
      System.err.println("L'erreur suivante s'est produite : "
              + ex.getMessage());
      return;
    } catch (Exception ex) {
      System.err.println("L'erreur suivante s'est produite : "
              + ex.toString());
      return;
    }
    ...

Acima, a classe [PamJFrame] foi originalmente escrita para ser executada num ambiente Spring/JPA:

Agora, esta classe deve tornar-se o cliente remoto de um EJB implementado no servidor Glassfish.


Exercício prático: Seguindo o exemplo do cliente de consola [ui.console.MainRemote] no projeto, modifique a forma como o método [doMyInit] (ver Secção 5.12.4) na classe [PamJFrame] é utilizado para obter uma referência à camada [business], que agora é remota.