2013-03-05 2 views
7

Пытается изменить существующее приложение Java/Tomcat для развертывания на Heroku после их tutorial и столкнуться с некоторыми проблемами, когда AppAssembler не находит класс записи. Запуск цели/bin/webapp (или развертывание на Heroku) приводит к Error: Could not find or load main class org.stopbadware.dsp.MainMaven AppAssembler не находит класс

Выполнение java -cp target/classes:target/dependency/* org.stopbadware.dsp.Main работает правильно. Вот соответствующая часть 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> 

Моя догадка mvn package вызывает AppAssembler не использовать правильный путь к классам, любые предложения?

+0

Можете ли вы показать, как выглядит сгенерированный скрипт (.sh/.bat)? – khmarbaise

+0

Сгенерированный скрипт можно увидеть на http://pastebin.com/f9gbVMgx - Основной класс, который не найден, находится в PROJECTROOT/src/org/stopbadware/dsp/ – Exupery

ответ

5

Ваш артефакта должен быть установлен в jar, в противном случае главный класс не найден.

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

Сам артефакт добавляется в конце пути к классам, так что ничего, кроме файла JAR не будет иметь никакого эффекта.

1

Первое, что вы используете старую версию appassembler-maven-plugin, текущая версия - 1.3.

Что я не понимаю, почему вы определяя папку с

<assembleDirectory>target</assembleDirectory> 

. Для этого существует хорошее значение по умолчанию. Так что обычно вам это не нужно. Кроме того, вам не нужно определять явное выполнение, которое связано с фазой пакета, вызывают appassembler-maven-plugin is by default bound to the package phase.

Кроме того, вы можете использовать опцию конфигурации useWildcardClassPath, чтобы сделать ваш classpath короче.

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

И что вызывающее сгенерированный сценарий показывает ошибка в зависимости от вещи, что расположение хранилища, где все зависимости находятся в папке отличается в сгенерированном сценарии определен.

+0

Это был мой первый опыт работы с AppAssembler, поэтому я использовал то, что Heroku в упомянутом выше учебнике. Использование 1.3, удаление ссылок на каталоги и выполнение, а добавление в подстановочные параметры не повлияло, все еще получая ту же ошибку. Очевидно, что при создании сценария он не создает правильный путь к классам, и, к сожалению, документация AppAssembler довольно ограничена и, как представляется, не указывает, как явно добавлять к сгенерированному пути к классам. – Exupery

+0

Лучше всего поставить пример проекта (с его pom.xml) на [jira] (https://jira.codehaus.org/browse/MAPPASM) и создать проблему или просто отправить мне файл pom.xml в частном порядке, так что я могу взглянуть на вашу проблему. – khmarbaise

+0

Вы можете увидеть pom.xml по адресу http://pastebin.com/11WmjBmB - сценарий сгенерированный appassembler находится по адресу http://pastebin.com/f9gbVMgx и прекрасно работает после того, как пропавшая запись PROJECTROOT/target/classes в пути к классам исправлено добавлением '' $ BASEDIR "/ classes' – Exupery

1

Удалось решить эту проблему, добавив "$BASEDIR"/classes в строку CLASSPATH в сгенерированном скрипте. Поскольку сценарий переписывается при каждом вызове mvn package, я написал короткий скрипт, который вызывает mvn package, а затем добавляет необходимую запись в класс.

Очевидно, что это немного взломанный, но после более чем 8 часов попыток более «правильного» решения это нужно будет сделать сейчас. Будет, безусловно, развлекать более элегантные способы исправления предложенного здесь класса.

3

Try: упаковка

mvn clean package jar:jar appassembler:assemble 
+2

Это отлично работает на моей локальной машине, но не раз развертывается в Heroku. Из того, что я вижу, нет способа изменить команду maven из Heroku по умолчанию «mvn clean install» (добавление «jar: jar appassembler: assembly» в MAVEN_OPTS не повлияло). – Exupery

1

Вы можете установить переменные окружения CLASSPATH_PREFIX:

export CLASSPATH_PREFIX=target/classes 

который получит предваряется пути к классам сгенерированного сценария.

1

Я проходил этот учебник некоторое время назад и имел очень схожую проблему. Я пришел с немного другим подходом, который работает для меня очень красиво.

Прежде всего, как уже было сказано ранее, вы должны держать тип вашего POM как jar (<packaging>jar</packaging>) - благодаря тому, что, appassembler плагин будет генерировать JAR файл из ваших классов и добавить его в путь к классам. Таким образом, ваша ошибка исчезнет.

Обратите внимание, что этот учебник Tomcat создается из каталога источника приложения. Во многих случаях этого достаточно, но учтите, что с использованием этого подхода вы не сможете использовать аннотации Servlet @WebServlet, так как /WEB-INF/classes в источниках пуст, и Tomcat не сможет сканировать ваши классы сервлета. Так что HelloServlet сервлет из этого учебника не будет работать, если вы не добавите некоторую дополнительную инициализацию Tomcat (конфигурацию ресурсов), как описано here (Кстати, вы найдете больше вопросов о SO, рассказывающих об этой конфигурации ресурсов).

Я сделал несколько иной подход:

Я бегу org.apache.maven.plugins:maven-war-plugin плагин (exploded цели) в течение package и использования, создавшего каталог как мой исходный каталог приложения. При таком подходе у моего каталога веб-приложений будет /WEB-INF/classes «заполнено» классами. Это, в свою очередь, позволит Tomcat правильно выполнять работу по сканированию (т. Е. Аннотации сервлета @WebServlet будут работать).

Я также должен был изменить источник моего приложения в классе пусковую:

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 

Изменения в POM, которые я добавил - включены maven-war-plugin непосредственно перед appassembler плагин:

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

Обратите внимание, что exploded Цель называется.

Я надеюсь, что небольшое изменение поможет вам.


еще один комментарий на этом учебнике и Maven сборки: обратите внимание, что учебник был написан, чтобы показать, как просто это создать приложение и запустить его в Heroku. Однако это не лучший подход к сборке maven.

Рекомендация Maven заключается в том, что вы должны придерживаться производства одного артефакта на ПОМ. В вашем случае есть два должны артефакты:

  • Tomcat пусковых
  • Tomcat веб-приложение

Оба должно быть строить как отдельный РОМ и ссылки как модули из родительского П. Если вы посмотрите на сложность этого учебника, нет смысла разбить его на два модуля. Но если ваши приложения становятся все более сложными (и пусковая установка получает некоторые дополнительные конфигурации и т. Д.), Это будет иметь большой смысл сделать этот «раскол». По сути, есть некоторые библиотеки «Tomcat launcher», которые уже созданы так, что вы можете использовать один из них.

Смежные вопросы