Skip to content

4. Ejecución de la aplicación

Ahora queremos ejecutar la aplicación fuera del IDE de STS (para el servidor) y de WebStorm (para el cliente).

4.1. Implementación del servicio web en un servidor Tomcat

En la sección 2.11.9 vimos cómo crear un archivo WAR para Tomcat. Repetimos el proceso aquí. En primer lugar, para conservar la estructura existente, duplicamos el proyecto de Eclipse [rdvmedecins-webapi-v3] en [rdvmedecins-webapi-v4].

  

El archivo [pom.xml] se modifica de la siguiente manera:


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

Hay que realizar cambios en dos lugares:

  • línea 5: debes especificar que vas a generar un archivo WAR (Web ARchive);
  • líneas 23-27: debe añadir una dependencia del artefacto [spring-boot-starter-tomcat]. Este artefacto incluye todas las clases de Tomcat en las dependencias del proyecto;
  • línea 26: este artefacto está [provided], lo que significa que los archivos correspondientes no se incluirán en el WAR generado. En su lugar, estos archivos se ubicarán en el servidor Tomcat donde se ejecutará la aplicación;

También debe configurar la aplicación web. A falta de un archivo [web.xml], esto se hace utilizando una clase que extienda [SpringBootServletInitializer]:

  

La clase [ApplicationInitializer] es la siguiente:


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);
    }
 
}
  • línea 6: la clase [ApplicationInitializer] extiende la clase [SpringBootServletInitializer];
  • línea 8: se sobrescribe el método [configure] (línea 7);
  • línea 9: se proporciona la clase [AppConfig] para configurar el proyecto;

Una vez hecho esto, es posible que tengas que actualizar el proyecto Maven (yo tuve que hacerlo): [haz clic con el botón derecho del ratón en el proyecto / Maven / Actualizar proyecto] o [Alt-F5].

Para ejecutar el proyecto, proceda de la siguiente manera:

  • en [1], ejecute el proyecto en uno de los servidores registrados en el IDE de Eclipse;
  • En [2], seleccione [tc Server Developer], que es la opción predeterminada. Se trata de una variante de Tomcat;

Obtendrás el siguiente resultado:

 

Esto es normal. Recuerda que el servicio web no tiene la URL [/] en sus métodos. Cuando intentas acceder a la URL [/getAllMedecins], obtienes la siguiente respuesta:

 

Esto es normal. El servicio web está protegido.

Ahora ejecutemos el cliente [rdvmedecins-angular-v2] en WebStorm:

