The Rise

As we constantly strive to make the Nuxeo Server better, more modern and more efficient than ever, we turned our attention to the rise of the Kotlin language this time.

Nuxeo KotlinKotlin is a statically typed programming language that runs on the Java Virtual Machine and can be compiled to JavaScript source code created by JetBrains. It is designed to be an industrial-strength object-oriented language and a “better language” than Java, but still be fully interoperable with Java code, allowing organizations to make a gradual migration from Java to Kotlin.

With Google announcing that it is making it possible to write any Android app in Kotlin, the language becomes a first-class one.

Today, we are pleased to announce that you can now develop your Nuxeo bundles in Kotlin!

Kotlin and Java

Kotlin is fully interoperable with Java code and in one bundle you can compile both and make them work together!

How it Works

Project Structure

Like any Maven project structure the Kotlin bundle looks like a Nuxeo Java bundle, except this time you actually use a new folder kotlin, instead of java for your Kotlin code:

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

Of course, you can mix both Java and Kotlin in the same bundle!

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


### First Kotlin Bundle

In order to do that, and to make it easy for you to bootstrap your project, we already created a dedicated template using [Nuxeo CLI](https://doc.nuxeo.com/nxdoc/nuxeo-cli/). Let's create a new bundle with a package and a sample Operation.

```bash # 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

You can answer as below, but feel free to get creative:

`text 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: `

First Kotlin Operation

Here is the generated Kotlin-based Operation that has roughly the same behavior as the Java one:

`kotlin 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)) } } }


Of course, this operation is contributed and mentioned in the MANIFEST like any other Nuxeo bundle.

### Maven Build Plugin

You will notice that we added the [Kotlin Maven build plugin](https://kotlinlang.org/docs/reference/using-maven.html) to compile properly as follows:

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

Deployment

Like any other Nuxeo bundle, you can build your project by running mvn package and put the bundle in your $NUXEO_HOME/nxserver/bundles folder.

But before starting the Nuxeo server, don’t forget to set the related JetBrains Kotlin Runtime library in NUXEO_HOME/nxserver/lib.

The best part is that it is automatically handled using the Nuxeo Package we just created. You don’t have to do anything other than deploying your package.

`bash # 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 `

Next, let’s get the Operation definition and then call it using curl:

`bash # 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 `

Awesome results!

Debugging

Add a “breakpoint” anywhere in your Operation and use your IDE remote debugging feature to connect to Nuxeo (port 8787). You will be able to execute all the steps in both Kotlin and Java!

Debug

Tests

Using Kotlin to code faster will not protect you against the need to test it. Sorry about that!

As you can see in the TestSampleOperation file, you can use our Test Framework:

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

@Inject protected lateinit var session: CoreSession

… } ` Try it out and have fun with this modern and elegant language!