Skip to content

8. Versão 4 – cliente/servidor numa arquitetura de serviço web

Nesta nova versão, a aplicação [Pam] será executada em modo cliente/servidor numa arquitetura de serviço web. Voltemos à arquitetura da aplicação anterior:

Na figura acima, uma camada de comunicação [C, RMI, S] permitia uma comunicação transparente entre o cliente [ui] e a camada remota [metier]. Vamos utilizar uma arquitetura semelhante, em que a camada de comunicação [C, RMI, S] será substituída por uma camada [C, HTTP / SOAP, S]:

O protocolo HTTP / SOAP tem a vantagem, em relação ao protocolo anterior RMI / EJB, de ser multiplataforma. Assim, o serviço web pode ser escrito em Java e implementado no servidor Glassfish, enquanto o cliente pode ser um cliente .NET ou PHP.

Vamos desenvolver esta arquitetura de acordo com três modos diferentes:

  1. o serviço web será assegurado pelo EJB [Metier]
  2. o serviço web será prestado por uma aplicação web que utiliza o EJB e o [Metier]
  3. o serviço web será prestado por uma aplicação web que utiliza o Spring

Um serviço web pode ser implementado de várias formas num servidor Java EE:

  • através de uma classe anotada com @WebService que é executada num contentor web
  • através de um EJB anotado com @WebService que é executado num contentor EJB

Começamos por esta última arquitetura.

8.1. Serviço web implementado por um EJB

8.1.1. A parte do servidor

8.1.1.1. O projeto NetBeans

Comecemos por criar um novo projeto Maven, cópia do projeto EJB [mv-pam-ejb-metier-dao-jpa-eclipselink]:

  

Com a seguinte arquitetura:

a camada [metier] será o serviço web contactado pela camada [ui]. Esta classe não precisa de implementar uma interface. São as anotações que transformam um POJO (Plain Ordinary Java Object) num serviço web. A classe [Metier], que implementa a camada [metier] acima referida, é transformada da seguinte forma:


package metier;

...
@WebService
@Stateless()
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public class Metier implements IMetierLocal,IMetierRemote {
  
  // referências sobre as camadas [DAO]
  @EJB
  private ICotisationDaoLocal cotisationDao = null;
  @EJB
  private IEmployeDaoLocal employeDao=null;
  @EJB
  private IIndemniteDaoLocal indemniteDao=null;
  
  
  // obter a folha de pagamento
@WebMethod
  public FeuilleSalaire calculerFeuilleSalaire(String SS,
...
  }
  
  // lista de funcionários
@WebMethod
   public List<Employe> findAllEmployes() {
...
  }
// importante — não há getters nem setters para os EJB
 }
  • na linha 4, a anotação @WebService transforma a classe [Metier] num serviço web. Um serviço web expõe métodos aos seus clientes. Estes devem ser anotados com o atributo @WebMethod.
  • linhas 19 e 25: os dois métodos da classe [Metier] tornam-se métodos do serviço web.
  • linha 29: é importante que os getters e setters sejam removidos; caso contrário, serão expostos no serviço web, o que provoca erros de segurança.

A adição destas anotações é detetada pelo NetBeans, que, em seguida, altera a natureza do projeto:

Em [1], surgiu uma árvore de diretórios [Web Services] no projeto. Nela encontram-se o serviço web Metier e os seus dois métodos. A aplicação de servidor pode ser implementada em [2]. O servidor MySQL deve estar em execução e a sua base de dados [dbpam_eclipselink] deve existir e estar preenchida. Pode ser necessário, previamente, eliminar os ficheiros [3] e EJB do projeto cliente/servidor EJB analisado anteriormente, para evitar conflitos de nomes. Com efeito, o nosso novo projeto traz consigo os mesmos EJB que os do projeto anterior.

No [1], vemos a nossa aplicação serveur implementada no servidor Glassfish. Assim que o serviço web estiver implementado, pode ser testado:

  • em [1], no projeto atual, testamos o serviço web [Metier]
  • o serviço web está acessível através de diferentes URL. O URL [2] permite testar o serviço web
  • em [3], uma ligação para o ficheiro XML que define o serviço web. Os clientes do serviço web precisam de conhecer o URL deste ficheiro. É a partir deste que é gerada a camada cliente (stubs) do serviço web.
  • no ficheiro [4,5], um formulário que permite testar os métodos expostos pelo serviço web. Estes são apresentados com os respetivos parâmetros que o utilizador pode definir.