En [1], introduce la URL del nuevo servicio web [http://localhost:8080/rdvmedecins-webapi-v4]. Obtenemos el siguiente resultado:

Image

Para ejecutar la aplicación fuera del IDE de STS, existen varias soluciones. Aquí tienes una.

Descargue una versión de Tomcat [http://tomcat.apache.org/download-80.cgi] (julio de 2014):

Seleccione una versión comprimida en [1] y descomprímala en [2]. Vuelva a STS:

  • En la pestaña [Servidores], haz clic con el botón derecho del ratón en la aplicación [rdvmedecins-webapi-v4] y selecciona la opción [Examinar ubicación de implementación];
  • en [4]: copie la carpeta [rdvmedecins-webapi-v4];
  • en [5], pegue la carpeta [rdvmedecins-webapi-v4] en la carpeta [webapps] de Tomcat;
  • En [6], ejecute el archivo de comando [startup.bat] (el servidor Tomcat integrado en STS debe estar detenido). Se abrirá una ventana de DOS para mostrar los registros de Tomcat. Estos deberían indicar que la aplicación [rdvmedecins-webapi-v4] se ha iniciado.

Para verificarlo, ejecute de nuevo el cliente Angular [rdvmedecins-angular-v2] en WebStorm:

En [1], introduzca la URL del nuevo servicio web [http://localhost:8080/rdvmedecins-webapi-v4]. Verá el siguiente resultado:

Image

4.2. Implementación del cliente Angular en el servidor Tomcat

Ahora que el servicio web se ha implementado en Tomcat, vamos a implementar también el cliente Angular en un servidor. Este podría ser perfectamente el servidor que ya aloja el servicio web. Seguiremos este enfoque.

En primer lugar, duplicamos el cliente [rdvmedecins-angular-v2] en [rdvmedecins-angular-v3] y realizamos los siguientes cambios:

  • en [1], todo se ha trasladado a una carpeta llamada [ app];
  • en [1], hemos eliminado la carpeta [bower-components], que contenía las distintas bibliotecas CSS y JS necesarias para el proyecto. Todos estos elementos se han copiado a la carpeta [lib] [2];
  • en [1], el archivo [app.html] se ha renombrado como [index.html];

El archivo [index.html] se modificó para tener en cuenta los cambios en las rutas de los 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>

Además, se ha modificado el controlador [loginCtrl] para que apunte al servidor correcto, de modo que el usuario no tenga que escribir la URL:


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

Ahora que ya está hecho, ejecutemos el archivo [index.html]:

A continuación, iniciemos sesión en el servicio web. Debería funcionar. Una vez comprobado, detengamos el servidor Tomcat. Reutilizaremos el servidor integrado de STS.

En STS, copie todo el contenido de la carpeta [rdvmedecins-angular-v3/app] en la carpeta [webapp] del proyecto [rdvmedecins-webapi-v4] (pestaña Navegador) [1]:

Una vez hecho esto, inicie [2] el servidor VMware de STS y, a continuación, solicite la URL [http://localhost:8080/rdvmedecins-webapi-v4/app/index.html]:

Nos encontramos con un problema de permisos en [3]. Esto no es de extrañar, ya que hemos protegido el servicio web. Tenemos que especificar que el acceso al archivo [/app/index.html] no tiene restricciones. Volvamos a Eclipse:

  

Recuerda que los permisos de acceso se definieron en la clase [SecurityConfig]. Modifiquémosla de la siguiente manera:


    @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");
}
  • Líneas 11–12: Concedemos a todo el mundo permiso para leer la carpeta [app] y su contenido. Para ello, seguimos el ejemplo de las líneas anteriores.

Ahora, reinicie el servidor Tomcat de STS y vuelva a solicitar la URL [http://localhost:8080/rdvmedecins-webapi-v4/app/index.html]:

Image

Esta vez, funciona.

4.3. Encabezados CORS

Quizás recuerdes que nos costó bastante manejar los encabezados CORS. En el ejemplo anterior:

  • el servicio web se encuentra en la URL [http://localhost:8080/rdvmedecins-webapi-v4];
  • el cliente HTML se encuentra en la URL [http://localhost:8080/rdvmedecins-webapi-v4/app];

Por lo tanto, el cliente HTML y el servicio web se encuentran en el mismo servidor [http://localhost:8080]. No hay conflictos CORS, ya que estos solo se producen cuando el cliente y el servidor no están en el mismo dominio. Deberíamos poder verificarlo. Volvamos a STS:

  

La generación de encabezados CORS se controla mediante un valor booleano definido en la clase [ApplicationModel]:


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

Establecemos el valor booleano anterior en false, reiniciamos el servicio web y volvemos a solicitar la URL [http://localhost:8080/rdvmedecins-webapi-v4/app/index.html]. Podemos ver que la aplicación funciona.

4.4. Implementación del cliente Angular en una tableta Android

La herramienta [Phonegap] [http://phonegap.com/] permite generar un ejecutable móvil (Android, iOS, Windows 8, etc.) a partir de una aplicación HTML/JS/CSS. Hay diferentes formas de lograrlo. Utilizaremos la más sencilla: una herramienta en línea disponible en el sitio web de Phonegap [http://build.phonegap.com/apps].

  • Antes de [1], es posible que tengas que crear una cuenta;
  • En [1], empieza;
  • En [2], elige un plan gratuito que permita solo una aplicación Phonegap;
  • En [3], descargue la aplicación comprimida [4] (la carpeta [app] creada en la sección 4.2 está comprimida);
  • En [5], asigne un nombre a la aplicación;
  • en [6], compílela. Esto puede tardar 1 minuto. Espere hasta que los iconos de las distintas plataformas móviles indiquen que la compilación ha finalizado;
  • Solo se han generado los binarios para Android [7] y Windows [8];
  • haz clic en [7] para descargar el binario de Android;
  • en [9], el binario [apk] descargado;

Inicie un emulador [GenyMotion] para una tableta Android (véase la sección 6.4):

 

Arriba, iniciamos un emulador de tableta con la API 16 de Android. Una vez iniciado el emulador,

  • desbloquéalo arrastrando el candado (si aparece) hacia un lado y soltándolo;
  • Con el ratón, arrastra el archivo [PGBuildApp-debug.apk] que has descargado y suéltalo en el emulador. A continuación, se instalará y se ejecutará;

Debes cambiar la URL a [1]. Para ello, en una ventana del símbolo del sistema, escribe el comando [ipconfig] (línea 1 a continuación), que mostrará las distintas direcciones IP de tu equipo:


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 la dirección IP de la red Wi-Fi (líneas 6-9) o la dirección IP de la red local (líneas 11-17). A continuación, utilice esta dirección IP en la URL del servidor web:

 

Una vez hecho esto, conéctese al servicio web:

Prueba la aplicación en el emulador. Debería funcionar. En el lado del servidor, puedes permitir o no los encabezados CORS en la clase [ApplicationModel]:


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

Esto no es relevante para la aplicación de Android. No se ejecuta en un navegador. El requisito del encabezado CORS proviene del navegador, no del servidor.

4.5. Implementación del cliente Angular en un emulador de smartphone Android

Repetimos el paso anterior utilizando un emulador de smartphone. Queremos comprobar cómo se comporta nuestro cliente en pantallas pequeñas:

  • en [1], iniciamos un emulador de smartphone;
  • en [2] y [3], la barra de navegación se ha reducido a un menú;
  • en [4], iniciamos sesión;
  • en [5], la lista y el calendario se muestran uno debajo del otro en lugar de uno al lado del otro;
  • en [6], solicitamos el calendario;
  • en [7], como la pantalla es demasiado pequeña, parte de los intervalos de tiempo queda oculta. La biblioteca [footable] se encargó de esto;
  • en [8], la misma vista que antes, pero esta vez con una cita.

En general, nuestra aplicación se adapta bastante bien al smartphone. Sin duda podría ser mejor, pero sigue siendo usable.