El Método 2 hará uso de la clase helper WrapperStartStopApp.
Este método proporciona una forma de integrar aplicaciones como Tomcat, que se inician utilizando una clase y detenidas usando una otra clase.
Normalmente este tipo de aplicación abrirá un socket de servidor (server socket) al iniciar, cuyo trabajo es esperar una conexión que desencadene un apagado.
El apagado o la ejecución de la clase stop desencadena el apagado mediante la conexión de la aplicación.
El Wrapper trabaja con este tipo de aplicación iniciando la aplicación de la misma manera que en el Método 1, utilizando la clase start, para luego llamar la clase "stop" cuando sea el momento de que la aplicación se apague.
Cuando la integración se realiza con el método 2 (clase helper WrapperStartStopApp), la clase helper WrapperStartStopApp sustituye a la clase principal de la aplicación.
Esto le da oportunidad a la clase WrapperStartStopApp de inmediatamente iniciar el WrapperManager y registrar la máquina JVM con el Wrapper.
La clase WrapperStartStopApp entonces administra toda la interacción con el Wrapper, así como el ciclo de vida de una aplicación.
Cuando el Wrapper envía un mensaje de "inicio" a la máquina JVM a través del WrapperManager, el método principal de la aplicación de la clase "start" es invocado.
De la misma manera, cuando el Wrapper envía un mensaje para "detener", el método principal de la aplicación de la clase "stop" es invocado.
Al iniciar la clase WrapperStartStopApp, es necesario notificar los nombres de las dos clases
"start" y "stop" así como cualquier parámetro que se necesite proveer al método principal de cada clase.
Esto resulta en una lista de parámetros la cual es un poco más complicada
que la clase del Método 1 (WrapperSimpleApp).
El primer parámetro pasado a la clase WrapperStartStopApp será el nombre completo de la clase "start."
Esto es seguido por un conteo de los parámetros de la clase "start" del método principal que vendrá posteriormente.
Después de los parámetros de la clase "start", viene el nombre completo de la clase "stop".
A esto le sigue una bandera con valores TRUE/FALSE que se usa para notificar a la clase WrapperStartStopApp si debe o no esperar hasta que
todos los subprocesos que no son demonios se completen antes de realmente terminar.
Esta bandera indicadora es seguida por el conteo de los parámetros de la clase "stop" así como otros parámetros.
No se preocupe si esto es confuso en estos momentos. Un ejemplo más detallado se proporciona a continuación.
Instrucciones Detalladas
Esta sección le guiará a través de una explicación detallada de cómo configurar Tomcat para funcionar con el Wrapper.
La mayoría de las otras aplicaciones se puede integrar siguiendo los mismos pasos.
Instalar Tomcat
Este tutorial inicia con una instalación limpia de Tomcat.
En esta ocasión usamos Tomcat 9.0.0.M13, por lo que los pasos exactos pueden ser ligeramente diferentes dependiendo de la versión que se tenga instalada.
Tomcat fue instalado en el directorio /usr/lib, lo que nos da como resultado un directorio (Tomcat Home directory) /usr/lib/apache-tomcat-9.0.0.M13.
Instalar Archivos del Wrapper
Se requieren cuatro directorios para configurar y utilizar e instalar exitosamente el Wrapper.
NOTA
Por favor, asegúrese de que está utilizando la versión adecuada del Wrapper, que los archivos libwrapper.so fueron construidos para la plataforma que está ejecutando.
Suena obvio, pero por ejemplo la versión del Wrapper para Linux no funciona en Solaris.
Directorio bin
El Wrapper tiene incluido un shell script (sh) que se puede utilizar para iniciar y detener de forma fiable cualquier aplicación Java controlada por el Java Service Wrapper.
El primer paso es copiar los siguientes archivos en el directorio bin de Tomcat (en versiones anteriores del Wrapper, este archivo se llamaba 'sh.script.in'):
Cambie el nombre del archivo script para reflejar el nombre de la aplicación.
{TOMCAT_HOME}/bin/tomcat
Ahora abra el script en un editor.
Tenemos que definir los nombres largos y cortos para asegurarnos de que el el script es usado para lanzar la aplicación Tomcat.
Usted verá dos variables inmediatamente después del encabezado del script, APP_NAME y APP_LONG_NAME.
Algunos valores para estas variables que pueden usarse son presentados a continuación.
Valores sugeridos para estas variables son presentados a continuación.
El script no requiere ninguna modificación adicional.
Sin embargo, este asumirá que el archivo wrapper.conf será localizado dentro
del directorio conf (un nivel arriba, ../conf/wrapper.conf).
Si desea colocar el archivo wrapper.conf en otro lugar, la variable WRAPPER_CONF
en el script también necesitará ser modificado apropiadamente.
NOTA
¡Importante! Antes de continuar, asegúrese de que todos los archivos que se han copiado en el directorio bin tienen sus bits ejecutables configurados.
Directorio lib
Copie los dos archivos en el directorio lib de Tomcat:
El archivo libwrapper.so es un archivo de la librería nativa
que es requerido por la porción del Wrapper que se ejecuta dentro de la máquina JVM.
El archivo wrapper.jar contiene todas las clases del Wrapper.
NOTA
Note que la librería nativa hace uso de convenciones de nombres un poco diferentes en algunas plataformas.
Posibles nombres pueden incluir:
libwrapper.a,
libwrapper.sl,
libwrapper.so,
y libwrapper.jnilib.
En todo caso, el archivo debe ser copiado sin cambiar la extensión.
Directorio conf
El Wrapper requiere de un archivo de configuraciones "wrapper.conf" para cada aplicación.
La ubicación estándar para este archivo está en un directorio conf que se encuentra en el directorio principal (home) de cada aplicación.
Por favor copie la siguiente plantilla del archivo wrapper.conf.in en el directorio conf de Tomcat.
{WRAPPER_HOME}/src/conf/wrapper.conf.in
Renombre el archivo como a continuación se muestra.
Asegúrese de remover la extensión .in para que el nombre del archivo sea wrapper.conf.
Usted debe tener ahora:
{TOMCAT_HOME}/conf/wrapper.conf
Es posible cambiar la ubicación del archivo de configuración wrapper.conf si lo desea.
Usted tendrá que modificar los scripts copiados en el directorio bin para reflejar la nueva ubicación.
Directorio logs
El archivo de configuración establecido por defecto wrapper.conf
colocará un archivo wrapper.log en un directorio logs que se encuentra en el directorio principal (home) de la aplicación.
Tomcat ya cuenta con este directorio, así que estamos listos.
{TOMCAT_HOME}/logs
Puede cambiar la ubicación del archivo wrapper.log si lo desea.
Tendrá que editar el wrapper.conf
y modificar la propiedad wrapper.logfile para reflejar la nueva ubicación.
Localizar la Línea de Comandos de la Aplicación Java
Antes de que el Wrapper pueda ser configurado para lanzar una aplicación, usted tendrá que saber los comandos completos de Java que normalmente se utilizan.
La mayoría de las aplicaciones hace uso de un script para construir la línea actual de comandos.
Estos archivos son difíciles de manejar, pero la capacidad de funciones para evitar tener que trabajar con ellos es uno de los beneficios de usar el Wrapper.
Tomcat es iniciado por defecto usando un script llamado startup.sh y se termina al usar un archivo
llamado shutdown.sh.
Se lanza al cambiar el directorio actual al directorio bin y después se ejecuta desde ahí.
Si abre startup.sh en un editor, notará que Java en realidad no fue iniciado desde dicho script, pero otro script, catalina.sh es invocado.
Los scripts de Tomcat son muy avanzados y permiten que los usuarios establezcan muchas configuraciones desde la línea de comandos.
La línea de comandos que se capturará y usará con el Wrapper será literalmente una imagen de dicha configuración.
En este ejemplo se supone que los parámetros no son pasados a los scripts de inicio y término cuando estes se ejecutan.
Si abre catalina.sh en un editor y se desplaza a la parte final del archivo, verá una sección que responde al comando "start".
Hay dos opciones para el lanzamiento de la máquina JVM, con o sin un administrador de seguridad (Security Manager).
Para simplificar las cosas, vamos a utilizar la versión sin un administrador de seguridad.
Las líneas en las que estamos interesados en revisar son algo parecido a lo que a continuación se presenta:
La mayor parte del script tiene la tarea de recoger información específica del sistema y almacenar esa información en las variables de entorno.
La línea anterior expande toda la información recogida en el último comando de Java que ejecuta la aplicación.
Si busca detenidamente en la fuente del archivo de órdenes, esperamos que pueda apreciar la complejidad y el deseo de tener que evitar por completo escribir este tipo de archivos scripts usted mismo.
Para configurar el Wrapper, todo lo que se necesita realmente es la línea de comandos final expandida.
En lugar de leer todo el script y tratar de entenderlo, vamos a utilizar un sencillo truco para mostrar la línea de comandos final en la consola.
Edite el script catalina.sh como sigue:
Si ahora vuelve a ejecutar dicho archivo de órdenes catalina.sh stop, verá en la consola algo como lo siguiente (la salida de datos estará toda en una línea):
Aparte de exec al comienzo de la línea de apagado y la salida de datos redirigida de la consola de la línea de inicio, los dos comandos son casi idénticos.
La única diferencia es el parámetro que se pasa a la clase principal al final.
La parte exec del comando para el apagado y la redirección para capturar la salida de datos de la consola no se requiere cuando se utiliza el Wrapperm entonces ignoraremos esas partes de los comandos por el resto de este ejemplo.
El Wrapper también se encargará de las "comillas" de los elementos de la línea de comandos de Java que son creadas.
Así que no es necesario que se transfieran en el archivo de configuración wrapper.conf como se muestra abajo.
Modificación del Archivo "wrapper.conf"
Con el fin de poder utilizar la línea de comandos Java con el Wrapper, tenemos que dividir los componentes de la línea de comando en un archivo de configuración.
Abra el archivo wrapper.conf en un editor para hacer cambios como se muestra a continuación.
NOTA
Donde se mencionan las propiedades, se proporcionan vínculos sobre sus descripciones.
Tome un momento para revisar las descripciones de las propiedades que se modifican.
En muchos casos hay más detalles sobre su uso y que a veces no son mencionados aquí.
Java Ejecutable
Primero se necesita extraer el Java ejecutable y asignar la ubicación de la ruta a la propiedad wrapper.java.command:
wrapper.java.command=/opt/jdk1.8.0_45/bin/java
Argumentos Java
La mayoría de las aplicaciones proporciona una serie de parámetros al Java ejecutable cuando se ejecuta.
El Java Service Wrapper ofrece propiedades especiales para configurar la memoria, así como clases y rutas de la librería.
Estas se explican a continuación; sin embargo otras opciones se configuran mediante la serie de propiedades
wrapper.java.additional.<n>.
La línea de comandos de Tomcat cuenta con varias propiedades:
wrapper.java.additional.1=-Dcatalina.base=/usr/lib/apache-tomcat-9.0.0.M13
wrapper.java.additional.2=-Dcatalina.home=/usr/lib/apache-tomcat-9.0.0.M13
wrapper.java.additional.3=-Djava.io.tmpdir=/usr/lib/apache-tomcat-9.0.0.M13/temp
wrapper.java.additional.4=-Djdk.tls.ephemeralDHKeySize=2048
wrapper.java.additional.5=-Djava.protocol.handler.pkgs=org.apache.catalina.webresources
# Following properties are optional:
wrapper.java.additional.6=-Djava.util.logging.config.file=/usr/lib/apache-tomcat-9.0.0.M13/conf/logging.properties
wrapper.java.additional.7=-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
Archivo jar del Wrapper
El Wrapper requiere que su propiedad wrapper.jar sea especificada:
La propiedad wrapper.jarfile se introdució en la versión 3.5.55 del Wrapper.
Si usa una versión más antigua del Wrapper, es necesario incluir wrapper.jar en la ruta de la clase (classpath):
Después, los índices de los siguientes elementos de classpath deben ajustarse para no repetir la propiedad wrapper.java.classpath.1.
Classpath
Ahora tenemos el classpath, que es configurado usando las propiedades wrapper.java.classpath.<n>.
El Wrapper requiere que el classpath se divida en sus elementos individualmente.
El componente final del comando utilizado para el lanzamiento de Tomcat es la clase principal org.apache.catalina.startup.Bootstrap.
La clase principal ejecutada por Java al iniciar es especificada con la propiedad wrapper.java.mainclass. Como mencionado anteriormente, por hacer uso de la clase WrapperStartStopApp para iniciar y detener Tomcat,
especificarémos el nombre completo de la clase como la clase principal.
A continuación las clases principales de Tomcat son especificadas como parámetros de una aplicación.
Los parámetros de las aplicaciones son establecidos usando las propiedades
wrapper.app.parameter.<n>.
Dichos parámetros aparecen en la línea de comandos Java después de la clase principal.
Cuando se inicia usando la clase auxiliar WrapperStartStopApp, mucha información es requerida sobre las clases
"start" y "stop".
Esta información incluye el nombre completo de cada clase, la lista de parámetros que se pasan a sus métodos principales y una bandera que indica a la clase auxiliar si debe esperar o no a que todos los threads que no sean demonios terminen antes de terminar la máquina JVM.
Le explicaremos como dicha información es codificada.
Empezaremos por presentarle los valores de las propiedades de la aplicación Tomcat.
Varios comentarios están agregados en la parte de arriba, específicamente lo que normalmente encuentra en el wrapper.conf.
Esto hará fácil de entender lo que cada propiedad significa.
Le sugerimos agregar estos comentarios a su archivo de configuraciones wrapper.conf también.
# The first application parameter is the name of the class whose main
# method is to be called when the application is launched. The class
# name is followed by the number of parameters to be passed to its main
# method. Then comes the actual parameters.
wrapper.app.parameter.1=org.apache.catalina.startup.Bootstrap
wrapper.app.parameter.2=1
wrapper.app.parameter.3=start
# The start parameters are followed by the name of the class whose main
# method is to be called to stop the application. The stop class name
# is followed by a flag that controls whether or not the Wrapper should
# wait for all non daemon threads to complete before exiting the JVM.
# The flag is followed by the number of parameters to be passed to the
# stop class's main method. Finally comes the actual parameters.
wrapper.app.parameter.4=org.apache.catalina.startup.Bootstrap
wrapper.app.parameter.5=TRUE
wrapper.app.parameter.6=1
wrapper.app.parameter.7=stop
Los nombres de las clases start y stop deben ser bastante claros.
El primer recuento de parámetros es requerido para localizar la clase stop en la lista de parámetros.
El segundo conteo está ahí solo para mantener la consistencia.
La bandera que asiste al parámetro #5 en la parte de arriba se usa para controlar el comportamiento de la clase helper WrapperStartStopApp
cuando dicho parámetro apaga la máquina JVM.
Cuando el Wrapper envia una solicitud de apagado a la máquina JVM, la clase WrapperStartStopApp responde invocando el método principal de la clase "stop"
con los parámetros configurados.
La bandera controla lo que pasa cuando el método principal regresa.
Si la bandera es FALSE, la propiedad System.exit(0) es invocada inmediatamente.
Cuando es TRUE, WrapperStartStopApp espera hasta que los threads que no son demonios terminen su función antes de ejecutar System.exit(0).
El proceso de dicho comportamiento produce una manera limpia de apagar Tomcat.
Si se especifica TRUE pero uno o más threads demonio no terminan, el Wrapper apagará la máquina JVM a la fuerza después de que Shutdown Timeout expire.
El tiempo de espera predeterminado es de 30 segundos.
Los subprocesos que no son daemon se cuentan por iteración sobre todos los subprocesos en el sistema y
contando los métodos de isDaemon que regresan como resultado FALSE.
Desafortunadamente, este conteo nunca llegará a "0" (cero) en casi todas las máquinas JVM, debido a la existencia de subprocesos de sistema.
En la mayoría de las máquinas JVMS Oracle Hotspot, habrá un subproceso de sistema que no es demonio.
Para que el apagado funcione correctamente, el conteo de este subproceso de sistema también debe ser correcto.
Se puede establecer definiendo la propiedad de sistema:
org.tanukisoftware.wrapper.WrapperStartStopApp.systemThreadCount.
El valor predeterminado es "1 thread".
NOTA
Si el método principal de la clase stop llama a System.exit
desde su subproceso principal, dicho proceso automáticamente se convierte en un bloqueo "deadlock" como resultado de dicha llamada.
El Wrapper evita este bloqueo (deadlock) al detectarlo y proseguir con un apagado después de 5 segundos.
Sin embargo, esto puede hacer que la aplicación no termine de una manera limpia, lo que debe ser evitado siempre que posible.
Este caso puede ser examinado al habilitar la propiedad wrapper.debug=TRUE.
Después, analize el archivo log file durante el proceso de apagado.
Ruta de la Librería
Una propiedad más debe ser establecida para usar al Wrapper.
El Wrapper hace uso de una librería nativa para controlar las interacciones con el sistema.
Este archivo de libreríalibwrapper.so
necesita ser especificado en la ruta de la librería que se envía a la máquina JVM.
Tomcat no tiene librerías nativas, pero si las tuviera, los directorios donde se ubicarían también necesitarían ser especificados.
La ruta de la librería es configurada en las propiedades wrapper.java.library.path.<n>.
Observe que mientras estas configuraciones funcionarán correctamente en esta máquina en particular, depende altamente de la estructura de directorios y la plataforma.
Es una gran ventaja que los scripts del Wrapper siempre establezcan el directorio actual en la ubicación del script y también al hacer uso de una variable de entorno único, podemos modificar las propiedades anteriores de tal manera que sean completamente independientes de plataforma y máquina.
Sabemos que Tomcat 5.0.28 no funciona correctamente si el directorio bin es incluido en la propiedad del sistema java.endorsed.dirs.
Esto es causado por un cambio en Tomcat; el Wrapper no es un factor para que dicha propiedad no funcione.
Por favor, modifique la configuración anterior como a continuación:
Tomcat puede ejecutarse simplemente al ejecutar el script bin/tomcat console.
Debido a la manera en la que el Wrapper configura su directorio actual, no es necesario ejecutar este script desde el directorio bin.
Como se puede ver si se omite un comando, los scripts incluidos con el Wrapper son scripts de Demonio (Daemon) bastante comúnes.
Se aceptan los comandos:
console,
start,
stop,
restart, y
dump.
Los comandos start,
stop, y
restart son comúnes para casi todos los scripts de Demonio y son usados para controlar el Wrapper y su aplicación cuando es establecido como un proceso Demonio.
El comando status se usa para determinar si el Wrapper ha iniciado o no.
El comando console inicia el Wrapper en el shell actual, haciendo que termine repentinamente la aplicación al pulsar CTRL-C.
El comando final dump envia una señal "kill -3" al Wrapper causando que la máquina JVM ejecute un vertedero de memoria (thread dump) completo.
Felicidades. Su aplicación debe estar ahora en marcha y funcionando.
Si tiene algún problema, consulte la siguiente sección Solución de problemas para recibir ayuda y detectar el problema.
Nivel Avanzado
Preparando el Inicio
Por defecto, la clase WrapperStartStopApp
espera 2 segundos al método principal de la aplicación del usuario para completar.
Después de eso, se asume que la aplicación ha iniciado y mandará un reporte al Wrapper.
Esto se hace porque muchas aplicaciones se escriben con métodos principales que no regresan por todo el tiempo que una aplicación se ejecuta.
En estos casos, no hay una manera eficaz para que la clase WrapperStartStopApp informe cuando y/o si la aplicación a completado su inicio.
Sin embargo, si se sabe que el método principal de la aplicación retornará una vez que se inicia la aplicación, esto sería ideal para que el Wrapper espere antes de continuar.
Propiedad del Sistema waitForStartMain:
Para los métodos principales que regresan de esta manera, la clase WrapperStartStopApp busca la propiedad del sistema
org.tanukisoftware.wrapper.WrapperStartStopApp.waitForStartMain.
Si se establece como "TRUE", WrapperStartStopApp esperará indefinidamente a que el método principal se haya completado.
Esperar indefinidamente es una buena opción si se sabe a ciencia cierta que el método principal regresará a su debido tiempo. Pero por otro lado, si se espera eternamente, el Wrapper no desistirá del proceso de inicio, no importa el tiempo que espere.
Por lo tanto, si hay alguna posibilidad de que este inicio pueda colgarse, entonces configurar la propiedad del sistema org.tanukisoftware.wrapper.WrapperStartStopApp.maxStartMainWait
con un tiempo máximo de espera puede ser una mejor opción.
Por ejemplo, para esperar hasta 5 minutos (300 segundos) para que el método principal complete su inicio, configure la propiedad a 300 de la siguiente manera:
Los métodos principales de muchas aplicaciones están diseñados para no retornar.
En estos casos, debe ser consistente con el tiempo de espera de inicio establecido por defecto de 2 segundos o especificar un tiempo de espera ligeramente más largo, usando la propiedad maxStartMainWait para simular la cantidad de tiempo que su aplicación necesita para iniciar.
ADVERTENCIA
Si se especifica "TRUE" en waitForStartMain para una aplicación cuyo método de inicio start nunca retorna, el Wrapper parecerá al principio estar funcionando correctamente.
Sin embargo, el Wrapper está en verdad en un estado de espera eterno y nunca entrará en un estado de "ejecución".