たそらぼ

日頃思ったこととかメモとか。

sbtを使ってScalaコードを、Lambda用のオールインワンのjarにする

ScalaAWS Lambda用のjarファイルを作りました。

ScalaでLambdaのようなPaaSを利用したいと思い、jarファイルを作ることにしました。今回は@yoshiyoshifujiiさんのqiita記事(Amazon LambdaでScala - Qiita)を参考に、Lambdaで動かすことを目標にしています。

ちゃんとしたJavaの基礎があれば、Eclipseを使ってほいほいっとできると思うんですが、自分はよく分かんないので、比較的慣れているsbtを使って手軽にやってみました。

参考にした記事はすごく分かりやすいのですが、少し時間がたって若干変わっているところと、もう少し自分でかみ砕いて理解したいところがあったので、まとめてさせていただきました。

環境など

sbt 1.2.8
scala 2-13
windows10

ひな形の作成

まずディレクトリを作成していく。やり方はいろいろありますが、scala/scala-seed.g8テンプレートを使って最小構成のディレクトリを作っておきます。

> sbt new scala/scala-seed.g8

(略)
name [Scala Seed Project]: 適当にプロジェクト名を決める

> tree
C:.
└─lambda-scala
    ├─project
    └─src
        ├─main
        │  └─scala
        │      └─example
        └─test
            └─scala
                └─example

続いてコードをsrc/main/scala/example内に書いていきます。

サンプルコードの作成

前工程から文字列を受け取り、標準出力に同じ文字列をオウム返しする関数を実装しています。
src/main/scala/example/Repeat.scalaとして作成します。

package example

import scala.collection.JavaConverters._
import com.amazonaws.services.lambda.runtime.Context
import com.amazonaws.services.lambda.runtime.RequestHandler


trait RepeatBase {
  def repeat(testPhrase: String, context: Context) = {
    println(testPhrase)
  }
}

class Repeat extends RepeatBase


Lambda用におさえる点としては、

・lambdaを動かすのに使う関数をimportする。
 今回はRequestHandlerです。これは後程build.sbtで落としてくるように設定します。
・handler関数の引数に、「受け取る値」と「実行コンテキスト」の2変数を設定する。
 今回は、受け取る文字列をtestPhrase、実行コンテキストをcontextとして持たせています。

実際のシステムでLambda背後のサービスに処理結果を渡す場合は、当然返り値も必要です。これはそんなにむつかしくないので、ひとまずvoidにしておきます。

Lambda SDKのダウンロード設定

プロジェクトのルートにあるbuild.sbtにaws-lambda-java-coreの1.1.0を落とすように書きたします。以下のようになります。

import Dependencies._

ThisBuild / scalaVersion     := "2.13.0"
ThisBuild / version          := "0.1.0-SNAPSHOT"
ThisBuild / organization     := "com.example"
ThisBuild / organizationName := "example"

lazy val root = (project in file("."))
  .settings(
    name := "lambda-scala",
    libraryDependencies += scalaTest % Test,
    libraryDependencies += "com.amazonaws" % "aws-lambda-java-core" % "1.1.0" ←ここが書き足したところ!
  )


build.sbtのlibraryDependencies キーに、groupId、artifactId、と revisionを記載することで外部モジュールのダウンロードが設定できます。
www.scala-sbt.org

AWS公式に、Maven用に記載されているpom.xmlを見ると、
 groupId:com.amazonaws
 artifactId:aws-lambda-java-core
 revision:1.1.0
としておくとなんかよさそうなことが分かります。
docs.aws.amazon.com

sbt-assemblyの設定

sbt-assemblyを使い、オールインワンのjarを作成します。
github.com

project/assembly.sbtを作成し、以下を書いておきます。

addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.9")

あとはプロジェクトルートでsbt assemblyを実行すると、どこにjarが吐かれたかpathも表示されるので、作業完了です。

>sbt assembly

(略)

[info] Packaging C:\ほげほげ....

あとは、できたjarファイルをLambdaで動かせばOKです。

Lambdaで実行

Lambdaのコンソールにこんな感じで上げます。
f:id:tasotasoso:20190720225836p:plain

テストはこんな感じで作成しておきます。
f:id:tasotasoso:20190720185026p:plain

実行すると、ばっちりリピートしてくれてました!
f:id:tasotasoso:20190720185035p:plain

感想

Java用のライブラリを使って、ScalaでもLambdaで実行ができました。応用すると、Clojureでも実行できるのかな...とか、夢が広がります。Lambdaはほかのサービスと疎な開発ができるので、簡単なスクリプトではありますが、こうやって好きな言語で開発できるのはすごくモチベが上がって面白いです。API Gatewayなどとも組み合わせて、サービス開発にもどんどん使っていけると楽しいですね。