The Structure and Deployment of Web Applications (SCWCD)

Objetivos:
Section 2: The Structure and Deployment of Web Applications
2.1- Construct the file and directory structure of a Web Application that may contain (a) static content, (b) JSP pages, (c) servlet classes, (d) the deployment descriptor, (e) tag libraries, (d) JAR files, and (e) Java class files; and describe how to protect resource files from HTTP access.
2.2- Describe the purpose and semantics of the deployment descriptor.
2.3- Construct the correct structure of the deployment descriptor.
2.4- Explain the purpose of a WAR file and describe the contents of a WAR file, how one may be constructed.

Ver todos los objetivos de SCWCD 

La estructura de directorios de una aplicación web
La especificación de Servlets de java determina la manera en que una aplicación web debe ser almacenada. Es decir, se define una estructura de directorios para almacenar los recursos y archivos de una aplicación web.
El servidor Tomcat posee un directorio llamado webapps, el cuál contiene todas las aplicaciones web alojadas en el servidor. Cada directorio contenido representa una aplicación, la estructura de directorios de cada aplicación esta estandarizada por la especificación de Servlets:

WEB-INF: Almacena información necesaria para que el contenedor de servlets pueda iniciar la aplicación web. Este directorio no es accesible por el cliente, pero si por la aplicación. Contiene tres elementos:
  • classes (directorio): Almacena los archivos class de servlets y archivos class comunes necesarios para dar soporte a los servlets o JSP’s , si los mismos no están incluidos en un archivo JAR. Los archivos class se encuentran organizados acorde a sus paquetes. En tiempo de ejecución, el contenedor de servlets agrega este directorio al classpath de la aplicación web. 
  • lib (directorio): Almacena todos los archivos JAR utilizados por la aplicación, tanto de terceras partes como propios. En tiempo de ejecución, el contenedor de servlets agrega todos los archivos JAR de este directorio al classpath de la aplicación web. 
  • web.xml: Es el archivo de configuración de la aplicación (o descriptor de despliegue). Todas las aplicaciones web deben tenerlo. Contiene las declaraciones de los servlets y mapeos, propiedades, autorizaciones y restricciones de seguridad.
Cuando se importa una clase, el contenedor primero intenta ubicarla dentro del directorio classes, en caso de no hallarla, se busca la definición de la misma dentro de algún archivo JAR del directorio lib.



El archivo web (WAR)
Los archivos y recursos de una aplicación web pueden ser empaquetados dentro de un archivo JAR, a diferencia que el archivo debe tener la extensión .war en lugar de .jar. La extensión .war viene de las siglas Web ARchive, y significa que el archivo deberá ser tratado de diferente manera que un archivo JAR. El contenedor de servlets puede instalar el archivo WAR de una aplicación web sin una intervención manual.
Dentro del archivo WAR, se crea un directorio llamado META-INF. Dicho directorio contiene el archivo MANIFEST.MF, el cual permite declarar dependencias con librerías y clases. Es decir, brinda un chequeo en tiempo de despliegue (deploy-time) para que el contenedor pueda verificar las librerías y clases que se necesitan para ejecutar la aplicación web correctamente. Esto permite que no sea necesario esperar hasta que un recurso sea solicitado, para verificar que existan todos los componentes de los que depende la aplicación.

La aplicación web por defecto (default web application)
Junto a las aplicaciones web creadas por los usuarios, el contenedor de servlets contiene una aplicación web por defecto. Esta aplicación maneja todas las peticiones que no concuerdan con ninguna aplicación del usuario. En el servidor Tomcat, esta aplicación por defecto se encuentra dentro del directorio webapps/ROOT.
Esta aplicación web por defecto permite ejecutar JSP’s y servlets individuales, como también contenido estático, sin empaquetarlos en una aplicación separada.

El archivo descriptor de despliegue web.xml (deployment descriptor file)
El archivo web.xml, es un típico archivo XML que comienza con la línea: <?xml version="1.0" encoding="ISO-5589-1">
Dicha línea especifica la versión de XML y el juego de caracteres que se utilizará en el archivo. La línea siguiente depende de la versión de especificación Servlet o JSP que se utilice.
Nodos del archivo de configuración:

<!ELEMENT servlet (icon?, servlet-name, display-name?, description?, (servlet-class|jsp-file), init-param*, load-on-startup?, load-on-startup?, security-role-ref*) >

