Come posso eseguire una class in una WAR dalla riga di comando?

Ho una class Java che ha un main e che usavo come app standalone dalla riga di comando ad es

java -jar myjar.jar params 

Avevo bisogno di riconfezionare il codice da eseguire sotto apache e tutto il mio codice, inclusa la class del punto di ingresso dal vecchio jar, è finito in un file WAR per una facile deplyment nel server web.

Tuttavia, voglio ancora essere in grado di eseguirlo dalla riga di comando e il codice non è cambiato ed è tutto lì dentro, non riesco proprio a capire come farlo funzionare.

Ecco cosa ho provato …

Presumevo che la GUERRA fosse proprio come un jar, quindi

 java -jar mywar.war params 

Questo ha fallito dicendo che non c’era alcuna class principale definita nel manifest.

Ho aggiunto manualmente un manifest alla guerra e ho provato di nuovo, con lo stesso effetto.

Ho notato che nella mia guerra avevo una cartella chiamata META-INF che conteneva un manifest.mf, quindi ho aggiunto una riga a quella che dichiarava la mia class principale come farebbe con un manifest normale …

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

Questo ha dato un noClassDefFoundError mypackage.MyEntryPointClass , che è un progresso di un ordinamento. Ciò mi ha portato a credere che fosse solo un problema di percorso, così ci ho provato

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

Ora ho lo stesso errore, ma con una traccia dello stack …

 Exception in thread "main" java.lang.NoClassDefFoundError: WEB-INF/classs/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) 

Ho cercato su Google un po ‘ma non riesco a trovare nulla che risponda alla mia domanda, e ho letto un paio di altre domande qui che sono leggermente diverse, quindi ho pensato di pubblicare.

Java 1.5, non che penso che dovrebbe fare alcuna differenza.

Puoi fare quello che fa Hudson (progetto di integrazione continua). scarichi una guerra che può essere distribuita in tomcat o da eseguire usando

 java -jar hudson.war 

(Poiché ha un motore Jetty incorporato, eseguendolo dalla riga di comando causa il lancio di un server.) Comunque, guardando il manifest di hudson, capisco che hanno messo una class Main nella root per l’archivio. Nel tuo caso il tuo layout di guerra dovrebbe essere simile a:

sotto la radice:

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

mentre il manifest dovrebbe includere la seguente riga:

 Main-Class: mypackage.MyEntryPointClass 

si prega di notare che il mypackage / MyEntryPointClass.class è accessibile solo dalla riga di comando e che le classi in WEB-INF / classs sono accessibili solo dal server delle applicazioni.

HTH

Simile a quello di Richard Detsch ma con un po ‘più facile da seguire (funziona anche con i pacchetti)

Step 1: Unwrap the War file.

 jar -xvf MyWar.war 

Passaggio 2: sposta nella directory

 cd WEB-INF 

Passaggio 3: esegui il tuo principale con tutte le dipendenze

 java -classpath "lib/*:classs/." my.packages.destination.FileToRun 

Una guerra è una webapp. Se vuoi avere una console / applicazione standalone che riutilizza le stesse classi della tua webapp, considera la possibilità di impacchettare le tue classi condivise in un jar, che puoi inserire in WEB-INF/lib . Quindi usa quel jar dalla riga di comando. In questo modo si ottiene sia l’applicazione della console che è ansible utilizzare le stesse classi nei propri servlet, senza creare due pacchetti diversi. Questo, ovviamente, è vero quando la guerra è esplosa.

Per eseguire SomeClass.main (String [] args) da un file di guerra distribuito fare:

Passo 1: Scrivi class SomeClass.java che ha un metodo metodo principale cioè (public static void main (String [] args) {…})

Passaggio 2: distribuisci la tua GUERRA

Passaggio 3: cd / usr / local / yourprojectsname / tomcat / webapps / projectName / WEB-INF

Passaggio 4: java -cp “lib / jar1.jar: lib / jar2.jar: …: lib / jarn.jar” com.mypackage.SomeClass arg1 arg2 … arg3

Nota 1: (per vedere se la class SomeOtherClass.class è in / usr / tomcat / webapps / projectName / WEB-INF / lib)

eseguire -> cd / usr / tomcat / webapps / projectName / WEB-INF / lib && find. -name ‘* .jar’ | mentre leggi jarfile; fai se jar tf “$ jarfile” | grep SomeOtherClass.class; quindi echo “$ jarfile”; fi; fatto

Nota 2: scrivi sullo standard in modo da poter vedere se il tuo principale funziona effettivamente tramite le istruzioni di stampa sulla console. Questa è chiamata una porta di servizio.

Nota3: il commento sopra di Bozhidar Bozhanov sembra corretto

Le regole di localizzazione delle classi in un file di archivio sono che la posizione della dichiarazione del pacchetto del file e la posizione del file all’interno dell’archivio devono corrispondere. Poiché la class si trova in WEB-INF / classi, la class non è valida per l’esecuzione nel contesto corrente.

L’unico modo in cui puoi fare quello che stai chiedendo è di ricompattare la guerra in modo che il file .class risieda nella directory di mypackage nella root dell’archivio piuttosto che nella directory WEB-INF / classs. Tuttavia, se lo fai, non sarai più in grado di accedere al file da nessuna delle tue classi web.

Se si desidera riutilizzare questa class in war e all’esterno dalla riga di comando java, prendere in considerazione la creazione di un jar eseguibile che è ansible eseguire dalla riga di comando, quindi inserire tale jar nella directory WEB-INF / lib del file war .

Nel progetto Maven , puoi creare jar automaticamente usando il plugin Maven War impostando archiveClasses su true . Esempio di seguito.

  org.apache.maven.plugins maven-war-plugin  true   

Se stai usando Maven, basta seguire la documentazione di maven-war-plugin su ” Come posso creare un JAR contenente le classi nella mia webapp? “: Aggiungi true alla del plugin :

  ... mywebapp 1.0-SNAPSHOT ...    maven-war-plugin 2.6  true     ...  

Avrai 2 prodotti nella target/ cartella:

  • Il project.war stesso
  • Il project-classs.jar che contiene tutte le classi compilate in un barattolo

Quindi sarai in grado di eseguire una class principale usando il metodo classico: java -cp target/project-classs.jar 'com.mycompany.MainClass' param1 param2

Bene, secondo Wikipedia , con un file WAR, le classi che vengono caricate nel classpath sono nella directory “/ WEB-INF / classs” e “/ WEB-INF / lib”.

Potresti provare semplicemente a mettere una copia delle classi sul file system di root del file zip (che è ciò che è war / jar). Non sono sicuro che funzionerebbe comunque.

Puoi sempre creare solo due file separati.

Non è ansible eseguire una class java da un file WAR. I file WAR hanno una struttura diversa rispetto ai file Jar.

Per trovare le classi java correlate, esportare (modo preferito di usare ant) ​​come Jar metterlo nella tua lib di web app.

Quindi è ansible utilizzare il file jar normalmente per eseguire il programma java. Lo stesso barattolo è stato anche indicato nell’app Web (se si inserisce questo jar nella libreria Web lib)