eclipse+Jetty開発環境の作成
Herokuに手を出してからというものの、eclipse+Jettyで開発することが多くなりました。
JettyのおもしろいところはAPIを使って起動用クラスを作ることで、普通のJavaアプリとして起動できることです。
これが便利なところは
などですかね。
同じことはGlassfishでも出来るんですが、Jettyは依存JARが少なくサイズが小さいのでお手軽ですし、GlassfishはAPIが安定していなくって起動用クラスの作成に苦労するんですよね。
そんなわけで今回はeclipse+Jettyのお手軽開発環境を構築する手順をまとめてみました。
例として「sample-web」というプロジェクトを作ってみましょう。
eclipseとMavenを連携させるための準備
コマンドラインで次のコマンドを実行します。
mvn -Declipse.workspace=<eclipseのworkspaceのパス> eclipse:add-maven-repo
このコマンドでM2_REPOという変数がeclipseに作られます。
ですのであるworkspaceに対して一度だけ実行すればOKです。
作業フォルダに移動
コマンドラインで次のコマンドを実行します。
cd <eclipseプロジェクトを置くフォルダ>
eclipseプロジェクトを置くフォルダは、通常だとworkspaceと同じ場所が多いでしょう。
プロジェクトの原型作成
コマンドラインで次のコマンドを実行します。
mvn archetype:create -DgroupId=jabara -DartifactId=sample-web -DarchetypeArtifactId=maven-archetype-webapp
groupIdには適当な名前を指定して下さい。
このコマンドでsample-webディレクトリが作られ、その中にpom.xmlが作られます。
プロジェクトにJetty設定追加
pom.xmlを好きなエディタで開いて
<!-- 組み込みJettyの実行に必要 --> <dependency> <groupId>org.eclipse.jetty.aggregate</groupId> <artifactId>jetty-all-server</artifactId> <version>8.1.4.v20120524</version> </dependency> <dependency> <groupId>org.mortbay.jetty</groupId> <artifactId>jsp-2.1-glassfish</artifactId> <version>2.1.v20100127</version> </dependency> <!-- 組み込みJettyにServletAPI3.0のアノテーションを解釈させるために必要 --> <dependency> <groupId>asm</groupId> <artifactId>asm-commons</artifactId> <version>3.3.1</version> </dependency>
プロジェクトのJavaのバージョンを6にする
pom.xmlの
<plugins> <plugin> <inherited>true</inherited> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.3.2</version> <configuration> <source>1.6</source> <target>1.6</target> </configuration> </plugin> </plugins>
バージョンを7にしたい場合は「1.6」を「1.7」すればOKです。
eclipseプロジェクトの設定を追加
コマンドラインで次のコマンドを実行します。これでeclipseにインポートできるようになります。
mvn eclipse:eclipse
初回はいろんなライブラリをダウンロードするので時間がかかります
プロジェクトをeclipseにインポート
eclipseを起動し、メニューの「ファイル」→「インポート」→「既存プロジェクトをワークスペースへ」を使ってsample-webフォルダをインポートします。
詳しい手順は次のサイトを参考にして下さい。
http://www.javadrive.jp/eclipse3/project/index4.html
ソースフォルダを作成
なぜかソースフォルダが足りません。これではJettyの起動用クラスを作れないので、作成します。
「src/main/java」フォルダをソースフォルダとして作成して下さい。
デフォルト出力フォルダの変更
mvnの設定をそのまま使うと@WebServlet(など)の付いたクラスを自動的で探す機能が動作しません。
そこで「sample-web/src/main/webapp/WEB-INF/classes」に変更します。
なお、この設定は
mvn eclipse:eclipse
コマンドを実行する度に施す必要があります。依存ライブラリを追加したときなど、このコマンドを実行することはよくあります。その時にこの設定を忘れるとWebアプリが動作しなくなるので、注意が必要です。
もっと良い方法がきっとあると思うのですが、まだ調べがついていません。
ここまでの設定のスクリーンショットです。
Jetty起動用クラス作成
src/main/java直下に次のクラスを作ります。
import org.eclipse.jetty.annotations.AnnotationConfiguration; import org.eclipse.jetty.plus.webapp.EnvConfiguration; import org.eclipse.jetty.plus.webapp.PlusConfiguration; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.webapp.Configuration; import org.eclipse.jetty.webapp.FragmentConfiguration; import org.eclipse.jetty.webapp.MetaInfConfiguration; import org.eclipse.jetty.webapp.TagLibConfiguration; import org.eclipse.jetty.webapp.WebAppContext; import org.eclipse.jetty.webapp.WebInfConfiguration; import org.eclipse.jetty.webapp.WebXmlConfiguration; /** * @author jabaraster */ public class SampleWebStarter { /** * @param pArgs - * @throws Exception - */ public static void main(final String[] pArgs) throws Exception { final int port = getWebPort(); final String webappDirLocation = "src/main/webapp/"; //$NON-NLS-1$ final Server server = new Server(port); final WebAppContext context = new WebAppContext(); context.setConfigurations(new Configuration[] { // new AnnotationConfiguration() // , new WebXmlConfiguration() // , new WebInfConfiguration() // , new TagLibConfiguration() // , new PlusConfiguration() // , new MetaInfConfiguration() // , new FragmentConfiguration() // , new EnvConfiguration() // }); context.setContextPath("/"); //$NON-NLS-1$ context.setDescriptor(webappDirLocation + "/WEB-INF/web.xml"); //$NON-NLS-1$ context.setResourceBase(webappDirLocation); context.setParentLoaderPriority(true); server.setHandler(context); server.start(); server.join(); } private static int getWebPort() { final String webPort = System.getenv("PORT"); //$NON-NLS-1$ if (webPort == null || webPort.isEmpty()) { return 8080; } return Integer.parseInt(webPort); } }
ポートの決定には一工夫しています。
Herokuで動作させることを考慮し、環境変数PORTを見るようにしています。もし環境変数PORTが空なら、8080を決め打ちで使います。
なおクラスのpackage宣言を省略している(default packageに所属させている)のには深い意味はありません。
Jetty起動
SampleWebStarterをeclipseから起動します。
1秒くらいで起動します。速い。
Servletを作ってみる
ついでにServletAPI3.0を使ってServletを作ってみましょう。
src/main/javaの下に次のJavaクラスを作ります。
package servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet(urlPatterns={"/sample"}) public class SampleServlet extends HttpServlet{ protected void doGet(final HttpServletRequest pReq, final HttpServletResponse pResp) throws ServletException, IOException { pResp.setContentType("text/plain"); pResp.getWriter().print("Hello World!"); } }
もしこのServletのソースに「Syntax error, annotations are only available if source level is 1.5 or greater」というエラーが起きた場合、「プロジェクトのJavaのバージョンを6にする」の手順の設定を追加して下さい。