初めてのherokuでJavaデプロイ

herokuを触ってみようとおもって、herokuでjavaを動かそうとトライした時のメモ。

基本はこちらの2つを参考にさせて頂きました。ありがとうございます。

酒浸りの日々
daicham blog

参考にさせて頂いたブログを見ればherokuのへのpushまでは行けます。

で、自分のアプリにアクセスしたところエラー発生。ブラウザの画面には以下のメッセージが。
Application Error
An error occurred in the application and your page could not be served. Please try again in a few moments.
If you are the application owner, check your logs for details.
 おやぁ?
ログを見てみようか…。

$heroku logs
 (中略)
2012-02-21T14:46:17+00:00 heroku[slugc]: Slug compilation finished
2012-02-21T14:46:19+00:00 heroku[web.1]: Starting process with command `sh target/bin/webapp`
2012-02-21T14:46:20+00:00 app[web.1]: Exception in thread "main" java.lang.NoClassDefFoundError: HelloWorld
2012-02-21T14:46:20+00:00 app[web.1]: Caused by: java.lang.ClassNotFoundException: HelloWorld
2012-02-21T14:46:20+00:00 app[web.1]:  at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294)
2012-02-21T14:46:20+00:00 app[web.1]:  at java.lang.ClassLoader.loadClass(ClassLoader.java:266)
2012-02-21T14:46:20+00:00 app[web.1]:  at java.lang.ClassLoader.loadClass(ClassLoader.java:321)
2012-02-21T14:46:20+00:00 app[web.1]:  at java.net.URLClassLoader$1.run(URLClassLoader.java:217)
2012-02-21T14:46:20+00:00 app[web.1]:  at java.security.AccessController.doPrivileged(Native Method)
2012-02-21T14:46:20+00:00 app[web.1]:  at java.net.URLClassLoader.findClass(URLClassLoader.java:205)
2012-02-21T14:46:20+00:00 app[web.1]: Could not find the main class: HelloWorld. Program will exit.
2012-02-21T14:46:21+00:00 heroku[web.1]: Process exited with status 1
2012-02-21T14:46:21+00:00 heroku[web.1]: State changed from starting to crashed

 NoClassDefFoundErrorでてまんがな。
ググるとherokuのDevCenterが引っかかった。
http://devcenter.heroku.com/articles/release-note-java-2011-09-29
内容は…一応訳してみた。
Changes to Java Build Pack, Sep 29 2011
Javaビルドパックへの変更、2011/9/29


What Changed何が変わった?

On Sep 29, Heroku was updated with some changes to how Java applications are built. These changes only affect applications created after Sep 29th. Applications created before this date will continue to behave as they did. This change only impacts how applications are built and deployed. It does not affect running applications in any way.
9/29、herokuはjavaアプリケーションを構築するための変更でアップデートされました。これらの変更は9/29以降に作成されたアプリケーションにのみ影響します。この日付以前に作成されたアプリケーションはそれまでと同様の振る舞いを続けます。この変更はどのようにアプリケーションが構築/デプロイされるかにのみ、影響します。実行中のアプリケーションには決して影響しません。

If you are creating a new application on Heroku and you are using an old guide or an old sample, or if you are destroying and recreating a Java application, these changes may affect you.
もし、あなたが新しいアプリケーションをHerokuで作成し、古いガイド/サンプルを使っている場合、あるいは、javaアプリケーションを破棄して再作成している場合、これらの変更が影響するかもしれません。

If you are experiencing java.lang.ClassNotFoundException or java.lang.NoClassDefFoundError errors or get the error message “sh: mvn: not found” or similar, read on.
もし、あなたが、 java.lang.ClassNotFoundException、java.lang.NoClassDefFoundErrorのエラー、あるいは“sh: mvn: not found”や似たようなエラーメッセージに直面しているのであれば、以下を読んでください。

Before Sep 29th, Heroku included the .m2 Maven cache and the Maven distribution itself (residing in .maven) in your compiled slug. This allowed you to reference jar modules residing in the Maven cache without having to copy them to a target directory or including them in a WAR file. It also allowed you to execute mvn during runtime.
9/29以前、Herokuは、あたなのコンパイルしたslugに.m2 MavenキャッシュとMavenディストリビューション自身(.mavenに備わっている)を含んでいました。これは、Mavenキャッシュに備わっているjarモジュールをtargetディレクトリにコピーする、あるいは、WARファイルにそれらを含める、という必要なく、参照することができるようにしていました。また実行中にmvnを実行することもできるようにしていました。

