web-dev-qa-db-fra.com

Comment exécuter une classe dans un WAR à partir de la ligne de commande?

J'ai une classe Java qui a une classe principale et que j’exécutais auparavant en tant qu’application autonome à partir de la ligne de commande, par exemple.

Java -jar myjar.jar params

Je devais reconditionner le code pour qu'il fonctionne sous Apache et tout mon code, y compris la classe de point d'entrée de l'ancien fichier jar, s'est retrouvé dans un fichier WAR pour un déploiement facile sur le serveur Web.

Cependant, je veux toujours pouvoir l'exécuter à partir de la ligne de commande et le code n'a pas changé et est tout ce qu'il y a dedans, je ne peux tout simplement pas trouver comment le faire fonctionner.

Voici ce que j'ai essayé ...

J'ai supposé que la guerre était comme un pot, alors

Java -jar mywar.war params

Cela a échoué en disant qu'il n'y avait pas de classe principale définie dans le manifeste.

J'ai ajouté manuellement un manifeste à la guerre et essayé à nouveau, avec le même effet.

J'ai remarqué que dans ma guerre j'avais un dossier appelé META-INF contenant un manifest.mf, alors j'ai ajouté une ligne à celle déclarant ma classe principale comme je le ferais pour un manifeste normal ...

Manifest-Version: 1.0
Main-Class: mypackage.MyEntryPointClass

Cela a donné un noClassDefFoundError mypackage.MyEntryPointClass, qui est une sorte de progrès. Cela m'a amené à croire que c'était juste un problème de chemin, alors j'ai essayé

Manifest-Version: 1.0
Main-Class: WEB-INF.classes.mypackage.MyEntryPointClass

J'ai maintenant la même erreur, mais avec une trace de pile ...

Exception in thread "main" Java.lang.NoClassDefFoundError: WEB-INF/classes/mypackage/MyEntryPointClass (wrong name: mypackage/MyEntryPointClass)
        at Java.lang.ClassLoader.defineClass1(Native Method)
        at Java.lang.ClassLoader.defineClass(Unknown Source)
        at Java.security.SecureClassLoader.defineClass(Unknown Source)
        at Java.net.URLClassLoader.defineClass(Unknown Source)
        at Java.net.URLClassLoader.access$100(Unknown Source)
        at Java.net.URLClassLoader$1.run(Unknown Source)
        at Java.security.AccessController.doPrivileged(Native Method)
        at Java.net.URLClassLoader.findClass(Unknown Source)
        at Java.lang.ClassLoader.loadClass(Unknown Source)
        at Sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at Java.lang.ClassLoader.loadClass(Unknown Source)
        at Java.lang.ClassLoader.loadClassInternal(Unknown Source)

J'ai cherché sur Google pendant un moment, mais je ne trouve rien qui réponde à ma question. J'ai lu quelques autres questions ici qui sont légèrement différentes, alors j'ai pensé poster.

Java 1.5, pas que je pense que cela devrait faire la différence.

63
Simon