<!ELEMENT servlet-mapping (servlet-name, url-pattern) >

<web-app>: Nodo raíz del archivo.
  • <servlet>: Define un servlet para una aplicación web.
        - <servlet-name>: Define el nombre del servlet. Este elemento es obligatorio, y el nombre del servlet debe ser único en todo el archivo. Desde la aplicación, el nombre del servlet se puede obtener a través del método javax.servlet.ServletConfig.getServletName(). Este nombre también se utiliza para definir el mapeo del servlet a una URL.
        -
    <servlet-class>: Define el nombre de la clase utilizada por el contenedor de servlets para instanciar el servlet. Este elemento es obligatorio. Esta clase, como todas las clases de las que dependa, deben estar disponibles desde el classpath de la aplicación web.
        -
    <init-param>: Este elemento es utilizado para crear parámetros de inicialización del servlet. No hay un límite en la cantidad de parámetros de un servlet, pero cada uno debe contener:
              *
    <param-name>: Contiene el nombre del parámetro de inicialización.
              *
    <param-value>: Contiene el valor del parámetro de inicialización. 
  • <servlet-mapping>: Especifica que URL debe ser manejada por cada servlet. El contenedor de servlets utiliza el mapeo para invocar el servlet apropiado para una URL. Este elemento debe contener:
        - <servlet-name>: Contiene el nombre del servlet.
        - <url-pattern>: Contiene la cadena de caracteres que se va a asociar al servlet.
  • <load-on-startup>: Permite especificar un número, el cual indica si el servlet debe ser cargado en tiempo de despliegue (deploy-time). Si posee un valor negativo, el servlet se cargará e inicializará al momento en que recibe la primera petición. Si posee un número positivo, se indica al contenedor que inicialice automáticamente al servlet, es decir, cuando el servidor arranca. El valor se utiliza para determinar el orden de inicialización de los servlets, aquellos servlets que posean un número menor se inicializarán anteriormente a aquellos que poseen números mayores. Si varios servlets poseen el mismo número en este elemento, el contenedor inicializará a los mismos por el orden en que se encuentran declarados en el archivo web.xml.
Mapeando una URL a un Servlet
El enrutamiento de una petición a un servlet es un proceso de dos pasos:
  1. El contenedor de servlets identifica la aplicación web a la que pertenece la petición.
  2. Luego se localiza el servlet (perteneciente a la aplicación web) apropiado para manejar la petición.
Ambos pasos requieren que el contenedor servlets divida la URL de la petición en tres partes:
  • Context path (path de contexto): El contenedor de servlets intenta concordar la mayor parte posible de la URL con el nombre de una aplicación web disponible. Si no existen concordancia, se asocia la petición con la aplicación web por defecto.
  • Servlet path: Luego el contenedor de servlets intenta concordar la mayor parte del resto de la URL con los mapeos de servlets definidos en el archivo web.xml de la aplicación web. Si no se encuentra ninguna concordancia, se retorna una página de error.
  • Path info: Es el resto de información de la URL, es decir, el resto luego de haber determinado el servlet que manejará la petición. En caso de que la URL posea parámetros, el path info es todo el resto de la misma hasta la aparición del primer carácter ‘?’, el cual indica el comienzo de los parámetros.
La interface javax.servlet.http.HttpServletRequest provee tres métodos para obtener esta información: getContextPath(), getServletPath(), getPathInfo().

Identificación del servlet path
Una vez identificado el path de contexto, el contenedor de servlets sigue un algoritmo para determinar el servlet que manejará la petición. Este algoritmo verifica, en ciertos pasos ordenados, la concordancia de la URI con los mapeos de los servlets. Una vez hallada la concordancia el algoritmo finaliza. Los pasos son:
  • El contenedor intenta coincidir la URI completa. En este caso, el path info es null.
  • Se intenta coincidir la URI recursivamente a través del separador / quitando elementos de atrás para adelante. Si hay una coincidencia, la parte que concuerda es el servlet path y la parte restante es el path info.
  • Si el último nodo de la URI contiene una extensión, el contenedor de servlets intenta encontrar un servlet que maneje todas las peticiones con esa extensión. En este caso, la URI completa es el servlet path, y el path info es null.
  • Si el contenedor sigue sin encontrar una coincidencia, envía la petición al servlet por defecto. Si no existe un servlet por defecto, se devuelve un mensaje de error.