Applications created after Sep 29th 2011 will no longer include the .m2 cache or Maven itself. It is your responsibility to copy dependencies into a directory such as target during the build process. This is a standard best practice and should not cause any issues to new developers. For example, if you are building a WAR based application and deploying it with Jetty runner using an approach like the one shown in the Spring MVC guide, you will not have any issue.
2011/9/29以降に作成されたアプリケーションにはもう.m2キャッシュやMaven自身は含まれません。依存関係をディレクトリ(targetなど)をビルドプロセス中にコピーすることは、あなたの責務となります。これは普通のベストプラクティスで、新規の開発者にとっては全く問題にならないはずです。例えば、もしあなたがWARベースのアプリケーションを構築していて、Spring MVCガイドに掲載されていた1つのような手法としてJetty runnerを使ってデプロイをしている場合、何も問題はないでしょう。

Similarly, it is not a best practice to use Maven as part of your production configuration since it may introduce unpredictable behavior due to how Maven loads plugins dynamically.
同様に、Mavenが動的にプラグインをロードすることにより、予測できない振る舞いをもたらすかもしれないため、製品構成の一部としてMavenを使うことはベストプラクティスではありません。

Impact on Existing Apps
既存アプリへの影響

The behavior for applications created before Sep 29th have not changed. I.e. if you created your application before Sep 29th and you deploy a change to the application today, the application will get rebuilt with the Maven cache and the Maven executable included in the slug. Therefore, existing applications should continue to work as expected when you deploy changes.
9/29より前に作成されたアプリケーションの振る舞いは変更ありません。例えば、もしあなたがアプリケーションを9/29より以前に作成し、今日変更をデプロイした場合、アプリケーションは実行可能なslugに含まれていたMevenキャッシュとMavenによって再構築されるでしょう。従って、既存アプリケーションは、変更をデプロイした時でも想定通りの動きを継続するはずです。

Benefits
利益


With this change, your compiled slug size will generally be smaller. The more plugins and build time dependencies that you don’t need at runtime, the bigger a difference this will make.
この変更によって、あなたのコンパイルされたslugのサイズはたいてい小さくなります。あなたが実行時には必要としない多くのプラグインとビルド時間の依存関係、これが違いをより大きくします。

Maven App Assembler Plugin
Maven App Assembler プラグイン


The Maven appassembler plugin is a great way to set up an application execution wrapper for your Java application. It supports either referencing dependencies directly in the Maven cache and copying dependencies into a repo directory in target. Because .m2 is not included in the slug and therefore not available at runtime, you must configure the plugin to copy dependencies to your target directory. Fortunately this is the default behavior. But in case you are using sample code or a guide from before Sep 29, make sure you delete the following line in the plugin configuration:
false
Maven appassemblerプラグインはあなたのjavaアプリケーションにとってアプリケーション実行ラッパーをセットアップするためのすばらしい1つの方法です。Mevenキャッシュ内で依存関係を直接参照すること、依存関係をtarget内のrepoディレクトリにコピーすることのいずれの方法もサポートしています。.m2はslugに含まれず、その結果実行時には利用できないことから、あなたはtargetディレクトリに依存関係をコピーするようプラグインを設計しなければなりません。幸いにも、これはデフォルトの振る舞いです。しかし、9/29より前のサンプルコードやガイドを使っている場合、以下の行をプラグイン設定から削除するようにしてください。
false

If you’re in doubt exactly how to configure Maven or you are having trouble getting things to work, you can start over with the simple Getting Started example (with sample code in github and check how it might differ from your own app.
もし、どのようにMavenを設定するかが正直言って疑わしい、あるいは、何かを稼働させるようとしてトラブルに陥っている場合、simple Getting Started exampleでやり直してください。(githubのサンプルコードと、自身のアプリがどのように異なるかをチェックしてください)
うむ、じゃあ.gitignoreを削除して、targetディレクトリ丸ごとgitの管理対象にして、pom.xmlにあるgenerateRepositoryの行を削除してみて※追記参照もう一回gitにcommitして、herokuにpushしたら…。

動いた!

動いたは良いけど…、herokuのslugってなんだ!?と思った今日この頃でした。

追記
こちらのheroku本家に載っていたやり方だと、.gitignoreは必要、pom.xmlの内容が以前と違う、という2点があるので、本家を参考にした方がいいかも…。
http://devcenter.heroku.com/articles/java

コメント

このブログの人気の投稿

ユースケースポイント法(UCP法)

COCOMO(工数と工期)

seleniumをmacで使いたいメモ1