Por exemplo, vamos testar o método [findAllEmployes], que não requer nenhum parâmetro:

 

Acima, testamos o método. Recebemos então a resposta abaixo (vista parcial). Nela, encontramos efetivamente os dois funcionários com as respetivas indemnizações. O leitor é convidado a testar, da mesma forma, o método [4], passando-lhe os três parâmetros que este espera.

Image

8.1.2. A parte do cliente

8.1.2.1. O projeto NetBeans do cliente « » console

Criamos agora um projeto Java do tipo [Java Application] para a parte client da aplicação. Não foi possível (junho de 2012) criar um projeto Maven para este cliente. Ocorre um erro, que parece ser conhecido na Internet, mas continua por resolver.

 

Depois de criado o projeto, indicamos que este será cliente do serviço web que acabámos de implementar no servidor Glassfish:

  • em [2], selecionamos o novo projeto e clicamos no botão [New File]
  • em [3], indicamos que pretendemos criar um cliente do serviço web
  • com [4], vamos indicar o projeto NetBeans do serviço web
  • na janela [5], estão listados todos os projetos com um ramo [Web Services]; aqui, apenas o projeto [mv-pam-ws-metier-dao-eclipselink].
  • Um projeto pode implementar vários serviços web. Em [6], selecionamos o serviço web ao qual pretendemos ligar-nos.
  • Em [7], é apresentada a definição do serviço web URL. Esta URL é utilizada pelas ferramentas de software que geram a camada cliente que irá interagir com o serviço web.
  • A camada cliente [C] [1] que será gerada é constituída por um conjunto de classes Java que serão colocadas num único pacote. O nome deste pacote é definido como [8].
  • Assim que o assistente de criação do cliente do serviço web for concluído com o botão [Finish], a camada [C] acima referida é criada.

Isto reflete-se numa série de alterações no projeto:

  • No [10] acima, surge uma árvore de estrutura [Generated Sources] que contém as classes da camada [C], as quais permitem que o cliente [3] comunique com o serviço web. Esta camada permite que o cliente [3] comunique com a camada [metier] [4] como se esta fosse local e não remota.
  • Em [11], surge uma árvore [Web Service References] que lista os serviços web para os quais foi gerada uma camada cliente.

Note-se que, na camada [C] [10] gerada, encontramos classes que foram implementadas no lado do servidor: Indemnite, Cotisation, Employe, FeuilleSalaire, ElementsSalaire, Metier. Metier é o serviço web e as outras classes são classes necessárias a esse serviço. Podemos sentir curiosidade em consultar o seu código. Veremos que a definição das classes que, quando instanciadas, representam objetos manipulados pelo serviço, consiste na definição dos campos da classe e dos seus acessores, bem como na adição de anotações que permitem a serialização da classe num fluxo XML. A classe «Metier» tornou-se uma interface que contém os dois métodos que foram anotados com @WebMethod. Cada um destes métodos dá origem a duas classes, por exemplo, [CalculerFeuilleSalaire.java] e [CalculerFeuilleSalaireResponse.java], em que uma encapsula a chamada ao método e a outra o seu resultado. Por fim, a classe MetierService é a classe que permite ao cliente ter uma referência ao serviço web de negócio remoto:

1
2
3
4
    @WebEndpoint(name = "MetierPort")
    public Metier getMetierPort() {
        return super.getPort(new QName("http://metier/", "MetierPort"), Metier.class);
}

O método getMetierPort na linha 2 permite obter uma referência ao serviço web Metier remoto.

8.1.2.2. O cliente de consola do serviço web Metier

