Skip to content

Instantly share code, notes, and snippets.

@hayajo
Created April 4, 2016 08:21
Show Gist options
  • Save hayajo/e30595ea4135b375d3bb27dc24438763 to your computer and use it in GitHub Desktop.
Save hayajo/e30595ea4135b375d3bb27dc24438763 to your computer and use it in GitHub Desktop.
Server::StarterでJavaのWebアプリを起動する

Server::StarterでJavaのWebアプリを起動する

Scalatraで作成されJettyを組み込んだ実行可能なjarをServer::Starterで実行して、ホットデプロイを可能にするまでの簡単な手順です。

これにより、クラスローダーを利用した運用からLLと同様な形態でアプリケーションを運用することが可能となります(アプリケーションごとにJVMプロセスを起動する)。

環境構築

JDKのインストール

Scala 2.11.x のJDK8サポートが実験的とのことなので、JDK7をインストールします。

$ java -version

giter8のインストール

giter8はn8han氏が開発しているScalaベースのツールで、Githubのリポジトリに登録されているテンプレートからプロジェクトを生成するためのものです。 Scala界隈ではビルドツールとしてsbtが一般的に利用されていますが、sbtはMavenのようなライブラリ管理機能は持っているものの、Mavenのアーキタイプのようにプロジェクトの雛形を生成するための機能は備えていません。giter8はこの部分を補完してくれるツールといえます。 ただし、giter8をインストールするにはconscriptというツールが必要になります。 conscriptもgiter8と同じくn8han氏が開発しているもので、こちらはGithubからScalaベースのソフトウェアのインストールを行うためのものです。 どちらのツールもGithubそのものをリポジトリと見なしているのが面白いところですね。

Conscriptのインストール

$ curl https://raw.githubusercontent.com/n8han/conscript/master/setup.sh | sh
$ echo 'export PATH=$HOME/bin:$PATH' >> ~/.bashrc
$ source ~/.bashrc

giter8のインストール

$ cs n8han/giter8

Scalatraプロジェクトの作成

$ g8 scalatra/scalatra-sbt
organization [com.example]: 
name [My Scalatra Web App]: 
version [0.1.0-SNAPSHOT]: 
servlet_name [MyScalatraServlet]: 
package [com.example.app]: 
scala_version [2.11.7]: 
sbt_version [0.13.9]: 
scalatra_version [2.4.0]: 

Template applied in ./my-scalatra-web-app
$ cd ./my-scalatra-web-app
$ chmod +x sbt

プロジェクトのビルドと実行

$ ./sbt
> jetty:start
... # exitで終了
$ curl localhost:8080

実行可能jarの作成

準備

プロジェクトにstb-assemblyプラグインを追加

実行可能jarを作成するためにsbt-assemblyプラグインを追加します。

$ echo 'addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.2")' >> project/plugins.sbt

build.scalaのjetty-webappライブラリにcompileディレクティブを追加

$ sed -i -E 's/("jetty-webapp" % .* %) "container"/\1 "container;compile"/' project/build.scala

ランチャの作成

jarのMain-Classとなるアプリケーションランチャを作成します(src/main/scala/JettyLauncher.scala)。 このランチャでJettyを起動します。

package com.example  // remember this package in the sbt project definition
import org.eclipse.jetty.server.{Server, ServerConnector}
import org.eclipse.jetty.servlet.{DefaultServlet, ServletContextHandler}
import org.eclipse.jetty.webapp.WebAppContext
import org.scalatra.servlet.ScalatraListener

object JettyLauncher { // this is my entry object as specified in sbt project definition
  def main(args: Array[String]) {
    val port = if(System.getenv("PORT") != null) System.getenv("PORT").toInt else 8080

      val server = new Server()

      val connector = new ServerConnector(server)
      connector.setInheritChannel(true) // Server::Starter対応(STDINがソケット)
      connector.setPort(port)

      server.setConnectors(Array(connector))

      val context = new WebAppContext()
      context.setContextPath("/")
      context.setResourceBase("src/main/webapp")
      context.addEventListener(new ScalatraListener)
      context.addServlet(classOf[DefaultServlet], "/")

      server.setHandler(context)

      server.start
      server.join
  }
}

jarの作成

$ ./sbt clean assembly

jarの実行

作成したjarを実行してみます。

$ find . -name '*-assembly-*.jar' | xargs -L1 -I@ java -jar @
... # Ctrl-C で終了
$ curl localhost:8080

Server::Starterのインストール

Server::Starterをインストールします。

cpanmのインストール

ビルド関連ツール(gcc, make, etc.)が不足している場合は適宜インストールしてください。

$ curl -L https://cpanmin.us | perl - App::cpanminus

Server::Starterのインストール

$ cpanm Server::Starter

jarの実行(Server::Starter経由)

$ MY_WEB_APP_JAR=$(find . -name '*-assembly-*.jar' | head -n1)
$ start_server \
--log-file=start_server.log \
--daemonize \
--pid-file=start_server.pid \
--port=8080=0 \
java -- -jar "$MY_WEB_APP_JAR"
$ curl localhost:8080

再起動

$ start_server --pid-file=start_server.pid --restart

停止

$ start_server --pid-file=start_server.pid --stop

まとめ

これでクラスローダーとか使わずにLLと同じような運用ができるね!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment