( ꒪⌓꒪) ゆるよろ日記

( ゚∀゚)o彡°オパーイ!オパーイ! ( ;゚皿゚)ノシΣ フィンギィィーーッ!!!

Slim3をScalaで動かすためのいろいろ

「EXILEはクラウド!」


ではなく、appengine ja night #6 Beer Talk : ATNDで発表した内容です。


Slim3をScalaで動かすためのブランクプロジェクトと、ScalaのController/Serviceを生成するSlim3-gen-scalaを作りました。


yuroyoro/slim3-scala-blank · GitHub
yuroyoro/slim3-gen-scala · GitHub


特徴

やりかた

ブランクプロジェクトをダウンロー丼

とりあえず、JDKScalaGoogle appengine java SDKは入れておいてくださいね☆


まずは、yuroyoro/slim3-scala-blank · GitHubからブランクプロジェクトを取得します。
git cloneで取得するか、"Download Souce"ボタンで圧縮ファイルを取得して転回してください。ディレクトリ名は変えてね?

設定を変えるよ

build.propertiesの中で、Google appengine java SDKScala Homeのパスを環境に合わせて修正してください。

build.properties

# your appengine home
gae.sdk.home=/Users/ozaki/sandbox/GAEJava/sdk/appengine-java-sdk-1.3.1/
# your scala home
scala.home=/Users/ozaki/dev/Scala/scala-2.7.7.final/rt

build.xmlの先頭のプロジェクト名も変えておくとよいでしょう。


build.xml

<project name="slim3-blank" default="gen-controller" basedir=".">


war/WEB-INF/web.xmlのslim3.rootPackageの設定値を、作成するアプリケーションのパッケージ名に修正します。


war/WEB-INF/web.xml

<?xml version="1.0" encoding="utf-8"?>

<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5">
  <context-param>
        <param-name>slim3.rootPackage</param-name>
        <param-value>your.application.pakcage</param-value>
    </context-param>
    <context-param>
        <param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
        <param-value>application</param-value>

...


war/WEB-INF/appengine-web.xmlのアプリケーション名を設定します。

<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
	<application></application>
	<version>1</version>
	
...

いじょ。

自動生成ししてみる


現時点では、Ecipseでの開発環境に対応してません。ScalaEclipse-pluginが残念なためです。ごめんなさい。


なので、コマンドラインからantコマンドを使います。

Controllerの生成

"ant gen-scala-controller"と入力すると、Controllerのパスの入力を促されるので「えいやっ」と入れます(気合い大事)。すると、ScalaのControllerとテストクラスとJSPが生成されます。

ozaki@yuroyoro-MacBook $ ant gen-scala-controller                                 git[master][~/sandbox/.../yuroyoro/test] 
Picked up _JAVA_OPTIONS: -Dfile.encoding=UTF-8
Buildfile: build.xml

gen-scala-controller:
    [input] Input a controller path.
/Foo/
[gen-scala-controller] Generated. ({slim3scala.controller.Foo.IndexController}.scala:0)
[gen-scala-controller] Generated. ({slim3scala.controller.Foo.IndexControllerSpec}.scala:0)
 [gen-view] Generated. (/Users/ozaki/dev/Project/sandbox/scala/yuroyoro/test/war/Foo/index.jsp)

BUILD SUCCESSFUL
Total time: 11 seconds


生成されたController:

package slim3scala.controller.Foo

import org.slim3.controller.Controller
import org.slim3.controller.Navigation

class IndexController extends Controller {

    override def run() =  {
        forward("index.jsp")
    }
}


生成されたテストクラス:

package slim3scala.controller.Foo

import org.specs.Specification
import org.specs.runner._
import org.slim3.tester.ControllerTester

object IndexControllerSpec extends org.specs.Specification {

  val tester = new ControllerTester( classOf[IndexController] )

  "IndexController" should {
    doBefore{ tester.setUp;tester.start("/Foo/")}

    "not null" >> {
      val controller = tester.getController[IndexController]
      controller must notBeNull
    }
    "not redirect" >> {
      tester.isRedirect must beFalse
    }
    "get destination path is /Foo/index.jsp" >> {
      tester.getDestinationPath must_==/ "/Foo/index.jsp"
    }

    doAfter{ tester.tearDown}
  }
}
class IndexControllerSpecTest extends JUnit4( IndexControllerSpec )


JSPは、Java版で出来るものと同じです。
あとは、中身をオラオラ書いていくだけです。

Serviceの生成

"ant gen-scala-service"と入力すると、Serviceクラスのクラス名の入力を促されるので「ふぬいっ」と入れます(勢い大事)。すると、ScalaのServiceクラスとテストクラスが生成されます。

