Akka HTTPでWebJarsとTwirlを使う

仕事でちょっとしたツール(Webアプリ)を作るのに試しにAkka HTTPを使ってみています。Akka HTTPでJSONを使う方法については以前このブログでも紹介しましたが、

takezoe.hatenablog.com

今回はいわゆるHTMLを返すシンプルな作りの管理ツールなのでJavaScriptCSSライブラリはWebJarsで、HTMLのレンダリングはTwirlを使うようにしてみました。

WebJars

ThoughtWorksリポジトリにAkka HTTPでWebJarsを使うためのライブラリがありました。

github.com

メンテが止まっているようですが、リポジトリ内のWebJarsSupportは現在のAkka HTTPでもそのまま利用できます。実装としては非常にシンプルで、webjars-locatorで取得したクラスパス内のリソースをgetFromResource()で返しているだけです。

これを使う場合はbuild.sbtに以下の依存関係を追加する必要があります。

"org.webjars" % "webjars-locator" % "0.32"

WebJarsのリソースを返すエンドポイントはこんな感じ。/webjars/jquery.jsのようなパスでWebJarsでインポートしたJavaScriptCSSを参照できます。

import com.thoughtworks.akka.http.WebJarsSupport._

get {
  pathPrefix("webjars") {
    webJars
  }
}

Twirl

Twirlもライブラリを作っている人がいました。

github.com

こちらも最新のAkka HTTPのバージョンには追従できていないようですが、TwirlのHtml型などに対応するマーシャラーを定義しているだけのシンプルなものなので、リポジトリ内のTwirlSupportをそのまま持ってきて使ってもよいでしょう。

これを使う場合は普通にTwirlを使う場合と同様の設定が必要になります。まずはproject/plugins.sbtにTwirlプラグインを追加。

addSbtPlugin("com.typesafe.sbt" % "sbt-twirl" % "1.3.4")

build.sbtでTwirlプラグインを有効化します。

enablePlugins(SbtTwirl)

Twirlのテンプレートファイルはsrc/main/twirlディレクトリ配下に作成し、エンドポイントからは以下のようにして呼び出します。

import akkahttptwirl.TwirlSupport._

get {
  path("hello") {
    // src/main/twirl/hello.scala.html
    complete(html.hello())
  } ~
}

おまけ:静的ファイルを返す

おまけとしてAkka HTTPで静的ファイルを返す方法を書いておきます。ファイルシステム上のファイルを返す場合はこんな感じ。

get {
  pathPrefix("assets") {
    getFromDirectory("assets")
  }
}

クラスパス内のリソースを返すこともできます。

get {
  pathPrefix("assets") {
    getFromResourceDirectory("assets")
  }
}

とりあえずこのくらいでAkka HTTPで普通のWebアプリを作ることができるんじゃないかと思います。フォームのバリデーションなどもあると便利ですが、そのあたりも拡張して便利に使えるものを組み込んでしまうのがよさそうです。

オープンソースの機械学習プラットフォームまとめ

PredictionIOは機械学習を使用したアプリケーションを開発・運用するためのプラットフォームを提供するためのOSSですが、世の中には他にも同じ領域のOSSが存在します。PredictionIO含めて各プロダクトの特徴をまとめてみました(PredictionIO以外はドキュメントやソースをチラ見して書いているので見落としていることなどあるかもしれませんがご容赦いただければと思います)。

PredictionIO

github.com

Apache Software Foundationで開発されている機械学習プラットフォームです。基本的にSpark上で動作する機械学習ライブラリをターゲットにしていますが、最近はPython対応なども行われています。作成したマイクロサービスはSprayベースのAPIサーバとして起動することが可能です。用途に応じたテンプレートが多数用意されており、それをカスタマイズして使用できるのが特徴です。

Apacheのプロジェクトですし、ドキュメントやサンプルもそれなりに揃っています。日本人コミッタもおり、国内でのイベントも開催しているので、他のプロダクトと比べると情報を得やすいのもメリットといえます。

