2013-03-05 17 views
7

Tentativo di modificare un'app Java/Tomcat esistente per la distribuzione su Heroku dopo il tutorial e l'esecuzione di alcuni problemi con AppAssembler che non trova la classe di immissione. L'esecuzione di destinazione/bin/webapp (o la distribuzione in Heroku) produce Error: Could not find or load main class org.stopbadware.dsp.MainMaven AppAssembler non trova la classe

L'esecuzione di java -cp target/classes:target/dependency/* org.stopbadware.dsp.Main tuttavia viene eseguita correttamente. Ecco la quota di competenza di pom.xml:

<plugin> 
     <groupId>org.codehaus.mojo</groupId> 
     <artifactId>appassembler-maven-plugin</artifactId> 
     <version>1.1.1</version> 
     <configuration> 
      <assembleDirectory>target</assembleDirectory> 
      <programs> 
       <program> 
        <mainClass>org.stopbadware.dsp.Main</mainClass> 
        <name>webapp</name> 
       </program> 
      </programs> 
     </configuration> 
     <executions> 
      <execution> 
       <phase>package</phase> 
       <goals> 
        <goal>assemble</goal> 
       </goals> 
      </execution> 
     </executions> 
    </plugin> 

La mia ipotesi è mvn package sta causando AppAssembler non utilizzare il percorso di classe corretta, qualche suggerimento?

+0

Puoi mostrare come appare lo script generato (.sh/.bat)? – khmarbaise

+0

Lo script generato può essere visto su http://pastebin.com/f9gbVMgx - la classe Main che non è stata trovata è in PROJECTROOT/src/org/stopbadware/dsp/ – Exupery

risposta

5

vostro del manufatto deve essere impostato su jar, altrimenti la classe principale non è stato trovato.

<pom> 
    ... 
    <packaging>jar</packaging> 
    ... 
</pom> 

Il manufatto si è aggiunto alla fine del percorso di classe, quindi niente altro che un file JAR avrà alcun effetto.

1

La prima cosa è che si sta utilizzando una versione precedente di appassembler-maven-plugin la versione corrente è 1.3.

Quello che non capisco perché stai definendo la cartella

<assembleDirectory>target</assembleDirectory> 

. Esiste un buon valore predefinito per questo. Quindi di solito non ne hai bisogno. A parte ciò, non è necessario definire un'esecuzione esplicita che si lega alla fase del pacchetto, causa lo appassembler-maven-plugin is by default bound to the package phase.

Inoltre, è possibile utilizzare l'opzione di configurazione useWildcardClassPath per abbreviare il classpath.

<configuration> 
    <useWildcardClassPath>true</useWildcardClassPath> 
    <repositoryLayout>flat</repositoryLayout> 
    ... 
    </configruation> 

E che la chiamata dello script generato mostra l'errore è in funzione la cosa che la posizione del repository in cui si trovano nella cartella di tutte le dipendenze è diverso da quello nello script generato definito.

+0

Questa è stata la mia prima esperienza con AppAssembler, quindi stavo usando quello che Heroku aveva nel tutorial precedentemente menzionato. Usando 1.3, rimuovendo la directory ei riferimenti di esecuzione, e l'aggiunta delle opzioni jolly non ha avuto alcun effetto, ottenendo comunque lo stesso errore. Chiaramente quando si crea lo script non viene creato il classpath corretto e purtroppo la documentazione di AppAssembler è piuttosto limitata e non sembra indicare come aggiungere esplicitamente al classpath generato. – Exupery

+0

La cosa migliore è mettere un progetto di esempio (con il suo pom.xml) su [jira] (https://jira.codehaus.org/browse/MAPPASM) e creare un problema o semplicemente inviarmi il file pom.xml privatamente in modo posso dare un'occhiata al tuo problema – khmarbaise

+0

Puoi vedere il pom.xml su http://pastebin.com/11WmjBmB - lo script generato da un appassionatore è su http://pastebin.com/f9gbVMgx e funziona bene una volta che la voce PROJECTROOT/target/classes mancante nel classpath è corretto aggiungendo '" $ BASEDIR "/ classes' – Exupery

1

È stato possibile risolvere questo problema aggiungendo "$BASEDIR"/classes alla riga CLASSPATH nello script generato. Poiché lo script viene riscritto su ogni chiamata di mvn package, ho scritto uno script breve che chiama mvn package e quindi aggiunge la voce del percorso di classe necessaria.

Ovviamente un po 'un trucco, ma dopo 8+ ore di tentare una soluzione più "corretta" che dovrà fare per ora. Certamente intratterrà altri modi più eleganti di correggere il percorso di classe suggerito qui.

3

Prova: imballaggio

mvn clean package jar:jar appassembler:assemble 
+2

Che funziona bene sul mio computer locale, ma non una volta distribuito su Heroku. Da quello che vedo, non c'è modo di alterare il comando di Heroku dal suo default di 'mvn clean install' (l'aggiunta di' jar: jar appassembler: assemble' a MAVEN_OPTS non ha avuto effetto). – Exupery

