How to use Kotlin in your plugins

Jul 28, 2017
How to use Kotlin in your plugins
  • For those of you who do not know Kotlin, it is an open source JVM language created by JetBrains (the same company who make IntelliJ Idea). It's extremely similar to Java, in face, it can interface with Java and Java can mostly interface with Kotlin. It compiles to bytecode / a jar file, meaning that you can use it for plugins. If you don't know it yet, you can learn it in under an hour using JetBrain's documentation.

    Here's an example of a method that will take a list and select the even numbers from it:
    Code (Text):
    val numbers = listOf(1, 2, 3, 4, 6, 9, 37, 89)
    fun getEvens(): List<Int> = numbers.stream().filter { it % 2 == 0 }.collect(Collectors.toList())
    Since Kotlin is developed by JetBrains, IntelliJ Idea comes bundled with it, meaning you don't have to do anything to install it. However, if you use Eclipse (I highly suggest you move to IntelliJ btw), you can install this plugin. For this tutorial, I will be using IntelliJ Idea 2017.1.5 (although any version released since 2015 iirc will work). I'll also be starting a new project, although you can use an existing maven / gradle project. First off, I'll cover how to do it in gradle (recommended). Scroll down for the maven tutorial.

    Gradle
    I'm not too good at gradle, so if you notice anything wrong, please fix it. Anyway, gradle is a lot easier than maven as it will set most things up for you manually. So, let's get started!

    First, go to File -> New -> New Project.
    This menu will pop up:
    [​IMG]

    Java is selected by default, but you need to tick "Kotlin (Java)" too for it to setup kotlin as a dependency. Then hit next. You'll be asked for a Group ID and an ArtifactID. Your GroupId should be your package name and your ArtifactId should be the final name of your jar. You can change Version if you want, or you can leave it as is. Here's an example:
    [​IMG]

    Hit next and you'll be greeted with a gradle configuration screen. Tick "Use auto-import". The rest of the defaults should be fine, unless you need to set your java home (which you probably have done anyway).
    [​IMG]

    Then hit finish to create your project. Before you get started programming, we need to do 1 more thing. Open your build.gradle:
    [​IMG]

    As you can see, kotlin has been setup. However, we need to setup shadowing (the gradle equivalent of maven shade) to include kotlin in your jar. First, you need to install & apply the plugin. Take a look at your buildscript (right at the top). Replace it with this:
    Code (Text):
    buildscript {
        ext.kotlin_version = '1.1.3-2'

        repositories {
            mavenCentral()
            jcenter()
        }
        dependencies {
            classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
            classpath 'com.github.jengelman.gradle.plugins:shadow:2.0.1'
        }
    }
    Then just under that, apply the plugin:
    Code (Text):
    apply plugin: 'com.github.johnrengelman.shadow'
    Next, go to the bottom of your build.gradle and add this:
    Code (Text):
    shadowJar {
        dependencies {
            include(dependency("org.jetbrains.kotlin:kotlin-stdlib"))
        }
    }
    You can shadow more dependencies by duplicating that line and replace the "org.jetbrains.kotlin:kotlin-stdlib" with groupId:artifactId.

    Your entire build.gradle should somethinglook like this:
    Code (Text):
    group 'com.perkelle.dev.kotlingradle'
    version '1.0-SNAPSHOT'

    buildscript {
        ext.kotlin_version = '1.1.3-2'

        repositories {
            mavenCentral()
            jcenter()
        }
        dependencies {
            classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
            classpath 'com.github.jengelman.gradle.plugins:shadow:2.0.1'
        }
    }

    apply plugin: 'kotlin'
    apply plugin: 'com.github.johnrengelman.shadow'

    sourceCompatibility = 1.8

    repositories {
        mavenCentral()
    }

    dependencies {
        compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
        testCompile group: 'junit', name: 'junit', version: '4.12'
    }

    compileKotlin {
        kotlinOptions.jvmTarget = "1.8"
    }
    compileTestKotlin {
        kotlinOptions.jvmTarget = "1.8"
    }

    shadowJar {
        dependencies {
            include(dependency("org.jetbrains.kotlin:kotlin-stdlib"))
        }
    }
    Now you can go and write your code! Write your kotlin in the kotlin module and your java in the java module, like this:
    [​IMG]

    When you've finished, you open your project folder and open a terminal. The next step depends on your OS.

    Linux
    You should probably install gradle as it will make everything a lot easier. I'm using kubuntu, but any debian-based OS will be the same:
    Code (Text):
    sudo apt-get install gradle
    Then build using:
    Code (Text):
    gradle shadowJar
    Or, if you don't want to install gradle, you can use the gradle wrapper:
    Code (Text):
    ./gradlew shadowJar
    The output will be in build/libs. As you can see, your jar contains kotlin:
    [​IMG]

    And that's it. You're done!

    Windows
    You can install or gradle and add it to your path (recommended) or use the wrapper.
    If you want to install it, follow this tutorial and then run
    Code (Text):
    gradle shadowJar
    Or, if you don't want to install gradle, you can use the wrapper by running
    Code (Text):
    gradlew.bat shadowJar
    The output will be in build/libs. As you can see, your jar contains kotlin:
    [​IMG]

    And that's it. You're done!

    Maven

    Ok, so, you'll want to create a new project by going to File -> New Project. Then, instead of clicking Java, you'll want to click on maven:
    [​IMG]

    Don't bother with choosing an archetype, just hit next. On this screen, you'll be asked for a GroupId, an ArtifactId and a version. You can leave version as it is, but for GroupId, you'll want to put your package name and for ArtifactId, you'll want to put the final name of the jar file (excluding the .jar). You can get a better idea of what I mean by looking at the next image (click the button):
    [​IMG]

    Hit Next then Finish (unless you want to change your project name or location). Your project will now open and you'll be greeted with your pom.xml. This contains your dependences and build information. This means you don't have to manually import your spigot jar file. A blank pom.xml will look like this:

    Code (Text):
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>

        <groupId>com.perkelle.dev.kotlintutorial</groupId>
        <artifactId>KotlinTutorial</artifactId>
        <version>1.0-SNAPSHOT</version>


    </project>
    If you have any experience with HTML, this is pretty much exactly the same but with different tags.

    Next, you'll want to look at the bottom right corner of your screen and press "Enable Auto-Import". This means that when you add a dependency, it will automatically download it.
    [​IMG]

    Next, you'll want to import spigot (although you can use bungeecord if you like) by adding these lines above the </project> tag:
    Code (Text):
    <repositories>
            <repository>
                <id>spigot-repo</id>
                <url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
            </repository>
        </repositories>
        <dependencies>
            <dependency>
                <groupId>org.spigotmc</groupId>
                <artifactId>spigot-api</artifactId>
                <version>1.12-R0.1-SNAPSHOT</version>
                <scope>provided</scope>
            </dependency>
        </dependencies>
    You can view a full list of version names here.

    Next, I like to rename this my "java" folder to "kotlin". You can do this by expanding the directory list, clicking on java (it will be a blue folder) and then pressing Shift+F6. A rename menu will automatically open.
    [​IMG]

    Now, you'll want to set the Kotlin version. You can do it by adding the following lines:
    Code (Text):
    <properties>
            <kotlin.version>1.1.3-2</kotlin.version>
        </properties>
    The current version is 1.1.3-2 as of 17/7/17, so obviously you'll want to change this when the next release comes out. I'll tell you about this in a bit.

    Now, you'll want to add Kotlin as a dependency. You can do this by adding the following lines inside of your <dependency></dependency> tags that you created earlier:
    Code (Text):
    <dependency>
                <groupId>org.jetbrains.kotlin</groupId>
                <artifactId>kotlin-stdlib</artifactId>
                <version>${kotlin.version}</version>
            </dependency>
            <dependency>
                <groupId>org.jetbrains.kotlin</groupId>
                <artifactId>kotlin-test-junit</artifactId>
                <version>${kotlin.version}</version>
                <scope>test</scope>
            </dependency>
    If your Kotlin version does not exist, the versions will show up as red. If they are out of date, they will be highlighted in yellow.

    You'll be able to use Kotlin now! However, you need to do 1 more thing for you to be able to use your plugins. You need to tell maven to shade Kotlin into your jar, meaning it will contain Kotlin and be close to 1MB in size. Here is what you need:

    Code (Text):
    <build>
            <sourceDirectory>src/main/kotlin</sourceDirectory>
            <plugins>
                <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>
                            <configuration>
                                <sourceDirs>
                                    <sourceDir>${project.basedir}/src/main/kotlin</sourceDir>
                                </sourceDirs>
                            </configuration>
                        </execution>
                        <execution>
                            <id>test-compile</id>
                            <goals> <goal>test-compile</goal> </goals>
                            <configuration>
                                <sourceDirs>
                                    <sourceDir>${project.basedir}/src/test/kotlin</sourceDir>
                                </sourceDirs>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.5.1</version>
                    <executions>
                        <execution>
                            <id>default-compile</id>
                            <phase>none</phase>
                        </execution>
                        <execution>
                            <id>default-testCompile</id>
                            <phase>none</phase>
                        </execution>
                        <execution>
                            <id>java-compile</id>
                            <phase>compile</phase>
                            <goals> <goal>compile</goal> </goals>
                        </execution>
                        <execution>
                            <id>java-test-compile</id>
                            <phase>test-compile</phase>
                            <goals> <goal>testCompile</goal> </goals>
                        </execution>
                    </executions>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-shade-plugin</artifactId>
                    <version>3.0.0</version>
                    <executions>
                        <execution>
                            <phase>package</phase>
                            <goals>
                                <goal>shade</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    Yeah, pretty long. Your entire pom.xml should look something like this now:
    Code (Text):
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>

        <groupId>com.perkelle.dev.kotlintutorial</groupId>
        <artifactId>KotlinTutorial</artifactId>
        <version>1.0-SNAPSHOT</version>

        <properties>
            <kotlin.version>1.1.3-2</kotlin.version>
        </properties>

        <repositories>
            <repository>
                <id>spigot-repo</id>
                <url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
            </repository>
        </repositories>
        <dependencies>
            <dependency>
                <groupId>org.jetbrains.kotlin</groupId>
                <artifactId>kotlin-stdlib</artifactId>
                <version>${kotlin.version}</version>
            </dependency>
            <dependency>
                <groupId>org.jetbrains.kotlin</groupId>
                <artifactId>kotlin-test-junit</artifactId>
                <version>${kotlin.version}</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.spigotmc</groupId>
                <artifactId>spigot-api</artifactId>
                <version>1.11.2-R0.1-SNAPSHOT</version>
                <scope>provided</scope>
            </dependency>
        </dependencies>

        <build>
            <sourceDirectory>src/main/kotlin</sourceDirectory>
            <resources>
                <resource>
                    <directory>${project.basedir}/src/main/resources</directory>
                    <filtering>false</filtering>
                    <includes>
                        <include>plugin.yml</include>
                    </includes>
                </resource>
            </resources>
            <plugins>
                <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>
                            <configuration>
                                <sourceDirs>
                                    <sourceDir>${project.basedir}/src/main/kotlin</sourceDir>
                                </sourceDirs>
                            </configuration>
                        </execution>
                            <id>test-compile</id>
                            <goals> <goal>test-compile</goal> </goals>
                            <configuration>
                                <sourceDirs>
                                    <sourceDir>${project.basedir}/src/test/kotlin</sourceDir>
                                </sourceDirs>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.5.1</version>
                    <executions>
                        <execution>
                            <id>default-compile</id>
                            <phase>none</phase>
                        </execution>
                        <execution>
                            <id>default-testCompile</id>
                            <phase>none</phase>
                        </execution>
                        <execution>
                            <id>java-compile</id>
                            <phase>compile</phase>
                            <goals> <goal>compile</goal> </goals>
                        </execution>
                        <execution>
                            <id>java-test-compile</id>
                            <phase>test-compile</phase>
                            <goals> <goal>testCompile</goal> </goals>
                        </execution>
                    </executions>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-shade-plugin</artifactId>
                    <version>3.0.0</version>
                    <executions>
                        <execution>
                            <phase>package</phase>
                            <goals>
                                <goal>shade</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    </project>
    1 limitation of Kotlin is that you cannot compile your jar within IntellIj, you'll need to use maven. When this time comes, you'll need to install Git Bash and Maven. Then you can open the source folder, open Git Bash and run "mvn install":
    <execution>
    [​IMG]

    [​IMG]

    [​IMG]

    Maven will create a folder called "target", which will contain the final jar:
    [​IMG]

    And that's it! You just made your first plugin in Kotlin!

    Final Note
    If you see anything wrong, feel free to update this wiki entry.
    I made this post in honour / memory of @Proximyst since she was the one who introduced me to Kotlin
  • Loading...
  • Loading...