PredictionIOの概要については以下のQiitaの記事が参考になります。日本語のハウツー記事も多いので、ググってみていただけるとよいかと思います。

qiita.com

Seldon

github.com

基本的にはPredictionIO同様のユースケースが想定されており、Predict、Recommend用のサービスを構築可能。Spark、scikit-learn、TensorFlow、Kerasなどの機械学習ライブラリをサポートしていたり、作成したマイクロサービスをDockerコンテナとしてデプロイ可能、Graphanaによるマイクロサービスのモニタリング機能も自前で備えているなど機能的にはPredictionIOよりも先行している部分がありますが、ドキュメントが豊富とはいえず、日本語はもちろんのこと英語での情報もまだまだ少ないようです。ただ、企業がやっているOSSなので、そこはコンサルしますよということなのかもしれません。

日本語では以下のQiitaの記事が参考になると思います。

qiita.com

MLeap

github.com

MLパイプラインをシリアライズ/デシリアライズし、実行するためのライブラリを提供します。Spark、scikit-learn、TensorFlowをサポート。生成した予測モデルを使用してマイクロサービスとしてデプロイするためのDockerイメージも用意されています。PredictionIOやSeldonと違って機械学習を運用するためのプラットフォームというよりはパイプラインや予測モデルのポータビリティを実現するためのライブラリという感じです。

ドキュメントはSeldonと比べるとかなりしっかりしていますが、日本語情報は今のところ皆無です。

まとめ

アプリケーションに機械学習を活用した機能を組み込むことが一般的になるにつれ、それらを効率よく開発・運用するためにこのような機械学習プラットフォームの必要性は高まってくると考えています。SeldonやMLeapのように複数の機械学習ライブラリを扱うことができる仕組みも必要になってくると思いますし、逆に機械学習の専門家がいないチームではPredictionIOのように予め用意されているテンプレートを使用することで機械学習を利用できるというメリットもあるでしょう。

どのプロダクトも作成した予測モデルをマイクロサービスとしてデプロイしてアプリケーションから利用するという形は共通していますが、一方でバッチ的に使用したい場合やオンライン学習などのユースケースをどう取り込んでいくのかという点についても今後の注目ポイントかもしれないと思います。

また、今回はOSS機械学習プラットフォームを紹介しましたが、AWSやAzure、GCPなどで提供されているマネージドな機械学習プラットフォームももちろん有力なオプションです。機械学習プラットフォームの動向という意味ではこれらについても注視していく必要がありそうです。

PredictionIOがApache Software Foundationのトップレベルプロジェクトになりました!

弊社のメンバーもコミッタとして開発に参加しているApache PredictionIOですが、このたびめでたくIncubatorプロジェクトを卒業してトップレベルプロジェクトに昇格することができました。ASFからのリリースには弊社のチーフサイエンティストである@shinsuke_sugayaさんもコメントを寄せています。

"We are very interested in PredictionIO for solving any Machine Learning tasks," said Shinsuke Sugaya, Chief Scientist at BizReach, Inc. "At BizReach, using PredictionIO, we have built a data-analysis platform for HR, which fits learning models from about 5 million job descriptions and recommends preferred items from them to users everyday. PredictionIO has accelerated our analysis and development tasks for data scientists and developers, and simplified infrastructure from data management to prediction server."

また、ASFからのリリースとは別にSalesforce社のブログにもPredictionIOの共同創業者兼CEOだったSimon Chan氏によるエントリが上がっていました。

PredictionIOはもともと彼らが起業したスタートアップで開発されていたOSSだったのですが、昨年Salesforce社に買収され、その後はApache Incubatorで開発されていました。少し停滞してこれは時間がかかるかな…と思った時期もあったのですが、14ヶ月(弊社のメンバーが正式にコミッタになってからは約半年)でのトップレベルプロジェクト昇格というのはまあまあ早いほうなのではないかと思います。