Resta-nos apenas escrever o cliente do serviço web Metier. Copiamos a classe [MainRemote] do projeto [mv-pam-client-metier-dao-jpa-eclipselink], que era um cliente de um servidor EJB, para o novo projeto.

  • em [1], a classe do cliente do serviço web. A classe [MainRemote] apresenta erros. Para as corrigir, começaremos por eliminar todas as instruções [import] existentes na classe e iremos regenerá-las através da opção [Fix Imports]. Com efeito, algumas das classes utilizadas pela classe [MainRemote] fazem agora parte do pacote [client] gerado.
  • No [3], o trecho de código onde a camada [metier] é instanciada é o [3]. A instância é criada com código JNDI para obter uma referência a um EJB remoto.

Alteramos o código da seguinte forma:

  • o código JNDI é eliminado
  • uma vez que a classe [PamException] não existe do lado do cliente, eliminamos o catch associado para manter apenas o catch na classe-mãe [Exception].
  • no [4], resta-nos obter uma referência ao serviço web remoto [Metier] para podermos chamar o seu método [calculerFeuilleSalaire].
  • em [5], com o rato, arrastamos (drag) o método [calculerFeuilleSalaire] do serviço web [Metier] para o soltar (drop) em [4]. É gerado código [6]. Este código genérico pode ser posteriormente adaptado pelo programador.
  • na linha 112, verifica-se que [calculerFeuilleSalaire] é um método da classe [client.Metier] (linha 111). Agora que sabemos como obter a camada [metier], o código anterior pode ser reescrito da seguinte forma:
...    
// Está tudo bem — já é possível solicitar a folha de vencimento
    FeuilleSalaire feuilleSalaire = null;
    Metier metier = null;
    try {
       // instanciação da camada [metier]
      metier = new MetierService().getMetierPort();
       // cálculo da folha de pagamento
      feuilleSalaire = metier.calculerFeuilleSalaire(args[0], nbHeuresTravaillées, nbJoursTravaillés);
    } catch (Throwable th) {
       // cadeia de exceções
      System.out.println("Chaîne des exceptions --------------------------------------");
      System.out.println(th.getClass().getName() + ":" + th.getMessage());
      while (th.getCause() != null) {
        th = th.getCause();
        System.out.println(th.getClass().getName() + ":" + th.getMessage());
      }
      System.exit(1);
    }
     // visualização rápida
...

A linha 7 obtém uma referência ao serviço web Metier. Feito isto, o código da classe não se altera, exceto que, na linha 10, não é a exceção do tipo [Exception] que é tratada, mas sim o tipo mais geral Throwable, a classe pai da classe Exception. Se ocorrer uma exceção, apresentamos todas as causas aninhadas da mesma até à causa original.

Estamos prontos para os testes:

  • certificar-nos de que o SGBD MySQL5 é iniciado, que a base de dados dbpam_eclipselink é criada e inicializada
  • certificar-se de que o serviço web está implementado no servidor Glassfish
  • compilar o cliente (Clean and Build)
  • configurar a execução do cliente
  
  • Executar o cliente

Os resultados na consola são os seguintes:

...
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
...

Com a seguinte configuração:

Image

obtêm-se os seguintes resultados:

1
2
3
4
Chaîne des exceptions --------------------------------------
javax.xml.ws.soap.SOAPFaultException:L'employé de n°[xx] est introuvable
com.sun.xml.internal.ws.developer.ServerSideException:L'employé de n°[xx] est introuvable
Java Result: 1

Note-se que, embora o serviço web [Metier] envie uma exceção do tipo [PamException], a exceção recebida pelo cliente é do tipo [SOAPFaultException]. Mesmo na cadeia de exceções, não se verifica a presença do tipo [PamException].

8.1.3. O cliente Swing do serviço web Metier


Tarefa a realizar: portar o cliente Swing do projeto [mv-pam-client-ejb-metier-dao-jpa-eclipselink] para o novo projeto, para que também passe a ser um cliente do serviço web implementado no servidor Glassfish.


8.2. Serviço web implementado por uma aplicação web

Encontramo-nos agora no contexto da seguinte arquitetura:

O serviço web é assegurado por uma aplicação web executada no contentor web do servidor Glassfish. Este serviço web irá basear-se no EJB [Metier], que por sua vez está implementado no contentor EJB3.

8.2.1. A parte do servidor

Criamos uma aplicação web:

  • em [1], criamos um novo projeto
  • em [2]; este projeto é do tipo [Web Application]
  • em [3], atribuímos-lhe o nome [mv-pam-ws-ejb-metier-dao-eclipselink]
  • em [4], escolhemos a versão Java EE 6
  • em [6], o projeto criado