1

È possibile impostare la variabile di ambiente CLASSPATH_PREFIX:

export CLASSPATH_PREFIX=target/classes 

che andranno anteporre al classpath dello script generato.

1

Ho seguito quel tutorial un po 'di tempo fa e ho riscontrato un problema molto simile. Sono venuto con un approccio un po 'diverso che funziona per me molto bene.

Prima di tutto, come è stato accennato prima, è necessario mantenere il tipo del vostro POM come jar (<packaging>jar</packaging>) - grazie a ciò, appassembler plugin genererà un file JAR dalle classi e aggiungerlo al classpath. Quindi grazie a ciò il tuo errore andrà via.

Si prega di notare che questo tutorial Tomcat è un'istanza dalla directory di origine delle applicazioni. In molti casi è sufficiente, ma tieni presente che utilizzando tale approccio, non sarai in grado di utilizzare le annotazioni Servlet @WebServlet come /WEB-INF/classes nelle origini è vuoto e Tomcat non sarà in grado di eseguire la scansione delle classi servlet. Quindi il servlet HelloServlet da questo tutorial non funzionerà, a meno che non si aggiunga un'inizializzazione di Tomcat aggiuntiva (configurazione delle risorse) come descritto in here (a proposito, troverai altre domande SO che parlano della configurazione di tale risorsa).

ho fatto un po 'diverso approccio:

Ho eseguito una org.apache.maven.plugins:maven-war-plugin plug-in (exploded gol) durante package e l'uso che ha generato directory come la mia fonte di directory di applicazione. Con questo approccio la mia directory di applicazioni web avrà "popolato" /WEB-INF/classes con le classi. Ciò a sua volta consentirà a Tomcat di eseguire correttamente il lavoro di scansione (vale a dire che le annotazioni servlet @WebServlet funzioneranno).

ho anche dovuto cambiare una fonte della mia applicazione nella classe launcher:

public static void main(String[] args) throws Exception { 
    // Web application is generated in directory name as specified in build/finalName 
    // in maven pom.xml 
    String webappDirLocation = "target/embeddedTomcatSample/"; 
    Tomcat tomcat = new Tomcat(); 

    // ... remaining code does not change 

Modifiche a POM che ho aggiunto - incluso maven-war-plugin poco prima appassembler plugin:

... 
<plugin> 
    <groupId>org.apache.maven.plugins</groupId> 
    <artifactId>maven-war-plugin</artifactId> 
    <version>2.5</version> 
    <executions> 
     <execution> 
      <phase>package</phase> 
      <goals> 
       <goal>exploded</goal> 
      </goals> 
     </execution> 
    </executions> 
</plugin> 
... 

prega di notare che L'obiettivo exploded viene chiamato.

Spero che questo piccolo cambiamento ti possa aiutare.


più Un commento su questo tutorial e Maven costruzione: notare che il tutorial è stato scritto per mostrare come semplice è quello di costruire un'applicazione ed eseguirlo in Heroku. Tuttavia, questo non è l'approccio migliore per costruire Maven.

La raccomandazione di Maven è che si dovrebbe aderire alla produzione di un artefatto per POM. Nel tuo caso ci sono due dovrebbero manufatti:

  • Tomcat launcher
  • Tomcat applicazione web

Entrambi dovrebbero essere costruire POMs come separati e fatto riferimento come i moduli da un genitore POM. Se si guarda alla complessità di quel tutorial, non ha molto senso dividerlo in due moduli. Ma se le tue applicazioni diventano sempre più complesse (e il programma di avvio ottiene alcune configurazioni aggiuntive, ecc.) Sarà molto sensato rendere questa "divisione". In effetti, ci sono alcune librerie "di avvio Tomcat" già create in modo alternativo che potresti usare una di esse.

Problemi correlati