現在はSalesforce社のメンバーと弊社のメンバーが中心となって開発が行われていますが、まだまだ改善すべき点も多いですし、機械学習を使用したサービス構築のためのフレームワークという領域には競合もそれなりに存在するので引き続き頑張っていきたいと思います。

また、先日Scala福岡でのPredictionIOに関する発表をタイミングよく記事にしていただきましたので、是非こちらもご覧いただければと思います。

codeiq.jp

GitBucket 4.18.0をリリースしました

Scalaで実装されたオープンソースのGitサーバ、GitBucket 4.18.0をリリースしました。

https://github.com/takezoe/gitbucket/releases/tag/4.18.0

レビューコメントへの返信フォーム

プルリクエストなど、ソースコードにつけたコメントに対して返信するためのフォームを表示するようにしました。レビューコメントに対してこのフォームから簡単に返信を行うことができます。

f:id:takezoe:20171011025818p:plain

ユーザ名のサジェストにフルネームも表示

ユーザ名のサジェスト時に、ユーザ名だけでなくフルネームも表示するようにしました。

f:id:takezoe:20171011025837p:plain

コミットフックをブラウザ編集時も適用

これまでプラグインが提供するコミットフック(実際にはReceiveHookとして実装されます)はgit pushでのプッシュ時のみ適用され、ブラウザ上でgitリポジトリ内のファイルをオンライン編集した場合には適用されていなかったのですが、GitBucket 4.18.0からはブラウザでの編集時もコミットフックが動作するようになりました。

これによってブランチプロテクションの設定を行っている場合、ブラウザ上での変更からも保護が有効になりました。

gitbucket-ci-pluginのアップデート

gitbucket-ci-pluginが1.1.0にバージョンアップし、以下の機能が追加されました。

  • コミットメッセージに特定のキーワードを含めておくとビルドをスキップ
  • プルリクエストに特定のキーワードを含むコメントを追加するとビルドを再実行

これらのキーワードはビルドの設定画面で指定可能です(カンマ区切りで複数設定可)。

f:id:takezoe:20171011025853p:plain

また、ビルドスクリプトで以下の環境変数が使用できるようになりました。

  • CI (true)
  • HOME (root of the build directory)
  • CI_BUILD_DIR (same as HOME)
  • CI_BUILD_NUMBER
  • CI_BUILD_BRANCH
  • CI_COMMIT_ID
  • CI_COMMIT_MESSAGE
  • CI_REPO_SLUG ("owner/repo")
  • CI_PULL_REQUEST (pull request id or "false")
  • CI_PULL_REQUEST_SLUG ("owner/repo" or "")

今回のバージョンではこの他にも様々な改善やバグフィックスを行っています。詳細についてはIssueの一覧をご覧ください。

第二十回 #渋谷java でElasticsearch + Akka Streamsの話をしました

f:id:takezoe:20171001013203j:plain

shibuya-java.connpass.com

渋谷javaもいつの間にか二十回、今回は久しぶりに蓮沼さんや小宮さんにも発表していただきました。

当日の様子は以下のTogetterまとめをご覧ください。

togetter.com

emegさんが紹介されていたActiveMQ Artemisは、後でお話を聞いたところ実はHornetQ(JBossの次世代JMS実装として開発されていたもの)がASFに寄贈されたものだとのことで、昔HornetQとだいぶ悪戦苦闘していた時期があったのでちょっと微妙な気持ちになりましたw ActiveMQはもともとApolloという次世代版をScalaで開発していたのですが、なかなか開発者が集まらず困っていたところにHornetQの寄贈の話があり、こちらで行くことにしたそうです。いつの間にかそんなことになってたんですねぇ。

さて、自分はといえば、10分枠のLTで先日AlpakkaにマージしていただいたAkka Streams用のElasticsearchコネクタの紹介と簡単なデモをさせていただきました。