Vous pouvez faire ce que Hudson (projet d'intégration continue) fait. vous téléchargez une guerre pouvant être déployée dans Tomcat ou exécutée à l'aide de

Java -jar hudson.war

(Comme il a un moteur Jetty intégré, son exécution à partir de la ligne de commande provoque le lancement d'un serveur.) Quoi qu'il en soit, en regardant le manifeste de hudson, je comprends qu'ils ont mis une classe Main à la racine de l'archive. Dans votre cas, votre plan de guerre devrait ressembler à ceci:

sous la racine:

  • mypackage/MyEntryPointClass.class
  • WEB-INF/lib
  • WEB-INF/classes
  • META-INF/MANIFEST.MF

tandis que le manifeste devrait inclure la ligne suivante:

Main-Class: mypackage.MyEntryPointClass

veuillez noter que le fichier mypackage/MyEntryPointClass.class est accessible uniquement à partir de la ligne de commande et que les classes figurant sous WEB-INF/classes ne sont accessibles que depuis le serveur d'applications.

HTH

36
Yonatan Maman

Semblable à ce que Richard Detsch mais avec un peu plus facile à suivre (fonctionne aussi avec les paquets)

Étape 1: Déballez le fichier War.

jar -xvf MyWar.war

Étape 2: déplacez-vous dans le répertoire

cd WEB-INF

Étape 3: lancez votre main avec toutes les dépendances

Java -classpath "lib/*:classes/." my.packages.destination.FileToRun
29
Bojan Petkovic

Une guerre est une webapp. Si vous souhaitez qu'une application console/autonome réutilise les mêmes classes que votre application Web, envisagez de conditionner vos classes partagées dans un fichier jar, que vous pouvez insérer dans WEB-INF/lib. Ensuite, utilisez ce fichier depuis la ligne de commande. Ainsi, vous obtenez votre application console et vous pouvez utiliser les mêmes classes dans vos servlets, sans créer deux packages différents. Ceci, bien sûr, est vrai lorsque la guerre est éclatée.

10
Bozho

Pour exécuter SomeClass.main (String [] args) à partir d'un fichier war déployé, procédez comme suit:

Étape 1: Écrivez la classe SomeClass.Java qui a une méthode principale, c'est-à-dire (public static void main (String [] args) {...})

Étape 2: Déployez votre WAR

Étape 3: cd/usr/local/votre nomprojet/Tomcat/webapps/nomProjet/WEB-INF

Étape 4: Java -cp "lib/jar1.jar: lib/jar2.jar: ...: lib/jarn.jar" com.mypackage.SomeClass arg1 arg2 ... arg3

Note1: (pour voir si la classe SomeOtherClass.class est dans/usr/Tomcat/webapps/nomProjet/WEB-INF/lib)

lancer -> cd/usr/Tomcat/webapps/nomduprojet/WEB-INF/lib && find. -name '* .jar' | en lisant jarfile; faire si jar tf "$ jarfile" | grep SomeOtherClass.class; puis echo "$ jarfile"; Fi; terminé

Remarque2: écrivez en sortie standard afin de voir si votre travail principal fonctionne via des instructions d'impression sur la console. Ceci s'appelle une porte arrière.

Note3: Le commentaire de Bozhidar Bozhanov semble correct

8
Richard Detsch

Selon les règles de localisation des classes dans un fichier d'archive, l'emplacement de la déclaration de package du fichier et l'emplacement du fichier dans l'archive doivent correspondre. Puisque votre classe est située dans WEB-INF/classes, il pense que la classe n’est pas valide pour être exécutée dans le contexte actuel.

La seule façon de faire ce que vous demandez est de reconditionner la guerre pour que le fichier .class Réside dans le répertoire mypackage à la racine de l'archive plutôt que dans le répertoire WEB-INF/classes . Cependant, si vous faites cela, vous ne pourrez plus accéder au fichier depuis aucune de vos classes Web.

Si vous souhaitez réutiliser cette classe à la fois en dehors de la ligne de commande Java), envisagez de créer un fichier jar exécutable que vous pouvez exécuter à partir de la ligne de commande, puis placez-le dans la zone war répertoire WEB-INF/lib du fichier.

6
Jason Gritman

Dans le projet Maven , vous pouvez créer un fichier jar automatiquement à l'aide de plug-in Maven War en définissant archiveClasses sur true. Exemple ci-dessous.

<plugin>
       <groupId>org.Apache.maven.plugins</groupId>
       <artifactId>maven-war-plugin</artifactId>
       <configuration>
        <archiveClasses>true</archiveClasses>
       </configuration>
</plugin>
4
marioosh

Si vous utilisez Maven, suivez simplement la documentation maven-war-plugin Sur " Comment créer un fichier JAR contenant les classes de mon application Web? ": add <attachClasses>true</attachClasses> au <configuration> Du plugin:

<project>
  ...
  <artifactId>mywebapp</artifactId>
  <version>1.0-SNAPSHOT</version>
  ...
  <build>
    <plugins>
      <plugin>
    <artifactId>maven-war-plugin</artifactId>
    <version>2.6</version>
    <configuration>
      <attachClasses>true</attachClasses>
    </configuration>
      </plugin>
    </plugins>
  </build>
  ...
</project>

Vous aurez 2 produits dans le dossier target/:

  • Le project.war Lui-même
  • Le project-classes.jar Qui contient toutes les classes compilées dans un jar

Ensuite, vous pourrez exécuter une classe principale en utilisant la méthode classique: Java -cp target/project-classes.jar 'com.mycompany.MainClass' param1 param2

3
Anthony O.

Eh bien, selon Wikipedia , avec un fichier WAR, les classes chargées dans le classpath se trouvent dans les répertoires "/ WEB-INF/classes" et "/ WEB-INF/lib".

Vous pouvez simplement essayer de placer une copie des classes sur le système de fichiers racine du fichier Zip (c'est ce que war/jar est). Je ne sais pas si cela fonctionnerait bien.

Vous pouvez toujours simplement créer deux fichiers distincts.

0
Chad Okere