Scala入門記013 sbt newテンプレート
こんにちは。
珍しく短い間隔でBlogを書いてます。
まだ海には行けていないくらいです。
前回はsbt newについて書きましたが、Myテンプレートを持つのが良さそう、と書きました。
Myテンプレートを持つためにはまずは簡単なテンプレートの作り方を覚えてそれを成長させていくのが良いと思います。
ということで、最もシンプルなテンプレートを作ってみました。
Scala入門記の目次はこちらです。
今回作るテンプレート
テンプレートの名前は.g8のサフィックスが必要なので、今回はscala-helloworld.g8と名前をつけます。
このテンプレートでは
Scala入門記006 sbt + ScalaTest - うさばかSE Blog3
で紹介したプロジェクトを生成できるようになります。
ルール
詳しくはドキュメント読めばいいので最低限と思われるものを紹介します。
ライセンス
ドキュメントでCC0を使えと言われているのでREADME.mdで示してみました。
ファイルの配置場所
Giter8のファイルはsrc/main/g8に配置するのが良いです。
こうすることでローカルでテンプレートをテストできるようになります。
プロジェクトフィールド
プロジェクトを生成する際にパラメータを指定可能にするプロジェクトフィールドと言う仕組みがあります。
パラメータはdefault.propertiesに書くと、テンプレート内で$name$という形で使えるようになります。
パッケージ名はディレクトリ階層にいい感じで変わってくれたりもしてすごく便利です。
他にもCamelCaseなどに置き換えたい場合もかんたんに指定できるようになっています。
詳しくはこちらのドキュメントを見ると困ることはないでしょう。
Giter8 — テンプレートフィールドのフォーマット
テンプレートを作る
今回はシンプルに以下の構成でファイルを作りました。
scala-helloworld.g8/README.md scala-helloworld.g8/src/main/g8/build.sbt scala-helloworld.g8/src/main/g8/default.properties scala-helloworld.g8/src/main/g8/src/main/scala/$package$/$classname$.scala scala-helloworld.g8/src/main/g8/src/test/scala/$package$/$classname$Spec.scala
各ファイル内容は載せると冗長なのでこちらをご確認ください。
github.com
ローカルでテスト
テンプレートができたらgithubなどにpushする前に正しく動作するかテストできます。
これはsrc/main/g8にテンプレートを作った場合の特権です。
テスト
sbt-helloworld.g8のあるフォルダで以下のコマンドを呼べばテストできます。
sbt new file://scala-helloworld.g8
うまくいかない場合はフルパスで書くと良いです。
sbt new file:///path/to/scala-helloworld.g8
今回のテンプレートであれば以下のようにプロジェクトの情報を聞かれます。
name [Scala HelloWorld]: classname [Greeting]: package [com.example]: scalaVersion [2.12.2]: applicationVersion [0.1.0-SNAPSHOT]:
とりあえずEnter連打で試して動作確認し、全部変えてみて試す感じが良いと思います。
今回のプロジェクトはmainクラスとScalaTestのSpecが出力されるので、生成されたプロジェクトに入って
sbt test
でテストが通ることを確認し、
sbt run
で動作確認ができます。
このあたりの詳細は
Scala入門記006 sbt + ScalaTest - うさばかSE Blog3
をご確認ください。
リポジトリにPush
動作が確認できればGitHubなどにPushします。
BitbucketにPush
GitHub以外はリポジトリをフルパスで指定することで利用できます。
今回はBitbucketで試しましたが、Bitbuketのリポジトリは
HTTPSは
https://bitbucket.org/thachi/scala-helloworld.g8.git
SSHは
git@bitbucket.org:thachi/scala-helloworld.g8.git
です。
sbt newで指定する場合は最後の.gitは省いて
sbt new https://bitbucket.org/thachi/scala-helloworld.g8
や
sbt new git@bitbucket.org:thachi/scala-helloworld.g8
とすることで指定ができます。
Bitbucketは無料で非公開なリポジトリも作れるので、公開しないライブラリを使う場合はこちらにテンプレートを置くと便利ですね。
まとめ
sbt newのテンプレートはgiter8のテンプレートを作ればそれが使えます。
src/main/g8にファイルを作り、プロジェクトフィールドを駆使して思い通りのプロジェクトが生成できるようにテンプレートを作ります。
そして、テンプレートができたらローカルでテストして動作確認し、最後にGitHubやBitbucketなどのgitリポジトリにPushして、利用可能にします。
今回は簡単なテンプレートを作りましたが要点は押さえていると思います。
みなさんも、Myテンプレートで素敵なsbt newライフを始めてみてはいかがでしょうか。
Scala入門記の目次はこちらです。
Scala入門記012 sbt new
こんにちは。
北海道にも短い夏がやってきました。
暑いうちに海に行ってバーベキューしたいですね。
さて、「Scalaを書こうかな」と思ってsbtプロジェクトを作るとき、build.sbtを書きますよね。
新しくファイルを追加して基本的な設定をコピペして、いつも使うプラグインを追加してプロジェクトの設定をし、設定が済んだらやっとコードを書き始めたりしているかもしれません。
そんな決まりきったプロジェクトの形をテンプレートとして公開し、テンプレートから新規にプロジェクトを作れるためのgiter8という仕組みがあります。
JavaプログラマにとってはMavenのarchetypeと同様のものだと考えて良いと思います。
このgiter8の使い方を前から書こうと思っていたのですが、これがsbt0.13.13に公式に取り込まれてとても簡単に利用できるようになっていました。
今日はこの"sbt new"の使い方をまとめたいと思います。
Scala入門記の目次はこちらです。
sbt newについて
公式のドキュメントは http://www.scala-sbt.org/0.13/docs/ja/Hello.html です。
ドキュメントにある通り、sbt newはsbtの0.13.13以降が必要です。
新しく何かをインストール必要はなく、最新のsbtを使うだけで良くなったのはとっても楽ですね。
sbt newをまずは使う
何をするにもまずは使うことが大切です。
さっそくsbt newを使ってみます。
sbt newを呼ぶ
sbt newの使い方は簡単です。
コマンドラインで適当なディレクトリに移動し、
sbt new sbt/scala-seed.g8
と入力すると
name [My Something Project]:
プロジェクト名を聞かれます。
ここではこれに対して
name [My Something Project]: sbt-new-project
と入力してEnterを押すと以下のようなプロジェクトができました。
$ find sbt-new-project -type f sbt-new-project/build.sbt sbt-new-project/project/build.properties sbt-new-project/project/Dependencies.scala sbt-new-project/src/main/scala/example/Hello.scala sbt-new-project/src/test/scala/example/HelloSpec.scala
上の3が設定ファイル、Hello.scalaがサンプルの実装、HelloSpec.scalaがサンプルのユニットテストですね。
project/Dependencies.scalaに依存関係が書いてありますね。
もしかしたら、こうやって分けて書くのが推奨されているのかもしれません。
できたプロジェクトを実行してみる
実行は
cd sbt-new-project
でプロジェクトのディレクトリに入って
sbt run
ですね。
ログがそこそこ出て、helloと表示されました。
$ sbt run (省略) hello
あとは好きなようにプログラムを書けばokですね。
テンプレートについて
今回使った sbt/scala-seed.g8 のテンプレートはもっともシンプルなものなのでこれだと自分で作っても対して変わらないです。
実用的なテンプレートはどうしたら良いでしょう。
PlayFrameworkの場合
ScalaのフレームワークであるPlayFrameworkも以前はTypesafe Activatorというツールでプロジェクトを生成していたところが、今ではsbt newを使うようになっています。
※2.5系からみたいです。
詳しくはこちら。
https://www.playframework.com/documentation/2.6.x/NewApplication
他のテンプレートは?
まずは、使いたいプロダクトがテンプレーとを提供しているか確認ですね。
でも、githubでプロジェクトを探してみるのが早い気がしました。
https://github.com/search?l=Scala&q=.g8&type=Repositories
PlayFramworkのテンプレートもすぐ見つかります。
https://github.com/search?utf8=%E2%9C%93&q=.g8+playframework&type=Repositories
まとめ
sbt 0.13.13以降ではgiter8が取り込まれて、sbt newでテンプレートからプロジェクトが簡単に作れます。
テンプレートは探せば用意されているかもしれませんが、ない場合は自分で作ったりもできます。
ということで次回はsbt newのテンプレートについて記事にしようと思います。
Scala入門記の目次はこちらです。
小学生にプログラミングを教えてきました
11/3の祝日に4,5,6年生を対象として豊沼小学校PTA主催のプログラミング教室を行ってきました。
最近都会では子ども向けのプログラミング教室が結構あるみたいです。
人口の少ない私の住む街でも子どもにはいろいろな可能性を知ってもらいたいと思って講師を引き受けました。
今回体験に来たのは9人で、1人で教えるにはちょうどいい人数でした。
内容
今回はScratchでブロック崩しを作ることで、プログラミングを体験してもらいました。
作り方は、基本的に私がスクリーン上でプログラムを組み立てるのを見よう見まねで操作していく流れです。
ブロック崩しは教えやすく、1時間半の時間で全員がブロック崩しを作ることができました。
中には教室の後も残ってプログラムを改造する子もでてきたりと、かなり楽しんでくれたようで大成功だったのではないかと思います。
ボールを増やしたり、ブロックを増やしたり、変な動きをする邪魔キャラを追加したり、大笑いしながらプログラミングを楽しんでいました。
アンケート結果
教室の後にとったアンケートの一部です。
難しかったと回答しているのは4年生だったのですが、最後まで残ってプログラミングを楽しんでいたのも4年生でした。
全員が「また参加したい」と回答してくれたのはとても嬉しかったです。
まとめ
今回はプログラミングがまったく初めての子に体験させることが目的でした。
今後は興味を持った子に何度かに分けて自分の好きなゲームを作れるくらいは教えてあげたいとは考えています。
私が作ったブロック崩し
Scratchでどのくらい作れるのか試しに作ってみたブロック崩しです。
1日もあればこれくらい作れるので、作り込めばかなりの物が作れそうです。
※見れないときはGoogle ChromeなどFlashが見れる環境でお願いします。
Scala入門記011 sbtでGoogle App Engine
ご無沙汰してます。
1年前から下書きにずっとあったのですが、内容は今も使ってる内容のままだったので投稿することにしました。
前回のServlet開発の延長線で、Google App EngineでServletを動かす環境を作る設定を紹介したいと思います。
Scala入門記の目次はこちらです。
build.sbtの設定
name := "scala-sbt-appengine" version := "1.0" scalaVersion := "2.11.8" libraryDependencies ++= Seq( "javax.servlet" % "servlet-api" % "2.5" % "provided", "org.eclipse.jetty" % "jetty-webapp" % "7.6.21.v20160908" % "container", "com.google.appengine" % "appengine-api-1.0-sdk" % "1.9.42", "com.google.appengine" % "appengine-api-stubs" % "1.9.42" % "test", "com.google.appengine" % "appengine-testing" % "1.9.42" % "test", "org.scalatest" %% "scalatest" % "2.2.6" % "test" ) appengineSettings
コンテナとしてJettyを設定しています。
2016年9月の時点でもまだApp EngineはServlet2.5で動作するためJetty7を選択していますが、より新しいJettyを使っても動作するようです。
※参考ページ: https://wiki.eclipse.org/Jetty/Starting/Jetty_Version_Comparison_Table
project/plugins.sbtの設定
addSbtPlugin("com.eed3si9n" % "sbt-appengine" % "0.6.2")
こちらがAppEngineを使うためのsbtプラグインです。
使い方はREADMEに詳しく載っていますが私がよく使うものは今回紹介します。
Servletのサンプル
package com.example import java.util.Date import javax.servlet.http.{HttpServlet, HttpServletRequest, HttpServletResponse} class SampleServlet extends HttpServlet { override def doGet(request: HttpServletRequest, response: HttpServletResponse) = { val s = response.getOutputStream s.print("Hello! " + new Date().toString) s.flush() } }
src/main/webapp/WEB-INF/web.xmlのサンプル
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" 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_3_0.xsd" id="serv" version="3.0"> <servlet> <servlet-name>SampleServlet</servlet-name> <servlet-class>com.example.SampleServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>SampleServlet</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> </web-app>
src/main/webapp/WEB-INF/appengine-web.xml
<?xml version="1.0" encoding="utf-8"?> <appengine-web-app xmlns="http://appengine.google.com/ns/1.0"> <application>app-name</application> <version>app-version</version> <threadsafe>true</threadsafe> </appengine-web-app>
App Engineで実行するための設定ファイルです。
https://appengine.google.comで作成したプロジェクトのIDと任意のバージョンを指定します。
これは実際にApp Engineへデプロイするまでは適当でOKですが、存在しないと開発サーバでも実行できません。
実行
sbt appengineDevServer
これで開発サーバが起動しますが、デフォルトでは8080で起動するため私はJenkinsとかぶってしまいます。
sbt "~appengineDevServer --port=8081"
このように--port=[ポート番号]と指定することで開発サーバが使うポートを変更することができます。
基本的に私は自分ではこのコマンドしか使わないです。
また、appengineDevServerでは毎回warを作る形ではありますがソースを更新すると開発サーバが再起動されすぐに動作を確認することも出来ます。
デプロイ
sbt "appengineDeploy"
このコマンドでAppEngineへデプロイ出来ます。
sbt "appengineDeploy --oauth2"
このように--oauth2オプションを付けることでOAuth認証が使えるので一度Google認証すると次回から認証画面を出さずにデプロイが可能です。
Jenkinsでデプロイするときなどに便利です。
まとめ
前回のServletをappengine-web.xmlを追加して設定を書き換えるだけでApp Engineにデプロイできるようになりました。
Mavenサポートが充実してきているようなのでsbtを使うメリットは少ないかもしれませんが、Scalaで書くならsbtで管理したいと思っています。
今回試した內容のソースはこちらです。
https://github.com/thachi/scala-sbt-appenginegithub.com
おまけ
今回作ったサンプルをApp Engineで実際に実行したところスピンアップは2.77秒でした。
Scala入門記010 sbtでServlet開発
だいぶ時間が開いてしまいましたが元気です。
北海道なのに蒸し暑い日が続いています。
Macのフォルダを整理していたら以前作ったsbtでのServlet環境のサンプルが出てきたのでもろもろを最新バージョンに設定しなおして動かしてみましたので記録しておきます。
Scala入門記の目次はこちらです。
利用したライブラリ
sbtのプラグイン「xsbt-web-plugin」を使いました。github.com
以前の1.xではjettyなどをcontainerとして依存ライブラリに指定しなければならなかったのですが2.0からはプラグインがやってくれるようになったみたいです。
実行環境としてはjettyとtomcatが選べるようになってました。
build.sbtの設定
name := "scala-sbt-servlet" version := "1.0" scalaVersion := "2.11.7" libraryDependencies ++= Seq( "javax.servlet" % "javax.servlet-api" % "3.1.0" % "provided", "org.scalatest" %% "scalatest" % "2.2.5" % "test" ) enablePlugins(JettyPlugin) containerPort := 9090
デフォルトでは8080で起動しますがJenkinsさんが使ってたので9090にしてみました。
project/plugins.sbtの設定
addSbtPlugin("com.earldouglas" % "xsbt-web-plugin" % "2.0.3")
これが肝です。
7月4日から2.0系がリリースされているみたいです。
Servletのサンプル
package com.example import java.util.Date import javax.servlet.http.{HttpServlet, HttpServletRequest, HttpServletResponse} class SampleServlet extends HttpServlet { override def doGet(request: HttpServletRequest, response: HttpServletResponse) = { val s = response.getOutputStream s.print("Hello! " + new Date().toString) s.flush() } }
Hello!と時刻を表示するだけのシンプルなServletです。
web.xmlのサンプル
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" 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_3_0.xsd" id="serv" version="3.0"> <servlet> <servlet-name>SampleServlet</servlet-name> <servlet-class>com.example.SampleServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>SampleServlet</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> </web-app>
これもシンプルですべてのリクエストをSampleServletにマッピングしています。
実行
sbt ~jetty:start
超簡単です。「~」を付けないと起動してすぐ終了してしまいます。
メモ
tomcatを使うときはbuild.sbtの
enablePlugins(JettyPlugin)
を
enablePlugins(TomcatPlugin)
に変更して、
sbt ~tomcat:start
で起動します。
依存ライブラリにコンテナを指定しなくても良くなったのは楽になったと思います。
特定のバージョンを指定したい場合も指定できるので安心ですね。
プラグインの使い方の詳細は2.0のドキュメントにまとまってます。
まとめ
earldouglas/xsbt-web-plugin · GitHubを使えば特に難しいこともなくScalaでWebアプリの開発が行えます。
フレームワークなどを使うプロジェクトも基本はこれで動くのではないでしょうか。
今回試した內容のソースはこちらです。
Scala入門記009 sbtでマルチプロジェクト その2
私の住んでいる北海道も、雪がだいぶ溶けて春らしくなってきました。
最近はScalaのマクロを色々とさわって勉強してみたりしてします。
前回のその1ではプロジェクトのファイルが
- Build.scala x 1
- build.sbt x 3
の4つに分かれていました。
今回はこれをBuild.scalaの1つにまとめる設定をしてみます。
Scala入門記の目次はこちらです。
Build.scalaの設定
import sbt._ import sbt.Keys._ object ScalaSample002Build extends Build { lazy val projectSettings = Defaults.defaultSettings ++ Seq( organization := "com.xhachi.samples", version := "1.0", scalaVersion := "2.10.3", libraryDependencies ++= Seq( "org.scalatest" %% "scalatest" % "2.0" % "test" ) ) lazy val root = Project( id = "scala-sample-002", base = file("."), settings = projectSettings ++ Seq( name := "scala-sample-002" ) ).dependsOn(project2) lazy val project1 = Project( id = "scala-sample-002-1", base = file("project1"), settings = projectSettings ++ Seq( name := "scala-sample-002-1" ) ) lazy val project2 = Project( id = "scala-sample-002-2", base = file("project2"), settings = projectSettings ++ Seq( name := "scala-sample-002-2" ) ).dependsOn(project1) }
今回は前回のrootのプロジェクトにあった
.aggregate(project1, project2)
の設定を省いていみたところEclipseのプロジェクトが3つ作成されインポートできるようになりました。
この辺りの動きは今後確認して行きたいと思います。
インポートしたらこんな感じです。
いいこと
Build.scalaをこう書き換えることで、他の3つのbuild.sbtは不要になります。
また、
- organization := "com.xhachi.samples"
- version := "1.0"
- scalaVersion := "2.10.3"
のような共通の設定をまとめたりもできるので管理しやりやすくなります。
また、Scalaのコードなのでコンパイルエラーなどで構文チェックもできます。
ソースコード
今回のソースは009のタグを打ってあるこちらです。
thachi/scala-sample-002 at 009 · GitHub
修正した差分はこちら。
プロジェクトの設定をBuild.scalaにまとめ、build.sbtを削除しました。 · 4971d6e · thachi/scala-sample-002 · GitHub
Scala入門記008 sbtでマルチプロジェクト その1
ご無沙汰してしまっていました。。。
しばらく前に下書きしたマルチプロジェクトの記事を清書してみました。
ある程度のプロジェクトであれば、複数のサブプロジェクトに分けて開発することも多くなります。
モジュールを分けたり、ビルド単位を分けたかったり事情は色いろあるとは思いますが、分けると色々便利だったりします。
そういうことでsbtのマルチプロジェクトを試してみたいと思います。
基本的に始める sbt - マルチプロジェクト・ビルドの内容から試してみます。
Scala入門記の目次はこちらです。
ビルドの定義
まずはビルド定義だけ作成してみます。
ディレクトリ構成はこんな感じです。
- build.sbt
- project
- Build.scala
- project1
- build.sbt
- project2
- build.sbt
build.sbt
これは普通のsbtプロジェクトと同様です。
Scala入門記003 初めてのsbt - うさばかSE Blog3の時とnameだけ違います。
このプロジェクトを(一般的かはわかりませんが)ルートプロジェクトと呼びます。
name := "scala-sample-002" version := "1.0" scalaVersion := "2.10.3"
project1/build.sbt
「サブプロジェクト1」としてproject1というディレクトリを用意しました。
このビルド定義はproject1ディレクトリにbuild.sbtという名前で配置しました。
ルートプロジェクトと同様にnameだけが変えてあります。
name := "scala-sample-002-1" version := "1.0" scalaVersion := "2.10.3"
project2/build.sbt
「サブプロジェクト2」も同様にproject2というディレクトリを用意しbuild.sbtという名前で配置しました。
これもnameだけが異なります。
name := "scala-sample-002-2" version := "1.0" scalaVersion := "2.10.3"
project/Build.scala
順序が前後しましたが最後に本命のビルド定義ファイルです。
本当はこのファイルだけですべてが記述できるのですが、build.sbtとBuild.scalaと分けて徐々に慣れていく作戦です。
import sbt._ object ScalaSample002Build extends Build { lazy val root = Project( id = "scala-sample-002", base = file(".") ) aggregate(project1, project2) lazy val project1 = Project( id = "scala-sample-002-1", base = file("project1") ) lazy val project2 = Project( id = "scala-sample-002-2", base = file("project2") ) }
root, project1, project2の3つのプロジェクトを定義しています。
aggregateというメソッドでrootにproject1とproject2を関連させている感じでしょうか。