CLOVER🍀

That was when it all began.

sbt 0.10でサーブレットプログラミングにトライ

注意)この記事は、sbt 0.10とxsbt-web-plugin 0.1系の組み合わせです。
xsbt-web-plugin 0.2系では動作しませんので、ご注意ください。

今度は、sbtでサーブレットプログラミング。その前にコマンドとか基本的なことをまとめた方がいいような気がするのですが、今は遊んでみたいのでそちら優先で(笑)。

まずはプロジェクト作成。

$ mkdir hello-servlet
$ cd hello-servlet
$ sbt
Getting net.java.dev.jna jna 3.2.3 ...
:: retrieving :: org.scala-tools.sbt#boot-app
	confs: [default]
	1 artifacts copied, 0 already retrieved (838kB/26ms)
Getting Scala 2.8.1 (for sbt)...
:: retrieving :: org.scala-tools.sbt#boot-scala
	confs: [default]
	4 artifacts copied, 0 already retrieved (15296kB/133ms)
Getting org.scala-tools.sbt sbt_2.8.1 0.10.0 ...
:: retrieving :: org.scala-tools.sbt#boot-app
	confs: [default]
	34 artifacts copied, 0 already retrieved (6012kB/119ms)
[info] Set current project to default (in build file:/xxxxx/hello-servlet/)
>

一度sbtを抜けて、build.sbtを作成。

name := "Hello Servlet"

version := "1.0.0"

scalaVersion := "2.9.0"

organization := "littlewings"

libraryDependencies ++= Seq(
  "javax.servlet" % "servlet-api" % "2.5" % "provided",
  "org.mortbay.jetty" % "jetty" % "6.1.26" % "jetty"
)

が、sbtのページにこの後すべきなWebProjectの作成方法とかが書いてありません。まあ、ものは試しとこの状態でjetty-runコマンドを実行してみると…。

$ sbt
Getting Scala 2.9.0 ...
:: retrieving :: org.scala-tools.sbt#boot-scala
	confs: [default]
	4 artifacts copied, 0 already retrieved (20442kB/175ms)
[info] Set current project to default (in build file:/xxxxx/hello-servlet/)
> jetty-run
[error] Not a valid command: jetty-run
[error] Not a valid project ID: jetty-run
[error] Not a valid configuration: jetty-run
[error] Not a valid key: jetty-run (similar: run)
[error] jetty-run
[error]

そんなものないよと怒られます。やっぱりそうですか。

ここで、sbt 0.7系から0.10系へのマイグレーションについてのページを見ると…
https://github.com/harrah/xsbt/wiki/Migrating-from-SBT-0.7.x-to-0.10.x

What happened to the web development and Web Start support?

Web application support was split out into a plugin. See the xsbt-web-plugin project.

Webアプリケーションサポートは、プラグインに分割しちまったんですと。「xsbt-web-plugin」を見よ、とな。

では、xsbt-web-pluginを見てみましょうか。
https://github.com/siasia/xsbt-web-plugin

一応やり方は書いてあるので、手順に従ってやってみましょう。まずは「project/plugins」ディレクトリを作成し、その配下に「build.sbt」を作成します。

$ mkdir project/plugins
$ cat project/plugins/build.sbt 
resolvers += "Web plugin repo" at "http://siasia.github.com/maven2"

libraryDependencies <+= sbtVersion(v => "com.github.siasia" %% "xsbt-web-plugin" % ("0.1.0-"+v))

次に、大元のbuild.sbtに設定の追加を行います。

name := "Hello Servlet"

version := "1.0.0"

scalaVersion := "2.9.0"

organization := "littlewings"

seq(webSettings: _*)

libraryDependencies ++= Seq(
  "javax.servlet" % "servlet-api" % "2.5" % "provided",
  "org.mortbay.jetty" % "jetty" % "6.1.26" % "jetty"
)

ここが追加点です。

seq(webSettings: _*)

では、sbtでreload。

> reload
[info] Set current project to default (in build file:/xxxxx/hello-servlet/project/plugins/)
[info] Set current project to default (in build file:/xxxxx/hello-servlet/)

なお、この時点でjetty-runコマンドが見えるようになっています。

> jetty-run
[info] Updating...
[info] Done updating.
2011-07-10 21:48:07.711:INFO::Logging to STDERR via org.mortbay.log.StdErrLog
[info] jetty-6.1.26
[info] NO JSP Support for /, did not find org.apache.jasper.servlet.JspServlet
[info] Started SelectChannelConnector@0.0.0.0:8080

まあ、サーブレットとか置いてないから、見るものないんですけどね…。

では、web.xmlとサーブレットを作りましょう。まずはディレクトリ作成。

$ mkdir -p src/main/webapp/WEB-INF/
$ mkdir -p src/main/scala

これ、ホントに手でやらねばならんのでしょうか…?

作成したServlet。

package littlewings.hello.servlet

import javax.servlet.http.{HttpServlet, HttpServletRequest, HttpServletResponse}

class HelloServlet extends HttpServlet {
  override protected def doGet(request: HttpServletRequest, response: HttpServletResponse): Unit = {
    response.getWriter.write("Hello Servlet")
  }
}

web.xml。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5">
  <display-name>Hello Simple Web Application</display-name>

  <servlet>
    <servlet-name>HelloServlet</servlet-name>
    <servlet-class>littlewings.hello.servlet.HelloServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>HelloServlet</servlet-name>
    <url-pattern>/hello</url-pattern>
  </servlet-mapping>
</web-app>

それでは、Jettyを起動してみましょう。

> jetty-run
[info] Updating...
[info] Done updating.
[info] Compiling 1 Scala source to /xxxxx/hello-servlet/target/scala-2.9.0.final/classes...
2011-07-10 21:57:26.445:INFO::Logging to STDERR via org.mortbay.log.StdErrLog
[info] jetty-6.1.26
[info] NO JSP Support for /, did not find org.apache.jasper.servlet.JspServlet
[info] Started SelectChannelConnector@0.0.0.0:8080

動作確認。

$ telnet localhost 8080
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
GET /hello
Hello ServletConnection closed by foreign host.

うん、動いていますね。

sbtを利用する場合は、Jettyを再起動しなくても結果が確認できるところが素敵です。ちょっとソースを修正してみます。

package littlewings.hello.servlet

import javax.servlet.http.{HttpServlet, HttpServletRequest, HttpServletResponse}

class HelloServlet extends HttpServlet {
  override protected def doGet(request: HttpServletRequest, response: HttpServletResponse): Unit = {
    response.getWriter.write("Hello My Servlet")
  }
}

いや、あんまり変わってませんが…。

続いてsbtで、prepare-webappコマンドを実行します。

> prepare-webapp
[info] Compiling 1 Scala source to /xxxxx/hello-servlet/target/scala-2.9.0.final/classes...
[success] Total time: 1 s, completed Jul 10, 2011 10:00:08 PM
[info] Reloading web application...
> [info] NO JSP Support for /, did not find org.apache.jasper.servlet.JspServlet
[info] Reload complete.

再度確認。

$ telnet localhost 8080
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
GET /hello
Hello My ServletConnection closed by foreign host.

返ってくるメッセージが変わりましたね!

追記)
WARファイルの作り方は、次のエントリを参照してくださいね。