No esquema abaixo, a aplicação web criada será executada no contentor web. Esta irá utilizar o EJB [Metier], que, por sua vez, será implementado no contentor EJB do servidor.

Para que a aplicação web criada tenha acesso às classes associadas ao EJB [Metier], adicionamos às bibliotecas da aplicação web [mv-pam-ws-ejb-metier-dao-eclipselink], a dependência do servidor EJB [mv-pam-ejb-metier-dao-eclipselink], já analisado.

  • no [1], adicionamos um projeto às dependências do projeto web,
  • em [2], seleciona-se o projeto [mv-pam-ejb-metier-dao-eclipselink],
  • em [3], o tipo da dependência é ejb,
  • em [4], o âmbito da dependência é provided, ou seja, será fornecida pelo ambiente de execução,
  • em [5], a dependência foi adicionada.

Para criar o mesmo serviço web que anteriormente, precisamos de:

  • criar uma classe com a tag @Webservice
  • com dois métodos calculerFeuilleSalaire e findAllEmployes marcados com @WebMethod

Criamos uma classe [PamWsEjbMetier] num pacote [pam.ws]:

  

A classe [PamWsEjbMetier] é a seguinte:

package pam.ws;

import java.util.List;
import javax.ejb.EJB;
import javax.jws.WebMethod;
import javax.jws.WebService;
import jpa.Employe;
import metier.FeuilleSalaire;
import metier.IMetier;
import metier.IMetierLocal;

@WebService
public class PamWsEjbMetier implements IMetier{

  @EJB
  private IMetierLocal metier;

  @WebMethod
  public FeuilleSalaire calculerFeuilleSalaire(String SS, double nbHeuresTravaillées, int nbJoursTravaillés) {
    return metier.calculerFeuilleSalaire(SS, nbHeuresTravaillées, nbJoursTravaillés);
  }

  @WebMethod
  public List<Employe> findAllEmployes() {
    return metier.findAllEmployes();
  }

}
  • linhas 7-10: a classe importa classes do módulo EJB e [pam-serveurws-metier-dao-jpa-eclipselink], cujo projeto Maven foi adicionado às dependências do projeto.
  • linha 12: a classe é um serviço web
  • linha 13: implementa a interface IMetier definida no módulo EJB
  • linhas 18-19: o método calculerFeuilleSalaire é exposto como método do serviço web
  • linhas 23-24: o método findAllEmployes é exposto como método do serviço web
  • linhas 15-16: a interface local do EJB [Metier] é inserida no campo da linha 16. Utilizamos a interface local porque a aplicação web e o módulo EJB são executados no mesmo JVM.
  • linhas 20 e 25: os métodos calculerFeuilleSalaire e findAllEmployes delegam o seu processamento aos métodos com o mesmo nome do EJB [Metier]. A classe serve, portanto, apenas para expor aos clientes remotos os métodos de EJB e [Metier] como métodos de um serviço web.

No NetBeans, a aplicação web é reconhecida como expondo um serviço web:

Para implementar o serviço web no servidor GlassFish, é necessário implementar:

  • o módulo web no contentor web do servidor
  • o módulo EJB no contentor EJB do servidor

Para tal, precisamos de criar uma aplicação do tipo [Enterprise Application] que irá implementar os dois módulos em simultâneo. Para o fazer, é necessário que os dois projetos estejam carregados no NetBeans [2].

Feito isto, criamos um novo projeto [3].

  • no [4], escolhemos um projeto do tipo [Enterprise Application].
  • em [5], atribuímos um nome ao projeto
  • em [6], configuramos o projeto. A versão do Java EE será Java EE 6. Um projeto empresarial pode ser criado com dois módulos: um módulo EJB e um módulo Web. Neste caso, o projeto empresarial irá encapsular o módulo Web e o módulo EJB já criados e carregados no NetBeans. Por isso, não solicitamos a criação de novos módulos.
  • No [7], o projeto empresarial [mv-pam-webapp-ear] assim criado. Foi criado, ao mesmo tempo, outro projeto Maven: o [mv-pam-webapp]. Não nos ocuparemos desse.
  • No [8], adicionamos dependências ao projeto empresarial
  • no [9], adicionamos o projeto web do tipo WAR,
  • no [10], adicionamos o projeto EJB do tipo EJB,
  • em [11], o projeto empresarial com as suas duas dependências.

