Skip to content

4. Executar a aplicação

Agora queremos executar a aplicação fora do IDE STS (para o servidor) e do WebStorm (para o cliente).

4.1. Implantação do serviço web num servidor Tomcat

Vimos na Secção 2.11.9 como criar um arquivo WAR para o Tomcat. Repetimos o processo aqui. Primeiro, para preservar a estrutura existente, duplicamos o projeto Eclipse [rdvmedecins-webapi-v3] para [rdvmedecins-webapi-v4].

  

O ficheiro [pom.xml] é modificado da seguinte forma:


    <modelVersion>4.0.0</modelVersion>
    <groupId>istia.st.spring4.mvc</groupId>
    <artifactId>rdvmedecins-webapi-v4</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
 
    <name>rdvmedecins-webapi-v3</name>
    <description>Gestion de RV Médecins</description>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.0.0.RELEASE</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>istia.st.spring4.rdvmedecins</groupId>
            <artifactId>rdvmedecins-metier-dao-v2</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
</dependencies>

É necessário efetuar alterações em dois locais:

  • linha 5: deve especificar que vai gerar um ficheiro WAR (Web ARchive);
  • linhas 23–27: deve adicionar uma dependência do artefacto [spring-boot-starter-tomcat]. Este artefacto inclui todas as classes do Tomcat nas dependências do projeto;
  • linha 26: este artefacto é [fornecido], o que significa que os ficheiros correspondentes não serão incluídos no WAR gerado. Em vez disso, estes ficheiros estarão localizados no servidor Tomcat onde a aplicação será executada;

Deve também configurar a aplicação web. Na ausência de um ficheiro [web.xml], isto é feito utilizando uma classe que estende [SpringBootServletInitializer]:

  

A classe [ApplicationInitializer] é a seguinte:


package rdvmedecins.web.config;
 
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;
 
public class ApplicationInitializer extends SpringBootServletInitializer {
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(AppConfig.class);
    }
 
}
  • linha 6: a classe [ApplicationInitializer] estende a classe [SpringBootServletInitializer];
  • linha 8: o método [configure] é sobrescrito (linha 7);
  • linha 9: a classe [AppConfig] é fornecida para configurar o projeto;

Depois de fazer isto, poderá ser necessário atualizar o projeto Maven (eu tive de o fazer): [clique com o botão direito do rato no projeto / Maven / Atualizar projeto] ou [Alt-F5].

Para executar o projeto, proceda da seguinte forma:

  • em [1], execute o projeto num dos servidores registados no IDE Eclipse;
  • Em [2], selecione [tc Server Developer], que é a opção predefinida. Trata-se de uma variante do Tomcat;

O resultado obtido é o seguinte:

 

Isto é normal. Lembre-se de que o serviço web não tem o URL [/] nos seus métodos. Quando tenta o URL [/getAllMedecins], obtém a seguinte resposta:

 

Isto é normal. O serviço web está protegido.

Agora vamos iniciar o cliente [rdvmedecins-angular-v2] no WebStorm:

