2013-03-05 29 views
7

Cố gắng sửa đổi ứng dụng Java/Tomcat hiện có để triển khai trên Heroku sau tutorial của chúng và chạy vào một số vấn đề với AppAssembler không tìm thấy lớp nhập. Chạy các kết quả target/bin/webapp (hoặc deploying to Heroku) trong Error: Could not find or load main class org.stopbadware.dsp.MainTrình tạo ứng dụng Maven không tìm thấy lớp

Thực thi java -cp target/classes:target/dependency/* org.stopbadware.dsp.Main chạy đúng cách. Dưới đây là phần có liên quan của 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> 

Tôi đoán là mvn package đang gây ra AppAssembler không sử dụng classpath đúng, bất cứ đề nghị?

+0

Bạn có thể cho biết tập lệnh được tạo (.sh/.bat) trông như thế nào không? – khmarbaise

+0

Kịch bản được tạo có thể được nhìn thấy tại http://pastebin.com/f9gbVMgx - lớp Chính không được tìm thấy trong PROJECTROOT/src/org/stopbadware/dsp/ – Exupery

Trả lời

5

của tạo tác của bạn phải được thiết lập để jar, nếu không lớp chính là không tìm thấy.

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

Bản thân tạo tác được thêm vào cuối đường dẫn lớp, vì vậy không có gì ngoài tệp JAR sẽ có hiệu lực.

1

Điều đầu tiên là bạn đang sử dụng phiên bản cũ của appassembler-maven-plugin phiên bản hiện tại là 1,3.

gì tôi không hiểu tại sao bạn xác định thư mục

<assembleDirectory>target</assembleDirectory> 

. Có tồn tại một giá trị mặc định tốt cho điều đó. Vì vậy, thông thường bạn không cần nó. Ngoài ra, bạn không cần phải xác định một thực thi rõ ràng mà giới hạn cho giai đoạn gói, gây ra các appassembler-maven-plugin is by default bound to the package phase.

Ngoài ra, bạn có thể sử dụng tùy chọn cấu hình useWildcardClassPath để làm cho đường dẫn lớp của bạn ngắn hơn.

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

Và rằng sự kêu gọi của kịch bản được tạo ra hiển thị lỗi là tùy thuộc vào điều mà vị trí của kho nơi mà tất cả các phụ thuộc nằm trong thư mục khác với trong kịch bản được tạo ra định nghĩa.

+0

Đây là trải nghiệm đầu tiên của tôi với AppAssembler vì vậy tôi đã sử dụng Heroku đã có trong hướng dẫn đã đề cập trước đó. Sử dụng 1.3, loại bỏ các thư mục và thực hiện tài liệu tham khảo, và thêm vào các tùy chọn ký tự đại diện không có hiệu lực, vẫn nhận được cùng một lỗi. Rõ ràng khi xây dựng kịch bản, nó không tạo ra classpath đúng và đáng buồn là tài liệu AppAssembler khá hạn chế và không xuất hiện để chỉ ra cách thêm một cách rõ ràng vào classpath đã tạo ra. – Exupery

+0

Cách tốt nhất là đặt một dự án mẫu (với pom.xml) lên [jira] (https://jira.codehaus.org/browse/MAPPASM) và tạo ra một vấn đề hoặc chỉ gửi cho tôi tệp pom.xml một cách riêng tư tôi có thể xem xét vấn đề của bạn. – khmarbaise

+0

Bạn có thể xem tệp pom.xml tại http://pastebin.com/11WmjBmB - tập lệnh tạo ứng dụng được đặt tại http://pastebin.com/f9gbVMgx và các hàm hoạt động khi mục PROJECTROOT/target/classes bị thiếu trong đường dẫn lớp bị thiếu cố định bằng cách thêm '" $ BASEDIR "/ classes' – Exupery

1

Có thể giải quyết vấn đề này bằng cách thêm "$BASEDIR"/classes vào dòng CLASSPATH trong tập lệnh được tạo. Kể từ khi kịch bản được viết lại trên mỗi cuộc gọi của mvn package Tôi đã viết một kịch bản ngắn gọi mvn package và sau đó thêm mục nhập classpath cần thiết.

Rõ ràng là một chút hack nhưng sau hơn 8 giờ thử một giải pháp "thích hợp" hơn, điều này sẽ phải làm ngay bây giờ. Sẽ chắc chắn giải trí bất kỳ cách thanh lịch hơn của sửa chữa classpath đề nghị ở đây.

3

Hãy thử: bao bì

mvn clean package jar:jar appassembler:assemble 
+2

Điều đó hoạt động tốt trên máy cục bộ của tôi, nhưng không được triển khai cho Heroku một lần nữa. Từ những gì tôi có thể thấy không có cách nào để thay đổi lệnh maven của Heroku từ mặc định của 'mvn clean install' (thêm' jar: jar appassembler: assemble' thành MAVEN_OPTS không có hiệu lực). – Exupery

1

Bạn có thể thiết lập các biến môi trường CLASSPATH_PREFIX:

export CLASSPATH_PREFIX=target/classes 

đó sẽ được thêm vào phía trước classpath của kịch bản tạo ra.

1

Tôi đã trải qua hướng dẫn đó một thời gian trước và có vấn đề rất giống nhau. Tôi đến với một cách tiếp cận khác nhau một chút mà làm việc cho tôi rất độc đáo.

Trước hết, vì nó đã được đề cập trước đó, bạn cần phải giữ loại của POM của bạn như jar (<packaging>jar</packaging>) - nhờ đó, appassembler plugin sẽ tạo ra một tập tin JAR từ lớp học của bạn và thêm nó vào classpath. Vì vậy, nhờ đó, lỗi của bạn sẽ biến mất.

Xin lưu ý rằng hướng dẫn này Tomcat được khởi tạo từ thư mục nguồn ứng dụng. Trong nhiều trường hợp là đủ, nhưng xin lưu ý rằng bằng cách sử dụng phương pháp đó, bạn sẽ không thể sử dụng chú thích Servlet @WebServlet dưới dạng /WEB-INF/classes trong nguồn trống và Tomcat sẽ không thể quét các lớp servlet của bạn. Vì vậy, HelloServlet servlet từ hướng dẫn đó sẽ không hoạt động, trừ khi bạn thêm một số khởi tạo Tomcat bổ sung (cấu hình tài nguyên) như được mô tả here (BTW, bạn sẽ tìm thấy nhiều câu hỏi SO nói về cấu hình tài nguyên đó).

tôi đã làm một chút cách tiếp cận khác nhau:

tôi chạy một org.apache.maven.plugins:maven-war-plugin plugin (exploded khung thành) trong package và sử dụng mà tạo thư mục như thư mục nguồn của tôi của ứng dụng. Với cách tiếp cận đó, thư mục ứng dụng web của tôi sẽ có /WEB-INF/classes "được điền" với các lớp. Điều đó sẽ cho phép Tomcat thực hiện công việc quét chính xác (nghĩa là các chú thích Servlet @WebServlet sẽ hoạt động).

Tôi cũng đã phải thay đổi nguồn cung cấp ứng dụng của tôi trong lớp 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 

Changes để POM mà tôi thêm vào - bao gồm maven-war-plugin ngay trước 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> 
... 

Xin lưu ý rằng Mục tiêu exploded được gọi.

Tôi hy vọng rằng thay đổi nhỏ sẽ giúp ích cho bạn.


Một lưu ý khác về hướng dẫn đó và xây dựng maven: lưu ý rằng hướng dẫn được viết đơn giản là xây dựng ứng dụng và chạy ứng dụng đó trong Heroku. Tuy nhiên, đó không phải là cách tiếp cận tốt nhất để xây dựng maven.

Đề nghị Maven là bạn nên tuân thủ để sản xuất một tạo phẩm cho mỗi POM. Trong trường hợp của bạn có nên hai hiện vật:

  • Tomcat launcher
  • Tomcat ứng dụng web

Cả hai nên xây dựng POMs như riêng biệt và tham chiếu như module từ cha mẹ của bạn POM. Nếu bạn nhìn vào sự phức tạp của hướng dẫn đó, nó không có ý nghĩa nhiều để chia thành hai mô-đun. Nhưng nếu các ứng dụng của bạn ngày càng phức tạp hơn (và trình khởi chạy nhận được một số cấu hình bổ sung, vv), nó sẽ tạo ra rất nhiều ý nghĩa để làm cho "sự phân chia" đó. Như một vấn đề của thực tế, có một số "Tomcat launcher" thư viện đã được tạo ra để bạn có thể sử dụng một trong số họ.

Các vấn đề liên quan