Especificación de páginas por defecto (o welcome files)
A través del archivo web.xml se puede especificar las páginas por defecto de una aplicación web. El contenedor utiliza este archivo para todos los directorios de la aplicación. Es decir, no importa que directorio se solicite, el contenedor revisará la misma lista de welcome files especificada. Se devolverá el primer archivo de la lista que exista en el directorio.
Se deben tener en cuenta los siguientes puntos, al especificar la lista de páginas por defecto:
  • No se utiliza una barra delante del nombre del archivo.
  • Todos los archivos (<welcome-file>) deben estar dentro de un solo elemento <welcome-file-list>, es decir, tienen que estar dentro de la misma lista.
<web-app …>
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>default.jsp</welcome-file>
    </welcome-file-list>
</web-app>
Especificación de páginas de error
A través del web.xml también se pueden especificar las páginas de error por defecto de una aplicación web. Pueden existir diferentes páginas de error dependiendo del tipo de excepción generada, o dependiendo del código de error HTTP. Estas páginas de error se especificación por medio del elemento <page-error>. Puntos a tener en cuenta:
  • Los subelementos <exception-type> y <error-code> no pueden ser utilizados conjuntamente dentro de un mismo elemento <page-error>.
  • Se existen varias páginas de error con diferentes <exception-type>, se intentará concordar la excepción generada con una declaración del mismo tipo, o el supertipo más cercano.
  • El atributo pageError de la directiva page (de las páginas JSP), permite sobrescribir la página de error especificada en el web.xml.
Ejemplos:
<web-app …>
    <error-page>
        <exception-type>java.lang.Throwable</exception-type>
        <location>/errorPageThrowable.jsp</location>
    </error-page>
    <error-page>
        <exception-type>java.lang.Exception</exception-type>
        <location>/errorPageException.jsp</location>
    </error-page>
    <error-page>
        <error-code>404</error-code>
        <location>notFoundError.jsp</location>
    </error-page>
</web-app>
En este ejemplo, si se produce una excepción de tipo RuntimeException, se ejecutará la página: errorPageThrowable.jsp. Pero si se lanza una excepción comprobada se ejecutará la página: errorPageException.jsp.

Definir referencias a EJB (Enterprise JavaBean)
Si bien los componentes EJB no están dentro de los objetivos del examen, se debe saber cómo definir referencias a los mismos a través del web.xml. Existen dos tipos de referencias a EJB’s:

Referencia a un bean local:
<web-app …>
    <ejb-local-ref>
        <ejb-ref-name>ejb/Customer</ejb-ref-name>
        <ejb-ref-type>Entity</ejb-ref-type>
        <local-home>com.example.CustomerHome</local-home>
        <local>com.example.Customer</local>
    </ejb-local-ref>
</web-app>
Referencia a un bean remoto:
<web-app …>
    <ejb-ref>
        <ejb-ref-name>ejb/LocalCustomer</ejb-ref-name>
        <ejb-ref-type>Entity</ejb-ref-type>
        <home>com.example.CustomerHome</home>
        <remote>com.example.Customer</remote>
    </ejb-ref>
</web-app>
Definir enviroment entry (JNDI)
Al igual que la definición de referencias a EJB, para el examen es necesario saber cómo definir estas entradas en el archivo web.xml:
<web-app …>
    <env-entry>
        <env-entry-name>rates/discountRate</env-entry-name>
        <env-entry-type>java.lang.Integer</env-entry-type>
        <env-entry-value>10</env-entry-value>
    </env-entry>
</web-app>
Se debe tener en cuenta que el elemento <env-entity-type> puede contener cualquier tipo que tome un solo String como parámetro en algún constructor, o un simple carácter. El valor debe ser pasado como un String, o un carácter si corresponde al tipo.

Definir tipos MIME
Se pueden configurar mapeos entre una extensión y un tipo MIME en el archivo web.xml:
<web-app …>
    <mime-mapping>
        <extension>mpg</extension> <!-- No se debe incluir el punto “.”  -->
        <mime-type>video/mpeg</mime-type>
    </mime-mapping>
</web-app>

0 comentarios :: The Structure and Deployment of Web Applications (SCWCD)

Publicar un comentario en la entrada