ozaki@yuroyoro-MacBook $ ant gen-scala-service                                    git[master][~/sandbox/.../yuroyoro/test] 
Picked up _JAVA_OPTIONS: -Dfile.encoding=UTF-8
Buildfile: build.xml

gen-scala-service:
    [input] Input a service name. (ex.  FooService -> root.service.FooService,  bar.FooService -> root.service.bar.FooService)
HogeService
[gen-scala-service] Generated. ({slim3scala.service.HogeService}.scala:0)
[gen-scala-service] Generated. ({slim3scala.service.HogeServiceSpec}.scala:0)

BUILD SUCCESSFUL
Total time: 4 seconds


生成されたServiceクラス:

package slim3scala.service


class HogeService {

}


生成されたテストクラス:

ozaki@yuroyoro-MacBook $ cat test/slim3scala/service/HogeServiceSpec.scala        git[master][~/sandbox/.../yuroyoro/test] 
package slim3scala.service

import org.specs.Specification
import org.specs.runner._
import org.slim3.tester.AppEngineTester

object HogeServiceSpec extends org.specs.Specification {
  val tester = new AppEngineTester
  val service = new HogeService

  "HogeService" should {
    doBefore{ tester.setUp}

    "not null" >> {
      service must notBeNull
    }

    doAfter{ tester.tearDown}
  }
}
class HogeServiceSpecTest extends JUnit4( HogeServiceSpec )


あとは、中身をURRRYYYYY!!と書いていくだけです。

テストを実行する

"ant test"とコマンドを打ちます。コンパイルが行われ、テストが実行されます。

test:
     [java] Picked up _JAVA_OPTIONS: -Dfile.encoding=UTF-8
     [java] Specification "/Users/ozaki/dev/Project/sandbox/scala/yuroyoro/test/test/**/*Spec.scala"
     [java]   Specification "IndexControllerSpec"
     [java]     IndexController should
     [java]     + not null
     [java]     + not redirect
     [java]     + get destination path is /Foo/index.jsp
     [java] 
     [java]   Total for specification "IndexControllerSpec":
     [java]   Finished in 0 second, 432 ms
     [java]   3 examples, 3 expectations, 0 failure, 0 error
     [java] 
     [java]   Specification "HogeServiceSpec"
     [java]     HogeService should
     [java]     + not null
     [java] 
     [java]   Total for specification "HogeServiceSpec":
     [java]   Finished in 0 second, 42 ms
     [java]   1 example, 1 expectation, 0 failure, 0 error
     [java] 
     [java] Total for specification "/Users/ozaki/dev/Project/sandbox/scala/yuroyoro/test/test/**/*Spec.scala":
     [java] Finished in 0 second, 498 ms
     [java] 4 examples, 4 expectations, 0 failure, 0 error
     [java] 

BUILD SUCCESSFUL
Total time: 14 seconds


テストはSpecsですので、"IndexController should not null."のようにテストケースが文章っぽくかけて細かく分割できます。ステキですね??

ローカルで動かす

EclipseのGAE pluginで起動できないので、"dev_appserver"コマンドでサーバを起動します。

ozaki@yuroyoro-MacBook $ dev_appserver.sh ./war/                                  git[master][~/sandbox/.../yuroyoro/test] 
Picked up _JAVA_OPTIONS: -Dfile.encoding=UTF-8
Picked up _JAVA_OPTIONS: -Dfile.encoding=UTF-8
2010-03-19 17:10:47.431 java[5406:903] Can't open input server /Library/InputManagers/Inquisitor
2010-03-19 17:10:47.482 java[5406:903] [Java CocoaComponent compatibility mode]: Enabled
2010-03-19 17:10:47.484 java[5406:903] [Java CocoaComponent compatibility mode]: Setting timeout for SWT to 0.100000
2010/03/19 8:10:49 com.google.apphosting.utils.jetty.JettyLogger info
情報: jetty-6.1.x
2010/03/19 8:10:50 com.google.appengine.tools.development.agent.impl.BlackList initBlackList
致命的: Unable to read a jre library while constructing the blacklist. Security restrictions may not be entirely emulated. /System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Home/lib/plugin.jar
Slim3 HOT reloading:true
2010/03/19 8:10:52 com.google.apphosting.utils.jetty.JettyLogger info
情報: Started SelectChannelConnector@127.0.0.1:8080
The server is running at http://localhost:8080/


"ant compilie/test"でコンパイルすれば、HotDeployも出来ます。

この先やること