Em [1], introduza o URL do novo serviço web [http://localhost:8080/rdvmedecins-webapi-v4]. Obtemos o seguinte resultado:

Image

Para executar a aplicação fora do IDE do STS, existem várias soluções. Aqui está uma delas.

Descarregue uma versão do Tomcat [http://tomcat.apache.org/download-80.cgi] (julho de 2014):

Selecione uma versão compactada em [1] e descompacte-a em [2]. Volte ao STS:

  • No separador [Servidores], clique com o botão direito do rato na aplicação [rdvmedecins-webapi-v4] e selecione a opção [Procurar local de implementação];
  • em [4]: copie a pasta [rdvmedecins-webapi-v4];
  • em [5], cole a pasta [rdvmedecins-webapi-v4] na pasta [webapps] do Tomcat;
  • Em [6], execute o ficheiro de comando [startup.bat] (o servidor Tomcat integrado no STS deve estar parado). Abre-se uma janela do DOS para apresentar os registos do Tomcat. Estes devem indicar que a aplicação [rdvmedecins-webapi-v4] foi iniciada.

Para verificar isto, execute novamente o cliente Angular [rdvmedecins-angular-v2] no WebStorm:

Em [1], introduza o URL do novo serviço web [http://localhost:8080/rdvmedecins-webapi-v4]. Verá o seguinte resultado:

Image

4.2. Implantação do cliente Angular no servidor Tomcat

Agora que o serviço web foi implementado no Tomcat, vamos também implementar o cliente Angular num servidor. Este pode muito bem ser o servidor que já está a hospedar o serviço web. Vamos seguir esta abordagem.

Primeiro, duplicamos o cliente [rdvmedecins-angular-v2] para [rdvmedecins-angular-v3] e efetuamos as seguintes alterações:

  • em [1], tudo foi movido para uma pasta chamada [ app];
  • em [1], removemos a pasta [bower-components], que continha as várias bibliotecas CSS e JS necessárias para o projeto. Todos estes elementos foram copiados para a pasta [lib] [2];
  • em [1], o ficheiro [app.html] foi renomeado para [index.html];

O ficheiro [index.html] foi modificado para refletir as alterações nos caminhos dos recursos utilizados:


<!DOCTYPE html>
<html ng-app="rdvmedecins">
<head>
  <title>RdvMedecins</title>
...
  <!-- on CSS -->
  ...
  <link href="lib/bootstrap-theme.min.css" rel="stylesheet"/>
  <link href="lib/bootstrap-select.min.css" rel="stylesheet"/>
</head>
<!-- controller [appCtrl], model [app] -->
<body ng-controller="appCtrl">
<div class="container">
  ...
</div>
<!-- Bootstrap core JavaScript ================================================== -->
<script type="text/javascript" src="lib/jquery.min.js"></script>
<script type="text/javascript" src="lib/bootstrap.min.js"></script>
<script type="text/javascript" src="lib/bootstrap-select.min.js"></script>
<script type="text/javascript" src="lib/footable.js"></script>
<!-- angular js -->
<script type="text/javascript" src="lib/angular.min.js"></script>
<script type="text/javascript" src="lib/ui-bootstrap-tpls.min.js"></script>
<script type="text/javascript" src="lib/angular-route.min.js"></script>
<script type="text/javascript" src="lib/angular-translate.min.js"></script>
<script type="text/javascript" src="lib/angular-base64.min.js"></script>
<!-- modules -->
...
<!-- services -->
...
<!-- guidelines -->
...
<!-- controllers -->
....
</body>
</html>

Além disso, o controlador [loginCtrl] foi modificado para apontar para o servidor correto, de modo que o utilizador não tenha de digitar o URL:


// credentials
app.serverUrl = "http://localhost:8080/rdvmedecins-webapi-v4";
app.username = "admin";
app.password = "admin";

Agora que isto está feito, vamos executar o ficheiro [index.html]:

Em seguida, vamos iniciar sessão no serviço web. Deverá funcionar. Depois de verificado, vamos parar o servidor Tomcat. Vamos reutilizar o servidor STS integrado.

No STS, copie todo o conteúdo da pasta [rdvmedecins-angular-v3/app] para a pasta [webapp] do projeto [rdvmedecins-webapi-v4] (separador Navegador) [1]:

Depois de fazer isso, inicie [2] o servidor VMware do STS e, em seguida, aceda ao URL [http://localhost:8080/rdvmedecins-webapi-v4/app/index.html]:

Encontramos um problema de permissões em [3]. Isto não é surpreendente, uma vez que protegemos o serviço web. Precisamos de especificar que o acesso ao ficheiro [/app/index.html] é irrestrito. Voltemos ao Eclipse:

  

Lembre-se de que as permissões de acesso foram definidas na classe [SecurityConfig]. Vamos modificá-la da seguinte forma:


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // CSRF
        http.csrf().disable();
        // the password is transmitted by the header Authorization: Basic xxxx
        http.httpBasic();
        // the HTTP OPTIONS method must be authorized for all
        http.authorizeRequests() //
                .antMatchers(HttpMethod.OPTIONS, "/", "/**").permitAll();
        // the [app] folder is accessible to all
        http.authorizeRequests() //
                .antMatchers(HttpMethod.GET, "/app", "/app/**").permitAll();
        // only the ADMIN role can use the application
        http.authorizeRequests() //
                .antMatchers("/", "/**") // all URL
                .hasRole("ADMIN");
}
  • Linhas 11–12: Concedemos a todos permissão para ler a pasta [app] e o seu conteúdo. Para tal, seguimos o exemplo dado pelas linhas anteriores.

Agora, reinicie o servidor STS Tomcat e solicite a URL [http://localhost:8080/rdvmedecins-webapi-v4/app/index.html] novamente:

Image

Desta vez, funciona.

4.3. Cabeçalhos CORS

Talvez se lembre que tivemos alguma dificuldade em lidar com os cabeçalhos CORS. No exemplo anterior:

  • o serviço web está na URL [http://localhost:8080/rdvmedecins-webapi-v4];
  • o cliente HTML está na URL [http://localhost:8080/rdvmedecins-webapi-v4/app];

O cliente HTML e o serviço web estão, portanto, no mesmo servidor [http://localhost:8080]. Não há conflitos CORS, pois estes só ocorrem quando o cliente e o servidor não estão no mesmo domínio. Devemos poder verificar isto. Voltemos ao STS:

  

A geração ou não de cabeçalhos CORS é controlada por um valor booleano definido na classe [ApplicationModel]:


    // données de configuration
    private boolean CORSneeded = true;

Definimos o booleano acima como false, reiniciamos o serviço web e solicitamos novamente a URL [http://localhost:8080/rdvmedecins-webapi-v4/app/index.html]. Podemos ver que a aplicação funciona.

4.4. Implementação do cliente Angular num tablet Android

A ferramenta [Phonegap] [http://phonegap.com/] permite gerar um executável móvel (Android, iOS, Windows 8, etc.) a partir de uma aplicação HTML/JS/CSS. Existem diferentes formas de o fazer. Vamos utilizar a mais simples: uma ferramenta online disponível no site da Phonegap [http://build.phonegap.com/apps].

  • Antes de [1], poderá ser necessário criar uma conta;
  • Em [1], comece;
  • Em [2], escolha um plano gratuito que permita apenas uma aplicação Phonegap;
  • Em [3], descarregue a aplicação compactada [4] (a pasta [app] criada na secção 4.2 está compactada);
  • Em [5], dê um nome à aplicação;
  • em [6], compile-o. Isto pode demorar 1 minuto. Aguarde até que os ícones das várias plataformas móveis indiquem que a compilação está concluída;
  • Apenas os binários para Android [7] e Windows [8] foram gerados;
  • clique em [7] para descarregar o ficheiro binário para Android;
  • em [9], o binário [apk] descarregado;

Inicie um emulador [GenyMotion] para um tablet Android (ver secção 6.4):

 

Acima, iniciamos um emulador de tablet com a API 16 do Android. Assim que o emulador for iniciado,

  • desbloqueie-o arrastando o cadeado (se houver) para o lado e, em seguida, soltando-o;
  • Usando o rato, arraste o ficheiro [PGBuildApp-debug.apk] que descarregou e solte-o no emulador. Este será então instalado e executado;

Tem de alterar o URL para [1]. Para tal, numa janela do prompt de comando, digite o comando [ipconfig] (linha 1 abaixo), que irá apresentar os vários endereços IP do seu computador:


C:\Users\Serge Tahé>ipconfig
 
Configuration IP de Windows
 
 
Carte réseau sans fil Connexion au réseau local* 15 :
 
   Statut du média. . . . . . . . . . . . : Média déconnecté
   Suffixe DNS propre à la connexion. . . :
 
Carte Ethernet Connexion au réseau local :
 
   Suffixe DNS propre à la connexion. . . : ad.univ-angers.fr
   Adresse IPv6 de liaison locale. . . . .: fe80::698b:455a:925:6b13%4
   Adresse IPv4. . . . . . . . . . . . . .: 172.19.81.34
   Masque de sous-réseau. . . . . . . . . : 255.255.0.0
   Passerelle par défaut. . . . . . . . . : 172.19.0.254
 
Carte réseau sans fil Wi-Fi :
 
   Statut du média. . . . . . . . . . . . : Média déconnecté
   Suffixe DNS propre à la connexion. . . :
 
...

Anote o endereço IP do Wi-Fi (linhas 6–9) ou o endereço IP da rede local (linhas 11–17). Em seguida, utilize este endereço IP no URL do servidor web:

 

Depois de fazer isso, conecte-se ao serviço web:

Teste a aplicação no emulador. Deverá funcionar. No lado do servidor, pode ou não permitir cabeçalhos CORS na classe [ApplicationModel]:


    // données de configuration
    private boolean CORSneeded = false;

Isto é irrelevante para a aplicação Android. Ela não é executada num navegador. A exigência do cabeçalho CORS provém do navegador, não do servidor.

4.5. Implementação do cliente Angular num emulador de smartphone Android

Repetimos o passo anterior utilizando um emulador de smartphone. Queremos verificar como o nosso cliente se comporta em ecrãs pequenos:

  • em [1], iniciamos um emulador de smartphone;
  • em [2] e [3], a barra de navegação foi recolhida num menu;
  • em [4], fazemos o login;
  • em [5], a lista e o calendário estão dispostos um abaixo do outro, em vez de lado a lado;
  • em [6], solicitamos o calendário;
  • em [7], como o ecrã é demasiado pequeno, parte dos intervalos de tempo fica oculta. A biblioteca [footable] tratou disso;
  • em [8], a mesma vista de antes, mas desta vez com um compromisso.

No geral, a nossa aplicação adapta-se bastante bem ao smartphone. Poderia certamente ser melhor, mas continua a ser utilizável.