Compilamos o projeto empresarial através de um «Clean and Build». Estamos praticamente prontos para o implementar no servidor Glassfish. Antes disso, poderá ser necessário descarregar as aplicações já carregadas no servidor, a fim de evitar possíveis conflitos de nomes entre EJB e [11]:

O servidor MySQL deve estar em execução e a base de dados [dbpam_eclipselink] disponível e preenchida. Feito isto, a aplicação empresarial pode ser implementada [12]. Em [13], é possível verificar que a aplicação foi efetivamente implementada no servidor Glassfish.

Podemos testar o serviço web que acabou de ser implementado:

  • em [1], solicitamos o teste do serviço web [PamWsEjbMetier]
  • em [2], a página de teste. Deixamos ao leitor a tarefa de realizar os testes.

8.2.2. A parte do cliente


Tarefa a realizar: seguindo o procedimento descrito no parágrafo 8.1.2.1, criar um cliente de consola para o serviço web anterior.


8.3. Serviço web implementado com Spring e Tomcat

Situamo-nos agora no contexto da seguinte arquitetura:

O serviço web é assegurado por uma aplicação web executada no contentor web do servidor Tomcat. A arquitetura da aplicação será a seguinte:

Iremos basear-nos no projeto [mv-pam-spring-hibernate] desenvolvido no parágrafo 5.11:

  

8.3.1. A parte do servidor

Criamos uma aplicação Maven do tipo web denominada [mv-pam-ws-spring-tomcat] [1]:

Alteramos o ficheiro [pom.xml] para incluir as seguintes dependências [2]:


  <dependencies>
    <dependency>
      <groupId>${project.groupId}</groupId>
      <artifactId>mv-pam-spring-hibernate</artifactId>
      <version>${project.version}</version>
    </dependency>
    <!-- Dependências do Apache CXF -->
    <dependency>
      <groupId>org.apache.cxf</groupId>
      <artifactId>cxf-rt-frontend-jaxws</artifactId>
      <version>2.2.12</version>
    </dependency>
    <dependency>
      <groupId>org.apache.cxf</groupId>
      <artifactId>cxf-rt-transports-http</artifactId>
      <version>2.2.12</version>
    </dependency>
