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.
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:
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
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
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.
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
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.
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>
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/
:
project.war
Lui-mêmeproject-classes.jar
Qui contient toutes les classes compilées dans un jarEnsuite, vous pourrez exécuter une classe principale en utilisant la méthode classique: Java -cp target/project-classes.jar 'com.mycompany.MainClass' param1 param2
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.