Skip to content

4. Operación de la aplicación

Ahora queremos poner en funcionamiento la aplicación fuera de IDE, STS (para el servidor) y Webstorm (para el cliente).

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

En el apartado 2.11.9 vimos cómo crear un archivo WAR para Tomcat. Repetimos la operación aquí. En primer lugar, para conservar lo 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>

Las modificaciones deben realizarse en dos lugares:

  • línea 5: se debe indicar que se va a generar un archivo WAR (Web ARchive);
  • líneas 23-27: hay que agregar una dependencia del artefacto [spring-boot-starter-tomcat]. Este artefacto incorpora todas las clases de Tomcat a las dependencias del proyecto;
  • línea 26: este artefacto es [provided], es decir, que los archivos correspondientes no se incluirán en el WAR generado. De hecho, estos archivos se encontrarán en el servidor Tomcat en el que se ejecutará la aplicación;

Además, es necesario configurar la aplicación web. A falta del archivo [web.xml], esto se hace con una clase que hereda de [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: el método [configure] se redefine (línea 7);
  • línea 9: se proporciona la clase [AppConfig], que configura el proyecto;

Una vez hecho esto, puede ser necesario actualizar el proyecto Maven (yo tuve que hacerlo): [clic droit sur projet / Maven / Update project] o [Alt-F5].

Para ejecutar el proyecto, se puede proceder de la siguiente manera:

  • en [1], se ejecuta el proyecto en uno de los servidores registrados en el IDE Eclipse;
  • en [2], se selecciona [tc Server Developer], que aparece por defecto. Se trata de una variante de Tomcat;

Se obtiene el siguiente resultado:

 

Esto es normal. Recordemos que el servicio web no cuenta con URL ni [/] entre sus métodos. Al intentar con URL y [/getAllMedecins], se obtiene la siguiente respuesta:

 

Esto es normal. El servicio web está protegido.

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

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

Image

Para ejecutar la aplicación fuera del entorno de IDE STS, existen varias soluciones. Aquí te presentamos una de ellas.

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

Seleccionamos en [1] una versión comprimida y la descomprimimos en [2]. Regresamos a STS:

  • en la pestaña [Servers], hacemos clic con el botón derecho en la aplicación [rdvmedecins-webapi-v4] y seleccionamos la opción [Browse Deployment Location];
  • en [4]: se copia la carpeta [rdvmedecins-webapi-v4];
  • en [5], pegue la carpeta [rdvmedecins-webapi-v4] en la carpeta [webapps] de Tomcat;
  • en [6], se ejecuta el archivo de comando [startup.bat] (el servidor Tomcat integrado en STS debe estar detenido). Se abre una ventana DOS para mostrar los registros de Tomcat. Estos deben indicar que se ha iniciado la aplicación [rdvmedecins-webapi-v4].

Para verificarlo, ejecutamos nuevamente el cliente Angular [rdvmedecins-angular-v2] en WebStorm:

En [1], se introduce el URL del nuevo servicio web [http://localhost:8080/rdvmedecins-webapi-v4]. Se obtiene 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 puede ser perfectamente el mismo servidor que ya aloja el servicio web. Optamos por esta opción.

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

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

El archivo [index.html] se modificó para reflejar los cambios en las rutas de los recursos utilizados:


<!DOCTYPE html>
<html ng-app="rdvmedecins">
<head>
  <title>RdvMedecins</title>
...
  <!-- el CSS -->
  ...
  <link href="lib/bootstrap-theme.min.css" rel="stylesheet"/>
  <link href="lib/bootstrap-select.min.css" rel="stylesheet"/>
</head>
<!-- controlador [appCtrl], plantilla [app] -->
<body ng-controller="appCtrl">
<div class="container">
  ...
</div>
<!-- Núcleo de Bootstrap 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>
<!-- AngularJS -->
<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>
<!-- módulos -->
...
<!-- servicios -->
...
<!-- directivas -->
...
<!-- controladores -->
....
</body>
</html>

Además, se ha modificado el controlador [loginCtrl] para que apunte al servidor correcto y así evitar que el usuario tenga que escribir su URL:


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

Una vez hecho esto, ejecutemos el archivo [index.html]:

Luego, conectémonos al servicio web. Debería funcionar. Una vez verificado esto, detengamos el servidor Tomcat. Vamos a reutilizar el servidor integrado de STS.

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

Una vez hecho esto, iniciemos [2], el servidor VMware de STS, y luego solicitemos el URL [http://localhost:8080/rdvmedecins-webapi-v4/app/index.html]:

Tenemos un problema de permisos en [3]. No es de extrañar, ya que hemos protegido el servicio web. Debemos indicar que el acceso al archivo [/app/index.html] es libre. Regresemos a Eclipse:

  

Recordemos que los permisos de acceso se definieron en la clase [SecurityConfig]. Modifiquemos esta clase de la siguiente manera:


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // CSRF
        http.csrf().disable();
        // la contraseña se transmite mediante el encabezado Authorization: Basic xxxx
        http.httpBasic();
        // el método HTTP OPTIONS debe estar autorizado para todos
        http.authorizeRequests() //
                .antMatchers(HttpMethod.OPTIONS, "/", "/**").permitAll();
        // la carpeta [app] es accesible para todos
        http.authorizeRequests() //
                .antMatchers(HttpMethod.GET, "/app", "/app/**").permitAll();
        // solo el rol ADMIN puede utilizar la aplicación
        http.authorizeRequests() //
                .antMatchers("/", "/**") // todos los URL
                .hasRole("ADMIN");
}
  • líneas 11-12: autorizamos a todos a leer la carpeta [app] y su contenido. Para ello, nos basamos en las líneas anteriores.

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

Image

Esta vez sí funcionó.

4.3. Los encabezados CORS

Quizás recuerden que nos costó mucho trabajo manejar los encabezados CORS. En el ejemplo anterior:

  • el servicio web está en URL [http://localhost:8080/rdvmedecins-webapi-v4];
  • el cliente HTML está en 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]. Así pues, 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. Volvemos a STS:

  

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


    // datos de configuración
    private boolean CORSneeded = true;

Establecemos el valor booleano anterior en false, reiniciamos el servicio web y volvemos a solicitar el URL [http://localhost:8080/rdvmedecins-webapi-v4/app/index.html]. Observamos 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 para dispositivos móviles (Android, IoS, Windows 8, ...) a partir de una aplicación HTML / JS / CSS. Hay diferentes formas de lograrlo. Nosotros utilizamos la más sencilla: una herramienta disponible en línea en el sitio web de Phonegap [http://build.phonegap.com/apps].

  • Antes de [1], es posible que tengas que crear una cuenta;
  • en [1], comenzamos;
  • en [2], elegimos un plan gratuito que solo permite una aplicación de Phonegap;
  • en [3], descargamos la aplicación comprimida [4] (la carpeta [app] creada en el párrafo 4.2 está comprimida);
  • en [5], se le da un nombre a la aplicación;
  • en [6], se compila. Esta operación puede tardar 1 minuto. Espere hasta que los íconos de las distintas plataformas móviles indiquen que la compilación ha finalizado;
  • solo se han generado los binarios de Android ([7]) y de Windows ([8]);
  • haga clic en [7] para descargar el binario de Android;
  • en [9], el binario [apk] descargado;

Inicie un emulador [GenyMotion] para una tableta Android (consulte el párrafo 6.4):

 

En la imagen de arriba, se inicia un emulador de tableta con el API 16 de Android. Una vez iniciado el emulador,

  • desbloquéalo deslizando el pestillo (si lo hay) hacia un lado y soltándolo;
  • con el ratón, arrastre el archivo [PGBuildApp-debug.apk] que descargó y suéltelo en el emulador. Se instalará y ejecutará de inmediato;

Debes cambiar URL por [1]. Para ello, en una ventana de comandos, escribe el comando [ipconfig] (línea 1 a continuación), que mostrará las diferentes 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. . . :

...

Anota ya sea la dirección IP de Wi-Fi (líneas 6-9) o la dirección IP de la red local (líneas 11-17). Luego, utilice esta dirección IP en el URL del servidor web:

 

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

Prueba la aplicación en el emulador. Debería funcionar. Del lado del servidor, se pueden autorizar o no los encabezados CORS en la clase [ApplicationModel]:


    // datos de configuración
    private boolean CORSneeded = false;

Esto no tiene importancia para la aplicación de Android. Esta no se ejecuta en un navegador. Sin embargo, el requisito de los encabezados CORS proviene del navegador y no del servidor.

4.5. Implementación del cliente Angular en el emulador de un teléfono inteligente Android

Repetimos la operación anterior con un emulador de teléfono inteligente. Queremos verificar cómo se comporta nuestro cliente en pantallas pequeñas:

  • en [1], iniciamos un emulador de teléfono inteligente;
  • en [2] y [3], la barra de navegación se ha plegado en un menú;
  • en [4], se inicia sesión;
  • en [5], la lista y el calendario aparecen uno debajo del otro en lugar de estar uno al lado del otro;
  • en [6], se solicita la agenda;
  • en [7], como la pantalla es demasiado pequeña, parte de los horarios queda oculta. Fue la biblioteca [footable] la que realizó esta tarea;
  • en [8], la misma vista que antes, pero esta vez con una cita.

Al final, nuestra aplicación se adapta bastante bien al celular. Seguramente podría ser mejor, pero sigue siendo usable.