Exploiter la puissance de Kotlin dans Nuxeo


Tue 23 May 2017 Par Arnaud Kervern, Vladimir Pasquier

L'ascension

Dans notre volonté de rendre Nuxeo Server plus efficace, plus moderne et plus performant que jamais, notre attention s'est tout naturellement tournée vers le langage de programmation Kotlin.

Kotlin est un langage de programmation créé par JetBrains qui dispose d'un typage statique et qui permet de compiler pour la Machine virtuelle Java et JavaScript. Il a été conçu dans l'optique de proposer un langage professionnel orienté objet "plus efficace" que Java mais entièrement interopérable avec le code Java pour permettre aux organisations de migrer progressivement de Java à Kotlin.

Kotlin est désormais un langage de première classe après l'annonce de Google qui en a fait le second langage de programmation supporté officiellement sur Android.

Aujourd'hui, nous sommes ravis de vous annoncer que vous pouvez maintenant développer vos bundles Nuxeo en Kotlin !

Kotlin et Java

Kotlin est entièrement interopérable avec le code Java. Vous pouvez donc compiler les deux langages dans un même bundle et les faire collaborer !

Comment ça fonctionne

Structure du projet

Comme n'importe quelle structure de projet Maven, le bundle Kotlin ressemble à un bundle Nuxeo Java. La seule différence étant que vous allez utiliser un nouveau répertoire kotlin et non pas java pour stocker votre code Kotlin :

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

Bien sûr, vous pouvez mélanger Java et Kotlin dans le même bundle !

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

Premier bundle Kotlin

Pour y parvenir, et pour faciliter le démarrage de votre projet, nous avons déjà créé un modèle dédié à l'aide de Nuxeo CLI. Commençons par créer un nouveau bundle avec un package et une opération de test.

# Assurez-vous d'avoir la dernière version
nuxeo update

# Vous pouvez créer un bundle vide avec
# nuxeo bootstrap kotlin-module
# Mais dans la suite de cet article, nous allons créer un exemple plus complet
mkdir kotlin-sample && cd $_
nuxeo bootstrap kotlin-operation package

Vous pouvez utiliser les réponses ci-dessous, mais n'hésitez pas à faire preuve de créativité :

     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:

Première opération Kotlin

Voici l'opération Kotlin générée qui adopte globalement le même comportement que l'opération 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))
        }
    }
}

Bien sûr, cette opération est évoquée dans le MANIFEST, comme n'importe quel bundle Nuxeo.

Plug-in de génération Maven

Vous remarquerez que nous avons ajouté le plug-in de génération Maven pour Kotlin pour obtenir une compilation propre :

<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>

Déploiement

Comme n'importe quel bundle Nuxeo, vous pouvez générer votre projet en exécutant mvn package et en plaçant le bundle dans votre répertoire $NUXEO_HOME/nxserver/bundles.

Mais avant de démarrer le serveur Nuxeo, n'oubliez pas de configurer la bibliothèque Runtime Kotlin de JetBrains dans NUXEO_HOME/nxserver/lib.

Ce qu'il y a de mieux, c'est que tout est géré automatiquement à l'aide du package Nuxeo que nous venons de créer. Vous avez uniquement besoin de déployer votre package.

# Générez l'intégralité du bundle
cd $PROJECT_ROOT && mvn package

# Assurez-vous que le serveur est arrêté
$NUXEO_HOME/bin/nuxeoctl stop

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

# Démarrez le serveur
$NUXEO_HOME/bin/nuxeoctl start

Ensuite, récupérez la définition de l'opération et appelez-la avec curl :

# Récupérez la documentation de l'opération
curl -u Administrator:Administrator http://localhost:8080/nuxeo/site/automation/Document.SampleOperation

# Exécutez l'opération
curl -H 'Content-Type:application/json+nxrequest' -X POST -d '{"params":{},"context":{}}' -u Administrator:Administrator http://localhost:8080/nuxeo/api/v1/automation/Document.SampleOperation

Incroyable !

Debugging

Ajoutez un "breakpoint" dans votre opération et utilisez la fonctionnalité de debugging à distance de votre environnement de développement pour vous connecter à Nuxeo (port 8787). Vous pourrez effectuer toutes ces étapes dans Kotlin et Java !

Debug

Tests

Utiliser Kotlin pour écrire plus rapidement votre code ne vous évitera pas de le tester. Désolé !

Comme vous pouvez le voir dans le fichier TestSampleOperation, vous pouvez utiliser notre framework de test :

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

    @Inject
    protected lateinit var session: CoreSession

    ...
}

Faites des essais et amusez-vous avec ce langage à la fois moderne et élégant !


Tagged: Nuxeo Platform, Kotlin, How to