NuxeoでKotlinの機能を活用する


Tue 23 May 2017 作成者: Arnaud Kervern, Vladimir Pasquier

台頭

Nuxeoサーバの性能を改善し、これまで以上に最新化と効率化を図る中、当社は今回、Kotlin言語の台頭に注目しました。

Nuxeo KotlinKotlinは、Java仮想マシン上で実行され、JetBrains作成のJavaScriptソースコードにコンパイルできる静的型付けプログラミング言語です。この言語は、Java「よりも優れた」インダストリアル強度のオブジェクト指向言語として設計されていますが、Javaコードとの相互運用性を完全に維持しています。そのため、組織はJavaからKotlinへの移行を徐々に進めることが可能です。

あらゆるAndroidアプリをKotlinで記述できるようにすることをGoogleが発表するなど、この言語は第一級のプログラミング言語となっています。

NuxeoバンドルをKotlinで開発できるようになったことを、ここに喜んで発表いたします!

KotlinとJava

KotlinはJavaコードと完全に相互運用可能です。そのため、KotlinとJavaの両方を1つのバンドルにコンパイルして、連携させることができます!

仕組み

プロジェクト構造

どのMavenプロジェクト構造もそうであるように、KotlinバンドルはNuxeo Javaバンドルと似ています。ただし、Kotlinコード用に新しいフォルダ「kotlin」を「java」の代わりに使用する点は異なります。

├── pom.xml
└── src
    ├── main
    │   ├── kotlin
    │   │   └── org
    │   │       └── nuxeo
    │   │           └── sample
    │   └── resources
    │       ├── META-INF
    │       └── OSGI-INF
    └── test
        └── org
            └── nuxeo
                └── kotlin
                    └── sample

もちろん、JavaとKotlinの両方を同じバンドルに混在させることが可能です!

├── pom.xml
└── src
    ├── main
    │   ├── kotlin
    │   │   └── org
    │   │       └── nuxeo
    │   │           └── sample
    |   |__ java
    |   |   |__ org......
    │   └── resources

最初のKotlinバンドル

それを行い、かつ、プロジェクトのブートストラップを容易に行えるよう、Nuxeo CLIを使用して専用のテンプレートを既に作成済みです。パッケージとサンプルオペレーションを使用して新しいバンドルを作成しましょう。

# Ensure to have the latest version
nuxeo update

# You can create an empty bundle using
# nuxeo bootstrap kotlin-module
# But, following this blog, we are going to create a more complete example
mkdir kotlin-sample && cd $_
nuxeo bootstrap kotlin-operation package

下記は答えの例です。これにこだわることなく、クリエイティブに答えていただいてかまいません。

     info You'll be prompted for generation of:
     info   kotlin-sample-kotlin: kotlin-module, kotlin-operation
     info   kotlin-sample-package: package

   create Generating Multi module (Your project parent POM)
     info   Parameters: Use a parent artifact, Parent group, Parent artifact, Parent version, Import nuxeo in the `dependency management`, Nuxeo version, Project group, Project artifact, Project version, Project description
