uoz 作業日記

様々な作業の記録を共有するブログです。

Scala開発環境をOSX yosemiteでつくるぜ (scalatraでなんか作るぜ)

やりたいこと

全くやったこと無いが、関数型言語を使ってみたい。

具体的には、「scalatraでちっちゃいAPIアプリつくる」
ってことにしよう。
ついでにフロントははやりのreactを使ってみよう。これは別記事で。

scalatraっていうのはscalasinatraみたいな感じで、マイクロフレームワークだろう。

最初はclojureでcompojureっていうのを使ってみたかったんだけど、検索してもあんまり出てこなかったから諦めた。

scalaなどインストール

java7のインストール

http://www.oracle.com/technetwork/jp/java/javase/downloads/jdk7-downloads-1880260.html
こっからjdk-7u75-macosx-x64をダウンロード 
実行

java -version

で1.7とかなんとかでたらOK

公式参考
http://www.scalatra.org/2.2/getting-started/installation.html

giter8,sbtのインストール

brew install giter8 
brew install sbt

sbtはビルドツールだって。

giter8はgitからプロジェクトひな形とか取ってくる便利つーるらしい。

参考
http://rkmathi.hatenablog.com/entry/2014/05/25/162308

intellij idea

scala プラグインを入れる

intelij ideaは学生だとタダだしおすすめだ。

起動→configure→plugins→install jetbrains plugin...
scalaを検索ボックスにいれ
install plugin

ためしにscalaでちょっと

なんせscalaなんて使ったこと無いので。

参考
http://www.scala-sbt.org/0.13/tutorial/ja/Hello.html

helloディレクトリ作り、移動して、なんかオブジェクト作ってビルドする

mkdir hello
cd hello
echo 'object Hi { def main(args: Array[String]) = println("Hi!") }' > hw.scala
sbt
Getting org.scala-sbt sbt 0.13.7 ...
downloading https://repo.ty以下略

sbtってやったらなんかいろいろダウンロードし始めた。
終わったら

> run 
[info] Running Hi 
Hi!
[success] Total time: 0 s, completed 2015/04/14 13:32:24

こうやって実行すんのか。
コンソールに入らなくても以下で実行できるらしい

sbt run
[info] Set current project to hello (in build file:/Users/XXXXX/hello/)
[info] Running Hi 
Hi!
[success] Total time: 1 s, completed 2015/04/14 13:33:00

Scalatraのプロジェクトを作る

g8 scalatra/scalatra-sbt 

対話的にプロジェクトを作れる。
またいろいろインストールしてた。
終わったらアプリ名とかいろいろ聞かれた。

g8 scalatra/scalatra-sbt 
organization [com.example]: aoyagiya
name [My Scalatra Web App]: testScalaApp   
version [0.1.0-SNAPSHOT]: 0.0.1
servlet_name [MyScalatraServlet]: testScalaServlet
package [com.example.app]: jp.saizoaoyagi.app
scala_version [2.11.1]: 2.11.1
sbt_version [0.13.5]: 0.13.5
scalatra_version [2.3.0]: 2.3.0

Template applied in ./testscalaapp


公式の流れ通りビルドしてみる。

cd testscalaapp
chmod u+x sbt
./sbt


あとは、最初にできたサーブレットをエディタで開いてみる

vi src/main/scala/jp/saizoaoyagi/app/testScalaServlet.scala
package jp.saizo-aoyagi.app

import org.scalatra._
import scalate.ScalateSupport

class testScalaServlet extends TestscalaappStack {

  get("/") {
    <html>
      <body>
        <h1>Hello, world!</h1>
        Say <a href="hello-scalate">hello to Scalate</a>.
      </body>
    </html>
  }

}


閉じて、以下でwebアプリ立ち上げ

./sbt
> container:start

http://localhost:8080
にアクセスすればなにか見えてOKだ


f:id:uoz:20150414140926p:plain

あと、以下のようにすればファイルを変えると勝手にリロードしてくれるらしい。そうじゃなきゃいちいちビルドすんのはpainfulだって。

./sbt
> container:start
> ~ ;copy-resources;aux-compile

おまけでjson返すように

ここを見ながら、json返すように改造
Scalatra2.2+scalatra-jsonでJSONを処理する | Developers.IO

scalatraが2.3.0でscalaが211.1だったので、
build.scalaに追記する内容がちょっと違った

     libraryDependencies ++= Seq(
        略
        "org.scalatra" %% "scalatra-json" % ScalatraVersion,
        "org.json4s" %% "json4s-jackson" % "3.2.11",
    略

参考
Maven Repository: org.scalatra » scalatra-json_2.10 » 2.3.0

package jp.saizoaoyagi.app

import org.scalatra._
import scalate.ScalateSupport
import org.fusesource.scalate.{ TemplateEngine, Binding }
import org.fusesource.scalate.layout.DefaultLayoutStrategy
import javax.servlet.http.HttpServletRequest
import collection.mutable

trait TestscalaappStack extends ScalatraServlet with ScalateSupport {

  /* wire up the precompiled templates */
  override protected def defaultTemplatePath: List[String] = List("/WEB-INF/templates/views")
  override protected def createTemplateEngine(config: ConfigT) = {
    val engine = super.createTemplateEngine(config)
    engine.layoutStrategy = new DefaultLayoutStrategy(engine,
      TemplateEngine.templateTypes.map("/WEB-INF/templates/layouts/default." + _): _*)
    engine.packagePrefix = "templates"
    engine
  }
  /* end wiring up the precompiled templates */
  
  override protected def templateAttributes(implicit request: HttpServletRequest): mutable.Map[String, Any] = {
    super.templateAttributes ++ mutable.Map.empty // Add extra attributes here, they need bindings in the build file
  }
  

  notFound {
    // remove content type in case it was set through an action
    contentType = null
    // Try to render a ScalateTemplate if no route matched
    findTemplate(requestPath) map { path =>
      contentType = "text/html"
      layoutTemplate(path)
    } orElse serveStaticResource() getOrElse resourceNotFound()
  }
}


case classって書き方について
Scalaクラスメモ(Hishidama's Scala class Memo)


これでサーバ起動して以下にアクセス
http://localhost:8080/json

jsonが返ってきた
f:id:uoz:20150414151528p:plain

intellij idea対応

プロジェクトディレクトリにあるplugins.sbtに
以下を追記

addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.5.2")


以下でOKらしい

./sbt
> gen-idea

Edit configurationsをいじればデバッグも可能

と思ったらintellij ideaのバージョンに追いついてない古いプロジェクト形式になってしまうらしい。

感想

必要なものを勝手にインストールしてくれるのって結構いいな。
環境構築はそんなにめんどくさくなかった。
でも感覚としてはすっげえ時間かかる。