2013-03-05 12 views
7

Es wurde versucht, eine vorhandene Java/Tomcat-App für die Bereitstellung auf Heroku nach ihrer tutorial zu modifizieren und Probleme mit AppAssembler zu finden, die die Eintragsklasse nicht finden. Das Ausführen von target/bin/webapp (oder die Bereitstellung bei Heroku) führt zu Error: Could not find or load main class org.stopbadware.dsp.MainMaven AppAssembler findet keine Klasse

Die Ausführung von java -cp target/classes:target/dependency/* org.stopbadware.dsp.Main läuft jedoch ordnungsgemäß. Hier ist der relevante Teil der 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> 

Meine Vermutung ist mvn package AppAssembler verursacht nicht die richtige Classpath zu verwenden, irgendwelche Vorschläge?

+0

Können Sie zeigen, wie das generierte Skript (.sh/.bat) aussieht? – khmarbaise

+0

Das generierte Skript kann unter http://pastebin.com/f9gbVMgx eingesehen werden - die Main-Klasse, die nicht gefunden wird, befindet sich in PROJECTROOT/src/org/stopbadware/dsp/ – Exupery

Antwort

5

Verpackung Ihr Artefakts muss jar eingestellt werden, da sonst die Hauptklasse nicht gefunden wird.

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

Das Artefakt selbst wird am Ende des Classpath hinzugefügt, so nichts anderes als eine JAR-Datei wird keine Auswirkungen haben.

1

Die erste Sache ist, dass Sie eine alte Version von appassembler-maven-plugin der aktuellen Version 1.3 verwenden.

Was ich nicht verstehe, warum Sie die

<assembleDirectory>target</assembleDirectory> 

Ordner definieren, sind. Dafür gibt es einen guten Standardwert. Also normalerweise brauchst du es nicht. Abgesehen davon müssen Sie keine explizite Ausführung definieren, die an die Paketphase gebunden ist, die appassembler-maven-plugin is by default bound to the package phase verursacht.

Außerdem können Sie die Konfigurationsoption useWildcardClassPath verwenden, um Ihren Klassenpfad kürzer zu machen.

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

Und dass die Berufung des erzeugten Skript zeigt die Fehler auf der Sache abhängig, dass die Position des Repository, in dem alle Abhängigkeiten im Ordner anders angeordnet sind als in der generierten Skript definiert.

+0

Das war meine erste Erfahrung mit AppAssembler, also benutzte ich was Heroku hatte in dem zuvor erwähnten Tutorial. Verwenden von 1.3, das Entfernen der Verzeichnis- und Ausführungsreferenzen und das Hinzufügen der Wildcard-Optionen hatte keine Wirkung, immer noch den gleichen Fehler. Beim Erstellen des Skripts wird eindeutig nicht der korrekte Klassenpfad erstellt, und leider ist die AppAssembler-Dokumentation ziemlich eingeschränkt und scheint nicht anzugeben, wie explizit zum generierten Klassenpfad hinzugefügt werden soll. – Exupery

+0

Das Beste ist, ein Beispielprojekt (mit pom.xml) auf [jira] (https://jira.codehaus.org/browse/MAPPASM) zu legen und ein Problem zu erstellen oder mir einfach die Datei pom.xml privat zu schicken Ich kann mir dein Problem ansehen. – khmarbaise

+0

Sie können die pom.xml unter http://pastebin.com/11WmjBmB sehen - das von appassembler generierte Skript befindet sich unter http://pastebin.com/f9gbVMgx und funktioniert ordnungsgemäß, wenn der fehlende Eintrag PROJECTROOT/target/classes im Klassenpfad ist behoben durch Hinzufügen von '" $ BASEDIR "/ classes' – Exupery

1

Konnte dies lösen, indem "$BASEDIR"/classes der CLASSPATH-Zeile im generierten Skript hinzugefügt wurde. Da das Skript bei jedem Aufruf von mvn package neu geschrieben wird, schrieb ich ein kurzes Skript, das mvn package aufruft und dann den erforderlichen Classpath-Eintrag hinzufügt.

Offensichtlich ein bisschen von einem Hack, aber nach 8+ Stunden des Versuchs einer "richtigen" Lösung wird dies für jetzt tun müssen. Wird sicherlich noch elegantere Möglichkeiten haben, den hier vorgeschlagenen Klassenpfad zu korrigieren.

3

Versuchen:

mvn clean package jar:jar appassembler:assemble 
+2

Das funktioniert gut auf meinem lokalen Rechner, aber nicht einmal nach Heroku eingesetzt. Von dem, was ich sehen kann, gibt es keine Möglichkeit, Herokus Maven-Befehl von seinem Standard 'mvn clean install' zu ändern (das Hinzufügen von' jar: jar appassembler: assemble' zu ​​MAVEN_OPTS hatte keinen Effekt). – Exupery

1

Sie können das CLASSPATH_PREFIX Umgebungsvariable:

export CLASSPATH_PREFIX=target/classes 

, die auf dem Classpath des erzeugten Skript erhalten wird vorangestellt.

1

Ich war vor einiger Zeit durch dieses Tutorial gegangen und hatte sehr ähnliches Problem. Ich kam mit einem etwas anderen Ansatz, der für mich sehr gut funktioniert.

Zunächst einmal, wie es vorher erwähnt wurde, müssen Sie Ihre POM Typen als jar (<packaging>jar</packaging>) halten - dank, dass, wird appassembler Plugin eine JAR-Datei von Ihren Klassen erzeugen und es zu dem Classpath hinzufügen. Also, damit wird dein Fehler verschwinden.

Bitte beachten Sie, dass dieses Tutorial Tomcat aus dem Quellverzeichnis der Anwendung instanziiert wird. In vielen Fällen ist das ausreichend, aber beachten Sie bitte, dass Sie mit diesem Ansatz Servlet @WebServlet Annotationen nicht verwenden können, da /WEB-INF/classes in Quellen leer ist und Tomcat Ihre Servlet-Klassen nicht scannen kann. So HelloServlet Servlet von diesem Tutorial wird nicht funktionieren, es sei denn, Sie fügen einige zusätzliche Tomcat-Initialisierung (Ressourcenkonfiguration) wie beschrieben here (BTW, finden Sie mehr SO Fragen sprechen über diese Ressource Konfiguration).

Ich habe ein bisschen anderen Ansatz:

Ich betreibe ein org.apache.maven.plugins:maven-war-plugin Plugin (exploded Ziel) während package und Verwendung, das Verzeichnis als meine Quellverzeichnis-Anwendung generiert. Mit diesem Ansatz wird mein Webanwendungsverzeichnis /WEB-INF/classes mit Klassen "aufgefüllt". Dies wiederum ermöglicht es Tomcat, den Scan-Job korrekt auszuführen (d. H. Servlet @WebServlet Annotationen funktionieren).

Ich musste auch eine Quelle für meine Anwendung in der Klasse Launcher ändern:

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 

Änderungen an POM, die ich hinzugefügt - maven-war-plugin vor appassembler Plugin nur enthalten:

... 
<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> 
... 

Bitte beachten Sie, dass exploded Ziel heißt.

Ich hoffe, dass kleine Änderungen Ihnen helfen werden.


Ein weiterer Kommentar zu diesem Tutorial und Maven Build: beachten Sie, dass das Tutorial zu zeigen, geschrieben wurde, wie einfach ist es, eine Anwendung zu erstellen und sie in Heroku laufen. Dies ist jedoch nicht der beste Ansatz zur Erstellung von Maven.

Die Empfehlung von Maven ist, dass Sie sich daran halten sollten, ein Artefakt pro POM herzustellen. In Ihrem Fall gibt es sollte zwei Artefakte:

  • Tomcat Launcher
  • Tomcat Web-Anwendung

Beide sollten als separaten POMs und verwies als Module aus Ihren Eltern POM sein zu bauen. Wenn Sie sich die Komplexität dieses Tutorials anschauen, ist es nicht sinnvoll, das in zwei Module aufzuteilen. Wenn Ihre Anwendungen jedoch immer komplexer werden (und der Launcher einige zusätzliche Konfigurationen usw. erhält), wird es sehr sinnvoll sein, diesen "Split" zu machen. In der Tat, es gibt einige "Tomcat Launcher" -Bibliotheken, die bereits erstellt wurden, so dass Sie alternativ eine davon verwenden könnten.

Verwandte Themen