</dependencies>
  • linhas 3-7: a dependência do projeto [spring-pam-jpa-hibernate],
  • linhas 8-17: as dependências do framework Apache CXF e [http://cxf.apache.org/]. Este framework facilita a criação de serviços web.

Este ficheiro [pom.xml] traz consigo numerosas dependências [2].

Voltemos à arquitetura da aplicação:

As chamadas ao serviço web que vamos construir são geridas por um servlet do framework CXF. Isto traduz-se no ficheiro [WEB-INF / web.xml] da seguinte forma:


<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <display-name>mv-pam-ws-spring-tomcat</display-name>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
<!--   Configuração do CXF -->
  <servlet>
    <servlet-name>CXFServlet</servlet-name>
    <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>CXFServlet</servlet-name>
    <url-pattern>/ws/*</url-pattern>
  </servlet-mapping>
  <session-config>
    <session-timeout>
      30
    </session-timeout>
  </session-config>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>
  • O framework CXF depende do Spring. Linhas 4-6: é declarado um listener. A classe correspondente será carregada em simultâneo com a aplicação web. Esta irá utilizar o ficheiro de configuração do Spring [WEB-INF / applicationContext.xml]:
  • linhas 8-12: o servlet CXF, que irá gerir as chamadas ao serviço web que vamos criar,
  • linhas 13-16: os URL tratados pelo servlet CXF serão do tipo /ws/*. Os restantes não serão tratados pelo CXF.

Para definir o serviço web, definimos uma interface e a sua implementação:

A interface [IWsMetier] será a seguinte:


package pam.ws;

import javax.jws.WebService;
import metier.IMetier;

@WebService
public interface IWsMetier extends IMetier{
  
}
  • linha 7: a interface [IWsMetier] deriva da interface [IMetier] da camada [métier] do projeto [mv-pam-spring-hibernate],
  • linha 6: a interface [IWsMetier] é a de um serviço web.

A classe de implementação desta interface é a seguinte:


package pam.ws;

import java.util.List;
import javax.jws.WebMethod;
import javax.jws.WebService;
import jpa.Employe;
import metier.FeuilleSalaire;
import metier.IMetier;

@WebService
public class PamWsMetier implements IWsMetier {

  // camada de negócio
  private IMetier metier;
  
  // Construtor
  public PamWsMetier(){
    
  }
  
  @WebMethod
  public FeuilleSalaire calculerFeuilleSalaire(String SS, double nbHeuresTravaillees, int nbJoursTravailles) {
    return metier.calculerFeuilleSalaire(SS, nbHeuresTravaillees, nbJoursTravailles);
  }

  @WebMethod
  public List<Employe> findAllEmployes() {
    return metier.findAllEmployes();
  }
  
  // getters e setters

  public void setMetier(IMetier metier) {
    this.metier = metier;
  }
  
}
  • linha 11: a classe [PamWsMetier] implementa a interface definida anteriormente,
  • linha 10: define a classe como um serviço web,
  • linha 14: a camada [métier] será injetada pelo Spring,
  • linhas 21 e 26: a anotação @WebMethod transforma um método num método exposto pelo serviço web,
  • linhas 23 e 28: os métodos são implementados com a ajuda da camada [métier].

Resta-nos definir o conteúdo do ficheiro de configuração do Spring [applicationContext.xml]:

O seu conteúdo é o seguinte:


<?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:jaxws="http://cxf.apache.org/jaxws"
       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://cxf.apache.org/jaxws
       http://cxf.apache.org/schemas/jaxws.xsd">
  
  <!-- Apache CXF -->
  <import resource="classpath:META-INF/cxf/cxf.xml" />
  <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
  <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />  

  <!-- camadas inferiores -->
  <import resource="classpath:spring-config-metier-dao.xml" />  
  
  <!-- serviço web -->
  <bean id="wsMetier" class="pam.ws.PamWsMetier">
    <property name="metier" ref="metier"/>
  </bean>
  <jaxws:endpoint id="wsmetier"
                  implementor="#wsMetier"
                  address="/metier">
  </jaxws:endpoint>  

</beans>
  • linhas 13-15: importam-se ficheiros de configuração do Apache CXF. Estes são procurados no Classpath do projeto (atributo classpath:),
  • linhas 4, 9, 10: são declarados espaços de nomes específicos do Apache CXF,
  • linha 18: importa-se o ficheiro de configuração do Spring do projeto [mv-pam-spring-hibernate],
  • linhas 21-23: definem o bean do serviço web com a sua dependência da camada [métier] (linha 22),
  • linhas 24-27: definem o próprio serviço web,
    • linha 25: o bean Spring que implementa o serviço web é aquele definido na linha 21;
    • linha 26: define o URL no qual o serviço web estará disponível, neste caso /metier. Combinada com o formato que as URL processadas pelo Apache CXF devem ter (ver ficheiro web.xml), esta URL passa a ser /ws/metier.

O nosso projeto está pronto para ser executado. Executamo-lo (Run) e acedemos ao URL [http://localhost:8080/mv-pam-ws-spring-tomcat/ws] num navegador:

Image

A página apresenta uma lista de todos os serviços web implementados. Neste caso, existe apenas um. Seguimos o link WSDL:

O texto apresentado, [1], corresponde ao conteúdo de um ficheiro XML que define as funcionalidades do serviço web, como o aceder e quais as respostas que este envia. Deve-se notar que o URL e o [2] estão associados a este ficheiro WSDL. Todos os clientes do serviço web precisam de o conhecer.

8.3.2. A parte do cliente


Tarefa a realizar: seguindo o procedimento descrito no parágrafo 8.1.2.1, criar um cliente de consola para o serviço web anterior.


Nota: para indicar o URL do ficheiro WSDL do serviço web, deve proceder-se da seguinte forma:

Colocaremos em [3] o URL anteriormente anotado em [2].