takezoe.hatenablog.com

資料はこちらです。バックプレッシャーのデモは何が起きているのかあれで伝わっただろうか?という一抹の不安がありますが…。

www.slideshare.net

今回紹介させていただいたElasticsearch以外にも、Alpakkaにはいろんなストレージ向けのコネクタが用意されているので、バックプレッシャー云々は置いておくとしてもデータの加工や移行などを行うバッチなんかは結構書きやすいんじゃないかと思います。Akka StreamsはJava用のAPIもあるので普段Javaを使ってる方も気軽に試してみて欲しいです。

GitBucket 4.17.0をリリースしました

Scalaで実装されたオープンソースのGitサーバ、GitBucket 4.17.0をリリースしました。

https://github.com/takezoe/gitbucket/releases/tag/4.17.0

gitbucket-ci-pluginが利用可能になりました

GitBucketでシンプルなCI機能を提供するgitbucket-ci-pluginが利用可能になりました。

f:id:takezoe:20170924143458p:plain

f:id:takezoe:20170924143509p:plain

このプラグインリポジトリのオーナーが設定したビルド用のコマンドを以下のタイミングで実行します。

  • デフォルトブランチにpushされたとき
  • プルリクエストにpushされたとき

このプラグインリポジトリのオーナーにGitBucketが動作しているサーバ上で任意のコマンド実行を許可することになりますので、公開環境で運用しているGitBucketでは使用しないでください。

また、このプラグインはあくまでGitBucketでのCIをWebフックやJenkinsなどの複雑な設定を行わなくても「試せる」ようにするためのものであり、本格的なCI/CDのために必要な柔軟性やスケーラビリティは持っていません。そのため、もしこのプラグインを試してGitBucketでのCIを本格的に使いたいと思った場合はJenkinsなどへの移行をおすすめします。

コミットID付きURLへの転送

リポジトリビューアでyキーを押すとコミットID付きのURLに移動するようになりました。ファイルの特定バージョンを示すURLを共有したい場合に便利です。

また、ファイルビューアでファイルの行番号をクリックした際も自動的にコミットID付きのURLになります。

f:id:takezoe:20170924143528p:plain

アップロード可能なファイル種別の制限を廃止

これまでGitBucketは添付可能なファイル種別に制限がありましたが、このバージョンでファイル種別による制限を廃止しました。Issues、Pull requests、各種コメントやWikiなど、ファイルをアップロード可能な箇所であればどのような種別のファイルでもアップロードできるようになりました。

メール送信APIの改善

GitBucketはプラグイン向けにメール送信用のAPIを提供していますが、このAPIがより汎用的になりました。プラグインでは以下のようにして使用できます:

val mailer = new Mailer(context.settings)

mailer.send(
  to           = "...", 
  subject      = "...", 
  textMsg      = "...", 
  htmlMsg      = Some("..."), 
  loginAccount = context.loginAccount
)

MailersendBcc()というメソッドも持っています。このメソッドはメールアドレスをSeq[String]で受け取り、これらのアドレスに対してBCCでメールを送信します。この修正に伴ってGitBucketに標準でバンドルされているgitbucket-notification-pluginは1.0.2にバージョンアップしています。

Web APIとWebフックの改善

  • 特定コミットの情報を取得するget a single commit APIを追加
  • プルリクエスト関連のAPIのレスポンスにasigneeを追加
  • Weフックのペイロードssh_urlを追加

今回のバージョンではこの他にも様々な改善やバグフィックスを行っています。詳細についてはIssueの一覧をご覧ください。

最強のMarkdown編集環境としてのAtom

ブログなどちょっとした文章の編集から書籍の執筆までMarkdownを活用しています。これまで試した各種テキストエディタMarkdown編集支援機能や、Markdown編集専用のツールはどれも満足の行くものではなかったのですが、最近はAtomに以下のようなパッケージを入れた環境が理想に近いMarkdown編集環境を得ることができました。