? Use a parent artifact (for instance your company's BOM or the org.nuxeo.ecm.distribution:nuxeo-distribution POM)? Yes
? Parent Group id: org.nuxeo.ecm.distribution
? Parent Artifact id: nuxeo-distribution
? Parent Version: 9.1
? Project Group id: org.nuxeo.sample
? Project Artifact id: kotlin-sample-parent
? Project Version: 1.0-SNAPSHOT
? Project Description:

   create Generate Module: kotlin-sample-kotlin

   create Generating Kotlin module
     info   Parameters: Nuxeo version, Project group, Project artifact, Project version, Project description
? Project Group id: org.nuxeo.sample
? Project Artifact id: kotlin-sample-kotlin
? Project version: 1.0-SNAPSHOT
? Project description:

   create Generating Kotlin operation
     info   Parameters: Operation class name, Operation label
? Operation class name: SampleOperation
? Operation label: My Kotlin Operation

   create Generate Module: kotlin-sample-package

   create Generating Package
     info   Parameters: Package artifact, Package version, Package name, Company name
? Package Artifact id: kotlin-sample-package
? Package Version: 1.0-SNAPSHOT
? Package name: kotlin-sample
? Company name:

最初のKotlinオペレーション

次のようなKotlinベースのオペレーションが生成されます。このオペレーションの動作はJava版とほぼ同じです。

package org.nuxeo.sample

import org.nuxeo.ecm.automation.core.Constants
import org.nuxeo.ecm.automation.core.annotations.Context
import org.nuxeo.ecm.automation.core.annotations.Operation
import org.nuxeo.ecm.automation.core.annotations.OperationMethod
import org.nuxeo.ecm.automation.core.annotations.Param
import org.nuxeo.ecm.core.api.CoreSession
import org.nuxeo.ecm.core.api.DocumentModel
import org.nuxeo.ecm.core.api.PathRef

@Operation(id = "Document.SampleOperation", category = Constants.CAT_DOCUMENT, label="My Kotlin Operation", description="Describe here what your operation does.")
open class SampleOperation {

    @Context
    protected lateinit var session: CoreSession

    @Param(name = "path", required = false)
    protected var path: String? = null

    @OperationMethod
    fun run(): DocumentModel {
        return when {
            path.isNullOrBlank() -> session.rootDocument
            else -> session.getDocument(PathRef(path))
        }
    }
}

当然のことながら、他のどのNuxeoバンドルもそうであるように、このオペレーションはマニフェストに寄稿され、言及されています。

Mavenビルドプラグイン

Kotlin Mavenビルドプラグインが追加され、次のように正しくコンパイルするようになっています。

<plugin>
  <artifactId>kotlin-maven-plugin</artifactId>
  <groupId>org.jetbrains.kotlin</groupId>
  <version>${kotlin.version}</version>
  <executions>
    <execution>
      <id>compile</id>
      <goals>
        <goal>compile</goal>
      </goals>
    </execution>
    <execution>
      <id>test-compile</id>
      <goals>
        <goal>test-compile</goal>
      </goals>
    </execution>
  </executions>
</plugin>

展開

他のどのNuxeoバンドルもそうであるように、「mvn package」を実行してプロジェクトをビルドし、「$NUXEO_HOME/nxserver/bundles」フォルダにバンドルを配置することができます。

ただし、Nuxeoサーバを起動する前に、関連するJetBrains Kotlinランタイムライブラリを「NUXEO_HOME/nxserver/lib」で忘れずに設定しておく必要があります。

うれしいことに、ランタイムライブラリの設定は、先ほど作成したNuxeoパッケージを使用して自動的に処理されます。パッケージを展開する以外に必要な操作は何もありません。

# Build the whole bundle
cd $PROJECT_ROOT && mvn package

# Ensure your server is stopped
$NUXEO_HOME/bin/nuxeoctl stop

# Install your bundle
$NUXEO_HOME/bin/nuxeoctl mp-install $PROJECT_ROOT/kotlin-sample-package/target/kotlin-sample-package-*.zip

# Start your server
$NUXEO_HOME/bin/nuxeoctl start

次に、オペレーションの定義を取得し、「curl」を使用して呼び出してみましょう。

# Get Operation Documentation
curl -u Administrator:Administrator http://localhost:8080/nuxeo/site/automation/Document.SampleOperation

# Execute the Operation
curl -H 'Content-Type:application/json+nxrequest' -X POST -d '{"params":{},"context":{}}' -u Administrator:Administrator http://localhost:8080/nuxeo/api/v1/automation/Document.SampleOperation

このように素晴らしい結果が得られます!

デバッグ

オペレーションの任意の場所に「ブレークポイント」を追加し、IDEリモートデバッグ機能を使用してNuxeo(ポート8787)に接続します。KotlinとJavaの両方で全ステップを実行できるようになります!

Debug

テスト

Kotlinを使用するとコーディングにかかる時間を短縮できますが、コードをテストする必要がなくなるわけではありません!

「TestSampleOperation」ファイルに示されているとおり、テストフレームワークを使用してコードをテストできます。

@RunWith(FeaturesRunner::class)
@Features(AutomationFeature::class)
@Deploy("org.nuxeo.sample.kotlin-sample-kotlin")
open class TestSampleOperation {

    @Inject
    protected lateinit var session: CoreSession

    ...
}

この洗練された最新のプログラミング言語を実際に使用して、その魅力を確かめてください!


タグ付き: Nuxeo Platform, Kotlin, How to