1. sbt ランチャー入門

sbt ランチャー入門 

sbtランチャーは2つのパートを提供します

  1. 起動されたアプリケーションがランチャーコードと対話するためのインターフェース
  2. ivyを通じてアプリケーションを解決することでアプリケーションを起動できる最小限のsbt-launch.jar。

sbtランチャーコンポーネントは、Scalaまたはアプリケーションがシステムに既に存在していなくても、Scalaアプリケーションまたはサーバーを起動する自己完結型のjarです。唯一の前提条件は、ランチャーjar自体、オプションの設定ファイル、およびJavaランタイムバージョン1.6以上です。

概要 

ユーザーはランチャーjarをダウンロードし、それを実行するためのスクリプトを作成します。このドキュメントでは、スクリプトは `launch` と呼ばれると仮定します。Unixの場合、スクリプトは次のようになります。 `java -jar sbt-launcher.jar "$@"`

ユーザーはsbtランチャー設定を提供するサーバーとアプリケーションを起動できます。

または、ランチャー設定ファイルを使用してランチャーを再パッケージ化できます。たとえば、sbt/sbt は生のJARを取得し、sbtに適切なboot.propertiesファイルを挿入します

アプリケーション 

アプリケーションを起動するには、ユーザーはアプリケーションの設定ファイル( `my.app.configuration` と呼ぶ)をダウンロードし、それを起動するためのスクリプト( `myapp` と呼ぶ)を作成します

launch @my.app.configuration "$@"

ユーザーは `myapp arg1 arg2 ...` を使用してアプリケーションを起動できます

ランチャー設定の詳細については、ランチャー設定を参照してください。

サーバー 

sbtランチャーを使用して、システム上で実行中のサーバーを起動および検出できます。ランチャーを使用して、アプリケーションと同様にサーバーを起動できます。ただし、必要に応じて、ランチャーを使用して、サーバーのインスタンスが一度に1つだけ実行されていることを確認することもできます。これは、クライアントが常にランチャーを *サービソロケータ* として使用することによって行われます。

サーバーがどこで実行されているかを確認する(または実行されていない場合は起動する)には、ユーザーはサーバーの設定ファイル( `my.server.configuration` と呼ぶ)をダウンロードし、サーバーを検出するためのスクリプト( `find-myserver` と呼ぶ)を作成します

launch --locate @my.server.properties.

このコマンドは、サーバーに到達するためのURIである1つの文字列、たとえば `sbt://127.0.0.1:65501` を出力します。クライアントはIP /ポートを使用してサーバーに接続し、接続を開始する必要があります。

`locate` 機能を使用する場合、sbtランチャーはサーバーに次の制限を設けます

  • サーバーには、 `xsbti.ServerMain` クラスを拡張する開始クラスが必要です
  • サーバーには、クライアントがサーバーを検出するために使用できるエントリポイント(URI)が必要です
  • サーバーは、ランチャーが一度に1つのインスタンスのみが実行されていることを確認するために使用できるロックファイルを定義している必要があります
  • ロックファイルが存在するファイルシステムは、ロックをサポートしている必要があります。
  • サーバーは、ランチャーがデータを送信せずにポートに対してソケットを開くことを許可する必要があります。これは、以前のサーバーがまだ生きているかどうかを確認するために使用されます。

アプリケーション/サーバーの解決 

`sbt` の配布に使用されるランチャーと同様に、ダウンロードされたランチャーjarは、提供された設定ファイルに従ってScalaとアプリケーションを取得します。バージョンは固定されるか、別の設定ファイルから読み取られる場合があります(その場所は設定可能です)。Scalaおよびアプリケーションjarのダウンロード先は設定可能です。検索されるリポジトリは設定可能です。起動時のプロパティファイルのオプションの初期化は設定可能です。

ランチャーが必要なjarをダウンロードしたら、アプリケーション/サーバーをロードし、そのエントリポイントを呼び出します。アプリケーションには、呼び出された方法に関する情報(コマンドライン引数、現在の作業ディレクトリ、Scalaバージョン、アプリケーションID(組織、名前、バージョン))が渡されます。さらに、アプリケーションは、設定ファイルで指定されたリポジトリから取得可能なScalaの任意のバージョンのScala jarと `ClassLoader` を取得するなどの操作を実行するようにランチャーに要求できます。他のアプリケーションをダウンロードして実行するように要求できます。アプリケーションが完了すると、ランチャーに特定の終了コードで終了するか、Scalaの別のバージョン、アプリケーションの別のバージョン、または別の引数でアプリケーションをリロードするように指示できます。

設定ファイルを設定ファイル内に配置し、それを単一のダウンロードとして配布するなど、セットアップの他のオプションがいくつかあります。このドキュメントの残りの部分では、アプリケーションの設定、記述、配布、および実行の詳細について説明します。

起動されたアプリケーションの作成 

