La Méthode 3, tout en offrant la plus grande flexibilité et l'accès à toutes les fonctionnalités du Wrapper,
est également la seule qui nécessite un peu de programmation pour terminer l'intégration.
Cette méthode consiste à créer une classe qui implémente l'interface
WrapperListener.
Une instance de la classe utilisateur est ensuite instanciée et enregistrée auprès du
WrapperManager.
Bien que cette méthode offre des fonctionnalités qui ne sont pas disponibles avec
l'une ou l'autre des deux premières méthodes (
Method1:WrapperSimpleApp,
Method2:WrapperStartStopApp
), elle ajoute une certaine complexité.
Si les fonctionnalités supplémentaires ne sont pas nécessaires,
l'implémentation d'un Shutdown Hook
pour permettre l'utilisation de la Méthode 1,
ou l'implémentation d'une classe d'arrêt, devrait être envisagée comme options.
La méthode main d'une classe shutdown peut être aussi simple que d'appeler simplement une méthode d'arrêt dans l'application.
Ce document ne couvrira pas l'installation des fichiers du Wrapper
ni des scripts qui seront utilisés pour lancer l'application.
Ces deux sujets sont traités en détail dans les descriptions des
deux premières méthodes d'intégration
(Method1:WrapperSimpleApp,
Method2:WrapperStartStopApp).
Instructions détaillées
La classe principale de l'application
Avant d'expliquer le processus trop en détail, nous commencerons par
un exemple de classe principale, puis nous expliquerons chacun de ses composants.
Le code ci-dessous est une classe simple qui implémente l'interface
WrapperListener
et contient une méthode main qui instancie la classe
et appelle start sur le WrapperManager.
Parcourez-le rapidement, nous l'examinerons étape par étape ci-dessous.
import org.tanukisoftware.wrapper.WrapperManager;
import org.tanukisoftware.wrapper.WrapperListener;
public class Main
implements WrapperListener
{
private MyApp m_app;
/*---------------------------------------------------------------
* Constructors
*-------------------------------------------------------------*/
private Main()
{
}
/*---------------------------------------------------------------
* WrapperListener Methods
*-------------------------------------------------------------*/
/**
* The start method is called when the WrapperManager is signaled by the
* native Wrapper code that it can start its application. This
* method call is expected to return, so a new thread should be launched
* if necessary.
*
* @param args List of arguments used to initialize the application.
*
* @return Any error code if the application should exit on completion
* of the start method. If there were no problems then this
* method should return null.
*/
public Integer start( String[] args )
{
m_app = new MyApp( args );
m_app.start();
return null;
}
/**
* Called when the application is shutting down. The Wrapper assumes that
* this method will return fairly quickly. If the shutdown code code
* could potentially take a long time, then WrapperManager.signalStopping()
* should be called to extend the timeout period. If for some reason,
* the stop method can not return, then it must call
* WrapperManager.stopped() to avoid warning messages from the Wrapper.
*
* @param exitCode The suggested exit code that will be returned to the OS
* when the JVM exits.
*
* @return The exit code to actually return to the OS. In most cases, this
* should just be the value of exitCode, however the user code has
* the option of changing the exit code if there are any problems
* during shutdown.
*/
public int stop( int exitCode )
{
m_app.stop();
return exitCode;
}
/**
* Called whenever the native Wrapper code traps a system control signal
* against the Java process. It is up to the callback to take any actions
* necessary. Possible values are: WrapperManager.WRAPPER_CTRL_C_EVENT,
* WRAPPER_CTRL_CLOSE_EVENT, WRAPPER_CTRL_LOGOFF_EVENT, or
* WRAPPER_CTRL_SHUTDOWN_EVENT
*
* @param event The system control signal.
*/
public void controlEvent( int event )
{
if ( ( event == WrapperManager.WRAPPER_CTRL_LOGOFF_EVENT )
&& ( WrapperManager.isLaunchedAsService() || WrapperManager.isIgnoreUserLogoffs() ) )
{
// Ignore
}
else
{
WrapperManager.stop( 0 );
// Will not get here.
}
}
/*---------------------------------------------------------------
* Main Method
*-------------------------------------------------------------*/
public static void main( String[] args )
{
// Start the application. If the JVM was launched from the native
// Wrapper then the application will wait for the native Wrapper to
// call the application's start method. Otherwise the start method
// will be called immediately.
WrapperManager.start( new Main(), args );
}
}
La méthode main
La méthode main devrait dans la plupart des cas être extrêmement simple.
Elle a pour rôle d'instancier une classe qui implémente l'interface
WrapperListener
puis de transmettre cette instance ainsi que tous les arguments à la
méthode start de la classe
WrapperManager.
Bien qu'il ne s'agisse pas d'une règle stricte, en général, la méthode main ne devrait rien faire d'autre.
Toute l'initialisation de l'application devrait être effectuée
depuis la méthode start.
public static void main( String[] args )
{
// Start the application. If the JVM was launched from the native
// Wrapper then the application will wait for the native Wrapper to
// call the application's start method. Otherwise the start method
// will be called immediately.
WrapperManager.start( new Main(), args );
}
Constructeur
Le constructeur devrait généralement être vide car il doit se terminer dans
le cadre de la méthode main ci-dessus.
En général, la règle de ne rien faire jusqu'à ce que la
méthode start ait été appelée devrait être suivie.
private Main()
{
}
Méthode start de WrapperListener
La méthode start est l'endroit où les choses
commencent à se produire. Elle est appelée par le
WrapperManager après qu'il a
établi une connexion avec le processus Wrapper.
Une fois que le Wrapper a confirmé que le processus Java a été lancé avec succès
et que la classe WrapperManager
a été chargée,
il demandera que l'application utilisateur soit démarrée en appelant la
méthode
WrapperListener.start.
À bien des égards, la méthode start
peut être considérée comme remplaçant la
méthode main d'une application. Il y a cependant quelques
différences que vous devrez garder à l'esprit. La
méthode start est appelée pendant que
l'application est dans sa phase de démarrage et l'application ne sera pas
considérée comme ayant démarré tant que la
méthode start n'aura pas retourné.
Le Wrapper doit pouvoir déterminer quand une application a réellement
terminé son démarrage afin de différer le lancement d'autres
processus qui dépendent de l'application contrôlée par le Wrapper.
Ceci n'est actuellement un problème que pour la version Windows,
dans les cas où un autre service Windows a le Wrapper dans sa liste de dépendances de services.
Ces dépendances stipulent que le Wrapper
doit être démarré avant et arrêté après le service dépendant.
Dans ce premier exemple,
la méthode start appelle simplement
la méthode main d'une autre classe.
N'oubliez pas que cela ne fonctionnera que si nous savons avec certitude
que la méthode main retournera en quelques secondes.
L'exemple suivant instancie la classe principale d'une application, puis lui demande de démarrer.
public Integer start( String[] args )
{
m_app = new MyApp( args );
m_app.start();
return null;
}
La valeur de retour de la méthode start donne à l'application une chance
d'interrompre le processus de démarrage avant que l'application n'ait réellement
été officiellement démarrée. Cela peut être important lorsqu'il s'agit de
services dépendants. Si vous avez de telles préoccupations, vous devez alors
utiliser cette méthode d'intégration. Les deux classes d'aide
method1 (WrapperSimpleApp) et
method2 (WrapperStartStopApp)
appellent la méthode main de l'application dans un thread d'arrière-plan et
signalent que l'application a démarré avec succès en quelques
secondes.
Une valeur de retour de « NULL » indique un démarrage réussi,
tandis que tout objet Integer est utilisé pour indiquer
le code de sortie que le Wrapper devrait retourner lorsqu'il se termine.
public Integer start( String[] args )
{
m_app = new MyApp( args );
m_app.start();
if ( m_app.isOk() )
{
return null;
}
else
{
System.out.println( "MyApp startup failed." );
return new Integer( 1 );
}
}
Comme indiqué ci-dessus, le Wrapper suppose que la
méthode start retourne
après que l'application a démarré.
Par défaut, le Wrapper attendra 30 secondes que la méthode start se termine.
Ce délai d'attente peut être défini à l'aide de la
propriété
wrapper.startup.timeout,
mais il n'est pas toujours souhaitable de définir cette propriété à une valeur élevée.
WrapperManager.signalStarting() :
Pour les applications dont le temps de démarrage est variable,
le Wrapper fournit un moyen pour l'application de rendre compte de sa progression.
À différents moments de la phase de démarrage, le code utilisateur peut appeler périodiquement
WrapperManager.signalStarting().
Cette méthode informe le Wrapper que
la JVM est en vie et que le démarrage de l'application se déroule bien.
Le rapport sera répété autant de fois que nécessaire.
Par conséquent, ce temps supplémentaire est requis,
et le démarrage peut prendre beaucoup plus de temps.
public Integer start( String[] args )
{
m_app = new MyApp( args );
WrapperManager.signalStarting( 60000 );
// Do something that takes a while
WrapperManager.signalStarting( 60000 );
// Do something else that also may take a while
return null;
}
NOTE
Si votre méthode start ne retourne pas en temps voulu, le Wrapper déclenchera un timeout avec
un message comme le suivant :
Startup failed: Timed out waiting for signal from JVM.
Si cela se produit, veuillez relire cette section.
Méthode stop de WrapperListener
La méthode stop est appelée par le Wrapper chaque fois que la JVM doit être arrêtée.
Elle sera toujours appelée, qu'un utilisateur appuie sur
CTRL-C,
que l'application soit arrêtée via le gestionnaire de services Windows ou depuis un script,
ou que le code utilisateur appelle
System.exit
ou WrapperManager.stop.
S'il existe du code dans votre application pour effectuer un arrêt propre,
il devrait être appelé depuis cette méthode, plutôt que de faire appeler
WrapperManager.stop par votre code d'arrêt.
Cela garantira que le code d'arrêt est toujours appelé au
bon moment. Sachez que les Shutdown Hooks existants continueront
de fonctionner comme toujours.
La méthode stop est appelée avec
le code de sortie avec lequel le Wrapper prévoit de se terminer. Vous avez
le choix de retourner ce même code de sortie, ou de modifier le code de
sortie pour refléter un problème lors de l'arrêt de l'application.
public int stop( int exitCode )
{
m_app.stop();
return exitCode;
}
Comme pour la méthode start.
Il arrive que
l'arrêt d'une application prenne plus de temps que le délai disponible dans le timeout d'arrêt par défaut.
Dans ce cas, vous avez la possibilité d'étendre le timeout d'arrêt à l'aide de la
propriété
wrapper.shutdown.timeout.
WrapperManager.signalStopping() :
Plutôt que de modifier cette propriété,
le Wrapper fournit un moyen pour l'application de rendre compte de sa progression.
À différents moments de la phase d'arrêt, le code utilisateur peut appeler périodiquement
WrapperManager.signalStopping().
Cette méthode informe le Wrapper que
la JVM est en vie et que l'arrêt de l'application se déroule bien.
Le rapport sera répété autant de fois que nécessaire.
Par conséquent, ce temps supplémentaire est requis,
et l'arrêt peut prendre beaucoup plus de temps.
public int stop( int exitCode )
{
WrapperManager.signalStopping( 60000 );
// Do some cleanup that takes a while
WrapperManager.signalStopping( 60000 );
// Do some more cleanup that takes a while
return exitCode;
}
Méthode controlEvent de WrapperListener
La méthode controlEvent est utilisée pour
recevoir les événements de contrôle du système.
Ceux-ci incluent CTRL-C sur toutes les plates-formes,
ainsi que les événements lorsque l'utilisateur se déconnecte ou que la machine veut s'arrêter, sous Windows.
Dans la plupart des cas, le Wrapper gérera correctement tous ces événements et déclenchera le processus d'arrêt.
Cependant, il est également possible d'exécuter l'application Java directement sans utiliser le Wrapper.
Cela peut être fait pour des tests ou pour un certain nombre de raisons.
Dans ce cas, c'est à l'application Java de gérer son propre cycle de vie.
L'exemple suivant déclenchera un arrêt de la JVM
si l'utilisateur appuie sur CTRL-C, clique sur la case de fermeture,
se déconnecte ou arrête la machine.
Mais uniquement si elle n'est pas contrôlée par le Wrapper.
public void controlEvent( int event )
{
if ( ( event == WrapperManager.WRAPPER_CTRL_LOGOFF_EVENT )
&& ( WrapperManager.isLaunchedAsService() || WrapperManager.isIgnoreUserLogoffs() ) )
{
// Ignore
}
else
{
WrapperManager.stop( 0 );
// Will not get here.
}
}