少し前にエンジニアHubさんで各社のエンジニアの方がオススメのAtomパッケージを紹介するという企画記事があり、私もMarkdown関連のパッケージを紹介させていただいたのですが、この記事では各パッケージを簡単にしか紹介できなかったので、ここでは少し詳しく紹介したいと思います。

employment.en-japan.com

document-outline

atom.io

サイドバーにMarkdownの見出しをツリー状に表示してくれるパッケージです。書籍原稿のような長文を編集していると文章の全体構造を見ながら作業を進めたくなることが多いのですが、Markdownの文章構造を表示してくれるツールというのは意外と見つからず、このパッケージの存在がAtomを最強のMarkdown編集環境足らしめていると言っても過言ではありません(Emacsoutline-tocという拡張を見つけたのですが、リフレッシュ時の画面のチラつきが激しくて実用は厳しかった…)。

以前は長文になるとリフレッシュが重く使い物にならなかったのですが、現在は高速化され数万文字のテキストでも問題なく扱えるようになりました。

markdown-writer

atom.io

Markdownの編集時に便利なちょっとした機能を提供してくれるパッケージです。たとえば箇条書きをしている際に行末で改行すると次の行の行頭に - を入れてくれたり(番号付きリストの場合は 1. の次は 2. のようにちゃんとインクリメントされて入ります)、TABやSHIFT + TABで箇条書きのインデントを調整したりすることができます。

他にもいろんな機能があるのですが、なくてもそんなに不便は感じないかも…。

markdown-scroll-sync

atom.io

Atomは標準機能でMarkdownのプレビューが可能ですが、エディタで表示している領域にあわせてプレビューを自動的にスクロールしてくれるパッケージです。ただ、Markdownの編集に慣れてくるとプレビューはあまり使わなくなるのでそんなに利用頻度は高くないかも…。あと、これは仕方ないことだとは思うのですが、スクロールがちょっとずれてしまうこともあります。

プレビュー機能は表や画像が正しく表示されているかを確認したり、ある程度書き終わった後に読み返す際に使うことが多いのですが、そういう用途の場合は逆にプレビューのスクロールにあわせてエディタをスクロールできるといいな、と思います。

atom-csv-markdown

atom.io

Markdownの編集時に一番手間がかかるのが表の作成ではないかと思います。これは自作のパッケージなのですが、CSV形式のテキストを範囲選択してMarkdownの表に変換できるというものです。

ゼロから表を作成する場合は次に紹介するmarkdown-table-writerを使ってエディタ上で編集するでもよいのですが、スプレッドシートなどに表の元ネタがあったりする場合にはCSVで貼り付けてからこれで一括変換するのが便利です。

markdown-table-editor

atom.io

Markdownの表の編集を支援してくれるパッケージです。文章では説明しずらいのですが、表を編集していると自動的にセル幅を調整してくれたり、タブキーでセルを移動できたり、ENTERキーで新しい行を追加してくれたりなど、あたかもスプレッドシートを編集しているかのような操作性を提供してくれます。キーボードショートカットなどを覚える必要もないのでめちゃくちゃ便利です(パッケージのページに掲載されている動画を見るとどのような動作をするかわかりやすいです)。

ただ、実際Markdownで表を作成していると、同じ列でも行によって入力される文字列の長さが大きく異なる場合などセル幅を統一したくないというケースもあります。このような場合はセル幅を自動調整しないよう設定を変更することもできます。コマンドパレットからも変更できるので編集中にサクッと切り替えできて便利です。

まとめ

なんといってもdocument-outlineの存在が大きいです。このパッケージのおかげで長文のMarkdownの編集が相当快適になりました。もともとMarkdownの記法はさほど複雑なものではないので編集支援系の機能は無ければ無いでなんとかなるのですが、これだけは替えがききません。

特にMarkdownで長文を編集する際は是非Atom + document-outlineパッケージの組み合わせを試してみていただければと思います。