このセクションでは、このランチャーによって起動されるアプリケーションを作成する方法を示します。まず、 `launcher-interface` への依存関係を宣言します。ランチャー自体への依存関係を宣言しないでください。ランチャーインターフェースは、ランチャーのコンパイルに使用されるScalaのバージョンとアプリケーションのコンパイルに使用されるバージョンの間のバイナリ非互換性を回避するために、厳密にJavaインターフェースで構成されています。ランチャーインターフェースクラスはランチャーによって提供されるため、コンパイル時の依存関係のみです。 sbtを使用してビルドしている場合、依存関係定義は次のようになります

libraryDependencies += "org.scala-sbt" % "launcher-interface" % "1.0.0" % "provided"

resolvers += sbtResolver.value

クラスのエントリポイントに `xsbti.AppMain` を実装させます。情報をいくつか使用する例

package com.acme.launcherapp

class Main extends xsbti.AppMain
{
    def run(configuration: xsbti.AppConfiguration) =
    {
        // get the version of Scala used to launch the application
        val scalaVersion = configuration.provider.scalaProvider.version

        // Print a message and the arguments to the application
        println("Hello world!  Running Scala " + scalaVersion)
        configuration.arguments.foreach(println)

        // demonstrate the ability to reboot the application into different versions of Scala
        // and how to return the code to exit with
        scalaVersion match
        {
            case "2.10.6" =>
                new xsbti.Reboot {
                    def arguments = configuration.arguments
                    def baseDirectory = configuration.baseDirectory
                    def scalaVersion = "2.11.8"
                    def app = configuration.provider.id
                }
            case "2.11.8" => new Exit(1)
            case _ => new Exit(0)
        }
    }
    class Exit(val code: Int) extends xsbti.Exit
}

次に、ランチャーの設定ファイルを定義します。上記のクラスの場合、次のようになります

[scala]
  version: 2.11.8
[app]
  org: com.acme
  name: launcherapp
  version: 0.0.1
  class: com.acme.launcherapp.Main
  cross-versioned: true
[repositories]
  local
  maven-central
[boot]
 directory: ${user.home}/.myapp/boot

次に、sbtのシェルでアプリケーションを `publishLocal` または `+ publishLocal` して、使用できるようにします。詳細については、ランチャー設定を参照してください。

アプリケーションの実行 

上記のように、アプリケーションを実際に実行するためのオプションがいくつかあります。1つ目は、ダウンロード用に変更されたjarを提供することです。 2番目と3番目は、ダウンロード用の設定ファイルを提供する必要があります。

  • ランチャーjarの `/sbt/sbt.boot.properties` ファイルを置き換え、変更されたjarを配布します。ユーザーは `java -jar your-launcher.jar arg1 arg2 ....` を実行するためのスクリプトが必要です
  • ユーザーはランチャーjarをダウンロードし、設定ファイルを提供します。

    • ユーザーは `java -Dsbt.boot.properties=your.boot.properties -jar launcher.jar` を実行する必要があります。
    • ユーザーはすでにランチャーを実行するためのスクリプト(「起動」と呼ぶ)を持っています。ユーザーは `launch @your.boot.properties your-arg-1 your-arg-2` を実行する必要があります

実行 

ランチャーがアプリケーションを起動したときに何が起こっているかを確認しましょう。

起動時に、ランチャーは設定ファイルを探し、それを解析します。最終的な設定が解決されると、ランチャーはアプリケーションを起動するために必要なJARファイルの取得に進みます。 boot.directory プロパティは、JARファイルを取得するためのベースディレクトリとして使用されます。ディレクトリに対してロックがかけられるため、システム全体で共有できます。ランチャーは、要求されたバージョンのScalaを

${boot.directory}/${scala.version}/lib/

このディレクトリが既に存在する場合、ランチャーは起動パフォーマンスを向上させるためにショートカットを取り、JARファイルが既にダウンロードされていると想定します。ディレクトリが存在しない場合、ランチャーはApache Ivyを使用してJARファイルを解決し、取得します。同様のプロセスがアプリケーション自体にも発生します。アプリケーションとその依存関係は

${boot.directory}/${scala.version}/${app.org}/${app.name}/.

必要なすべてのコードがダウンロードされると、クラスローダーが設定されます。ランチャーは、要求されたバージョンのScala用のクラスローダーを作成します。次に、要求された app.components のJARファイルと app.resources で指定されたパスを含む子クラスローダーを作成します。コンポーネントを使用しないアプリケーションは、すべてのJARファイルをこのクラスローダーに持ちます。

次に、アプリケーションのメインクラスがインスタンス化されます。これは、publicで引数のないコンストラクタを持つpublicクラスであり、 xsbti.AppMain に準拠する必要があります。 run メソッドが呼び出され、実行がアプリケーションに渡されます。 `run`メソッドの引数は、設定情報と、[repositories]のリポジトリから取得できる任意のバージョンのScalaのクラスローダーを取得するためのコールバックを提供します。 runメソッドの戻り値は、アプリケーションの実行後に何が行われるかを決定します。ランチャーがアプリケーションを再起動する必要があるか、提供された終了コードで終了する必要があるかを指定できます。