Programming Kotlin

4.1 (11 reviews total)
By Stephen Samuel , Stefan Bocutiu
  • Instant online access to over 7,500+ books and videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies
  1. Getting Started with Kotlin

About this book

Kotlin has been making waves ever since it was open sourced by JetBrains in 2011; it has been praised by developers across the world and is already being adopted by companies. This book provides a detailed introduction to Kotlin that shows you all its features and will enable you to write Kotlin code to production.

We start with the basics: get you familiar with running Kotlin code, setting up, tools, and instructions that you can use to write basic programs. Next, we cover object oriented code: functions, lambdas, and properties - all while using Kotlin's new features.

Then, we move on to null safety aspects and type parameterization. We show you how to destructure expressions and even write your own. We also take you through important topics like testing, concurrency, microservices, and a whole lot more. By the end of this book you will be able to compose different services and build your own applications.

Publication date:
January 2017
Publisher
Packt
Pages
420
ISBN
9781787126367

 

Chapter 1. Getting Started with Kotlin

It is time to write code. In this chapter, we will go over and write the typical entry code for every language: the famous Hello World! In order to do that, we will need to set up the initial environment required to develop software with Kotlin. We will provide a few examples using the compiler from the command line, and then we will move towards the typical way of programming using the IDEs and build tools available.

Kotlin is a JVM language, and so the compiler will emit Java bytecode. Because of this, of course, Kotlin code can call Java code, and vice versa! Therefore, you need to have the Java JDK installed on your machine. To be able to write code for Android, where the most recent supported Java version is 6, the compiler needs to translate your code to bytecode that is compatible at least with Java 6. For this book, however, all the code examples will be run with Java JDK 8. If you are new to the JVM world, you can get the latest version from http://www.oracle.com/technetwork/java/javase/downloads/index.html.

In this chapter you will learn how to:

  • Use the command line to compile and execute code written in Kotlin

  • Use the REPL and write Kotlin scripts

  • Create a gradle project with Kotlin enabled

  • Create a Maven project with Kotlin enabled

  • Use IntelliJ to create a Kotlin project

  • Use Eclipse IDE to create a Kotlin project

  • Mix Kotlin and Java code in the same project

 

Using the command line to compile and run Kotlin code


To write and execute code written in Kotlin, you will need its runtime and the compiler. At the time of writing, version 1.1 milestone 4 is available (the stable release is 1.0.6). Every runtime release comes with its own compiler version. To get your hands on it, navigate to https://github.com/JetBrains/kotlin/releases/tag/v1.1-M04, scroll to the bottom of the page, and download and unpack the ZIP archive kotlin-compiler-1.1-M04.zip to a known location on your machine. The output folder will contain a subfolder bin with all the scripts required to compile and run Kotlin on Windows, Linux, or OS X. Now you need to make sure the bin folder location is part of your system PATH in order to call the kotlinc without having to specify the full path.

If your machine runs Linux or OS X, there is an even easier way to install the compiler by using sdkman. All you need to do is execute the following commands in a terminal:

$ curl -s https://get.sdkman.io | bash
$ bash
$ sdk install kotlin 1.1-M04

Alternatively, if you are using OS X and you have homebrew installed, you could run these commands to achieve the same thing:

$ brew update

$ brew install  [email protected]

Now that all of this is done, we can finally write our first Kotlin code. The application we will be writing does nothing else but display the text Hello World! on the console. Start by creating a new file named HelloWorld.kt and type the following:

    fun main(args: Array<String>) { 
      println("Hello, World!") 
    } 

From the command line, invoke the compiler to produce the JAR assembly (include-runtime is a flag for the compiler to produce a self-contained and runnable JAR by including the Kotlin runtime into the resulting assembly):

kotlinc HelloWorld.kt -include-runtime -d HelloWorld.jar

Now you are ready to run your program by typing the following on your command line; it is assumed your JAVA_HOME is set and added to the system path:

$ java -jar HelloWorld.jar

The code is pretty straight forward. It defines the entry point function for your program, and in the first and only line of code, it prints the text to the console.

If you have been working with the Java or Scala languages, you might raise an eyebrow because you noticed the lack of the typical class that would normally define the standard static main program entry point. How does it work then? Let's have a look at what actually happens. First, let's just compile the preceding code by running the following command. This will create a HelloWorld.class in the same folder:

$ kotlinc HelloWorld.kt

Now that we have the bytecode generated, let's look at it by using the javap tool available with the JDK (please note that the file name contains a suffix Kt):

$ javap -c HelloWorldKt.class

Once the execution completes, you should see the following printed on your terminal:

Compiled from "HelloWorld.kt"
public final class HelloWorldKt {
  public static final void main(java.lang.String[]);
    Code:
      0: aload_0
      1: ldc           #9                  // String args
      3: invokestatic  #15                 // Method  kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull:(Ljava/lang/Ob ject;Ljava/lang/String;)V
      6: ldc           #17                 // String Hello, World!
      8: astore_1
      9: nop
      10: getstatic     #23                 // Field  java/lang/System.out:Ljava/io/PrintStream;
      13: aload_1
      14: invokevirtual #29                 // Method  java/io/PrintStream.println:(Ljava/lang/Object;)V
      17: return
}

You don't have to be an expert in bytecode to understand what the compiler has actually done for us. As you can see on the snippet, a class has been generated for us, and it contains the program entry point with the instructions to print Hello World! to the console.

I would not expect you to work with the command line compiler on a daily basis; rather, you should  use the tools at hand to delegate this, as we will see shortly.

 

Kotlin runtime


When we compiled Hello World! and produced the JAR, we instructed the compiler to bundle in the Kotlin runtime. Why is the runtime needed? Take a closer look at the bytecode generated, if you haven't already. To be more specific, look at line 3. It invokes a method to validate that the args variable is not null; thus, if you compile the code without asking for the runtime to be bundled in and try to run it, you will get an exception.

$ kotlinc HelloWorld.kt -d HelloWorld.jar
$ java -jar HelloWorld.jar
Exception in thread "main" java.lang.NoClassDefFoundError:  kotlin/jvm/internal/Intrinsics
at HelloWorldKt.main(HelloWorld.kt)
Caused by: java.lang.ClassNotFoundException:  kotlin.jvm.internal.Intrinsics

The runtime footprint is very small; with ~800 K one can't argue otherwise. Kotlin comes with its own standard class library (Kotlin runtime), which is different from the Java library. As a result, you need to merge it into the resulting JAR, or provide it in the classpath:

$ java -cp $KOTLIN_HOME/lib/kotlin-runtime.jar:HelloWorld.jar  HelloWorldKt

If you develop a library for the exclusive use of other Kotlin libraries or applications, then you don't have to include the runtime. Alternatively there is a shorter path. This is done via a flag passed to the Kotlin compiler:

$kotlinc -include-runtime HelloWorld.kt -d HelloWorld
 

The REPL


These days, most languages provide an interactive shell, and Kotlin is no exception. If you want to quickly write some code that you won't use again, then the REPL is a good tool to have. Some prefer to quickly test their methods, but you should always write unit tests rather than using the REPL to validate that the output is correct.

You can start the REPL by adding dependencies to the classpath in order to make them available within the instance. To give an example, we will use the Joda library to deal with the date and time. First, we need to download the JAR. In a terminal window, use the following commands:

$ wget https://github.com/JodaOrg/joda-time/releases/download/v2.9.4/joda-time-2.9.4-dist.tar.gz
$ tar xvf joda-time-2.9.4-dist.tar.gz

Now you are ready to start the REPL, attach the Joda library to its running instance, and import and use the classes it provides:

$ kotlinc-jvm -cp joda-time-2.9.4/joda-time-2.9.4.jar
Welcome to Kotlin version 1.1-M04 (JRE 1.8.0_66-internal-b17)
Type :help for help, :quit for quit
>>> import org.joda.time.DateTime
>>> DateTime.now()
2016-08-25T22:53:41.017+01:00
 

Kotlin for scripting


Kotlin can also be run as a script. If bash or Perl is not for you, now you have an alternative.

Say you want to delete all the files older than N given days. The following code example does just that:

    import java.io.File 
    val purgeTime = System.currentTimeMillis() - args[1].toLong() * 24  * 60 * 60 * 1000 
    val folders = File(args[0]).listFiles { file -> file.isFile } 
    folders ?.filter { 
      file -> file.lastModified() < purgeTime } 
    ?.forEach { 
      file -> println("Deleting ${file.absolutePath}") 
      file.delete() 
    } 

Create a file named delete.kts with the preceding content. Please note the predefined variable args, which contains all the incoming parameters passed when it is invoked. You might wonder what is the ? character doing there. If you are familiar with the C# language and you know about nullable classes, you already have the answer. Even though you might not have come across it, I am sure you have a good idea of what it does. The character is called the safe call operator, and, as you will find out later in the book when the subject is discussed in greater length, it avoids the dreadful NullPointerException error.

The script takes two arguments: the target folder, and then the number of days threshold. For each file it finds in the target, it will check the last time it was modified; if it is less than the computed purge time, it will delete it. The preceding script has left out error handling; we leave this to the reader as an exercise.

Now the script is available, it can be invoked by running the following:

$ kotlinc -script delete.kts . 5

If you copy/create files in the current folder with a last modified timestamp older than five days, it will remove them.

 

Kotlin with Gradle


If you are familiar with the build tool landscape, you might be in one of three camps: Maven, Gradle, or SBT (more likely if you are a Scala dev). I am not going to go into the details, but we will present the basics of Gradle, the modern open source polyglot build automation system, and leave it up to the curious to find out more from http://gradle.org. Before we continue, please make sure you have it installed and available in your classpath in order to be accessible from the terminal. If you have SDKMAN, you can install it using this command:

$ sdk install gradle 3.0

The build system comes with some baked-in templates, although limited, and in its latest 3.0 version Kotlin is not yet included. Hopefully, this shortfall will be dealt with sooner rather than later. However, it takes very little to configure support for it. First, let's see how you can interrogate for the available templates:

$ gradle help --task :init

You should see the following being printed out on the terminal:

Options
--type  Set type of build to create.
Available values are:
basic
groovy-library
java-library
pom
scala-library

Let's go and use the Java template and create our project structure by executing this bash command:

$ gradle init --type java-library

This template will generate a bunch of files and folders; if you have been using Maven, you will see that this structure is similar:

Project Folders layout

As it stands, the Gradle project is not ready for Kotlin. First, go ahead and delete Library.java and LibraryTest.java, and create a new folder named kotlin, a sibling of the java one. Then, using a text editor, open the build.gradle file. We need to add the plugin enabling the Gradle system to compile Kotlin code for us, so at the top of your file you have to add the following snippet:

    buildscript {
      ext.kotlin_version = '1.1-M04'

      repositories {
        maven { url "https://dl.bintray.com/kotlin/kotlin-dev" }
        mavenCentral()
      }
      dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
      }
    }

The preceding instructions tell Gradle to use the plugin for Kotlin, and set the dependency maven repository. Since Kotlin 1.1 is only at milestone 4, there is a specific repository to pick it from. See last entry in repositories. We are not done yet; we still need to enable the plugin. The template generated will already have an applied plugin: java. Replace it with the following:

    apply plugin: 'kotlin' 
    apply plugin: 'application' 
    mainClassName = 'com.programming.kotlin.chapter01.ProgramKt' 

Now Kotlin plugin support is enabled; you may have noticed that we have also added the application plugin, and set the class containing the program entry point. The reason for this is to allow the program to run directly, as we will see shortly.

We are not quite done. We still need to link to the Kotlin standard library. Replace the repositories and dependencies sections with the following:

    repositories {
      maven { url "https://dl.bintray.com/kotlin/kotlin-dev" }
      mavenCentral()
    } 
    dependencies { 
      compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" 
      testCompile 'io.kotlintest:kotlintest:1.3.3' 
    } 

Now let's create the file named HelloWorld.Kt. This time, we will set a namespace and thus avoid having our class as part of the default one. If you are not yet familiar with the term, don't worry; it will be covered in the next chapter.

From the terminal, run the following:

$ mkdir -p src/main/kotlin/com/programming/kotlin/chapter01
$ echo "" >> src/main/kotlin/com/programming/kotlin/chapter01/Program.kt
$ cat <<EOF >> src/main/kotlin/com/programming/kotlin/chapter01/Program.kt
package com.programming.kotlin.chapter01
fun main(args: Array<String>) {
  println("Hello World!")
}

We are now in a position to build and run the application:

$ gradle build
$ gradle run

Now we want to be able to run our program using java -jar [artefact]. Before we can do that, we need to adapt the build.gradle. First, we need to create a manifest file and set the main class; the JVM will look for the main function to start executing it:

    jar { 
      manifest { 
        attributes( 
          'Main-Class': 'com.programming.kotlin.chapter01.ProgramKt' 
        ) 
      } 
      from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } } 
    } 

Furthermore, we also embed into the JAR the dependency for kotlin-stdlib, as well as kotlin-runtime. If we leave out these dependencies, we will need to add them to the classpath  when we run the application. Now you are ready to build and run the code.

 

Kotlin with Maven


If you still prefer to stick with good old Maven, there is no problem. There is a plugin for it to support Kotlin as well. If you don't have Maven on your machine, you can follow the instructions at https://maven.apache.org/install.html to get it installed on your local machine.

Just as we did with Gradle, let's use the built-in templates to generate the project folder and file structure. From the terminal, within a brand new folder, you will have to run the following command:

$ mvn archetype:generate -DgroupId=com.programming.kotlin - DartifactId=chapter01 -DarchetypeArtifactId=maven-archetype- quickstart -DinteractiveMode=false

This will generate the pom.xml file and the src folder for Maven. But before we add the file containing the kotlin code, we need to enable the plugin. Just as before, start by deleting App.java and AppTest.java from src/main/java/com/programming/kotlin and test/main/java/com/programming/kotlin/, and create the src/kotlin folder (the subdirectory structure matches the namespace name):

$ mkdir -p src/main/kotlin/com/programming/kotlin/chapter01
$ mkdir -p src/test/kotlin/com/programming/kotlin/chapter01

In an editor of your choice, open up the generated pom.xml file and add the following:

    <pluginRepositories>
      <pluginRepository>
        <snapshots>
          <enabled>true</enabled>
        </snapshots>
        <id>bintray-kotlin-kotlin-dev</id>
        <name>bintray</name>
        <url>http://dl.bintray.com/kotlin/kotlin-dev</url>
      </pluginRepository>
    </pluginRepositories>

    <repositories>
      <repository>
        <snapshots>
          <enabled>true</enabled>
        </snapshots>
        <id>bintray-kotlin-kotlin-dev</id>
        <name>bintray</name>
        <url>http://dl.bintray.com/kotlin/kotlin-dev</url>
      </repository>
    </repositories>
    <properties>
      <kotlin.version>1.1-M04</kotlin.version> 
      <kotlin.test.version>1.3.3</kotlin.test.version> 
    </properties> 
  
    <build> 
       <sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirecto ry> 
       <testSourceDirectory>${project.basedir}/src/test/kotlin</testSourc eDirectory> 
     <plugins> 
        <plugin> 
          <artifactId>kotlin-maven-plugin</artifactId> 
          <groupId>org.jetbrains.kotlin</groupId> 
          <version>${kotlin.version}</version> 
 
          <executions> 
            <execution> 
              <id>compile</id> 
              <phase>process-sources</phase> 
              <goals> <goal>compile</goal> </goals> 
            </execution> 
 
            <execution> 
              <id>test-compile</id> 
              <phase>process-test-sources</phase> 
              <goals> <goal>test-compile</goal> </goals> 
            </execution> 
          </executions> 
        </plugin> 
      </plugins> 
     </build> 

All we have done so far is to enable the Kotlin plugin and make it run in the process-stages phase to allow the mixing of Java code as well. There are cases when you might have part of the source code written in good old Java. I am sure you also noticed the addition of source directory tags, allowing for the kotlin files to be included in the build.

The only thing left to do now is to add the library dependencies for the Kotlin runtime as well as the unit tests. We are not going to touch upon the testing framework until later in the book. Replace the entire dependencies section with the following:

     <dependencies> 
       <dependency> 
          <groupId>org.jetbrains.kotlin</groupId> 
          <artifactId>kotlin-stdlib</artifactId> 
          <version>${kotlin.version}</version> 
        </dependency> 
   
        <dependency> 
          <groupId>io.kotlintest</groupId> 
          <artifactId>kotlintest</artifactId> 
          <version>${kotlin.test.version}</version> 
          <scope>test</scope> 
        </dependency> 
      </dependencies> 

It is time now to add the Hello World! code; this step is similar to the one we took earlier when we discussed Gradle:

$ echo "" >> src/main/kotlin/com/programming/kotlin/chapter01/Program.kt
$cat <<EOF >> src/main/kotlin/com/programming/kotlin/chapter01/Program.kt
    package com.programming.kotlin.chapter01
    fun main(args: Array<String>) {
      println("Hello World!")
    }

We are now in a position to compile and build the JAR file for the sample program:

$ mvn package
$ mvn exec:java - Dexec.mainClass="com.programming.kotlin.chapter01.ProgramKt"

The last instruction should end up printing the Hello World! text to the console. Of course we can run the program outside Maven by going back to executing Java, but we need to add the Kotlin runtime to the classpath:

$java -cp $KOTLIN_HOME/lib/kotlin-runtime.jar:target/chapter01-1.0- SNAPSHOT.jar "com.programming.kotlin.chapter01.ProgramKt"

If you want to avoid the Classpath dependency setup when you run the application, there is an option to bundle all the dependencies in the resulted JAR and produce what is called a fat jar. For that, however, another plugin needs to be added:

    <plugin> 
      <groupId>org.apache.maven.plugins</groupId> 
      <artifactId>maven-shade-plugin</artifactId> 
      <version>2.4.3</version> 
      <executions> 
        <execution> 
          <phase>package</phase> 
          <goals> 
            <goal>shade</goal> 
          </goals> 
           <configuration> 
            <transformers> 
              <transformer  implementation="org.apache.maven.plugins.shade.resource.ManifestRe sourceTransformer"> 
                 <mainClass>com.programming.kotlin.chapter01.ProgramKt</mainClass> 
              </transformer> 
            </transformers> 
          </configuration> 
        </execution> 
      </executions> 
    </plugin> 

We can execute the command to run our JAR without having to worry about setting the classpath since this has been taken care of by the plugin:

$ java -jar target/chapter01-1.0-SNAPSHOT.jar
 

IntelliJ and Kotlin


Coding using Vim/nano is not everyone's first choice; working without the help of an IDE with its code completion, intelli-sense, shortcuts for adding files, or refactoring code can prove challenging the more complex the project is.

For a while now, in the JVM world, people's first choice when it comes to their integrated development environment has been IntelliJ. The tool is made by the same company that created Kotlin: JetBrains. Given the integration between the two of them, it would be my first choice of IDE to use, but, as we will see in the next section it is not the only option.

IntelliJ comes in two versions: Ultimate and Community (free). For the code we will be using in the course of this book, the free version is enough. If you don't have it already installed, you can download it from https://www.jetbrains.com/idea/download.

From version 15.0, IntelliJ comes bundled with Kotlin, but if you have an older version you can still get support for the language by installing the plugin. Just go to Settings|Plugins| Install IntelliJ plugins and type Kotlin in the search.

We are going to use the IDE to create a Gradle project with Kotlin enabled, just as we did in the previous section. Once you have started IntelliJ, you will have to choose Create new project. You will get a dialog window from which you should select Gradle from the left-hand side section; check the Kotlin(Java) option from the right-hand side. As you can see here:

Selecting a project type

You should already have the system variable JAVA_HOME set up for the tool to pick it up automatically (see the Project SDK at the top of the screenshot). If this isn't the case, choose the New button and navigate to where your Java JDK is. Once you have selected it, you are ready to go to the next step by clicking on the Next button available on the bottom right-hand side of the screen.

The next window presented to you is asking you to provide the Group Id and Artifact Id. Let's go with com.programming.kotlin and chapter01 respectively. Once you have completed the fields, you can move to the next step of the process where you tick the Use auto-import flag as well as Create directories for empty directory roots automatically. Now carry on to the next step, where you are asked where you wish to store the project on your machine. Set the project location, expand More Settings, type chapter01 for the Module name, and hit the Finish button.

IntelliJ will go on and create the project, and you should have the outcome shown in the following screenshot:

Hello World! basic project

On the selected kotlin folder, right-click and choose the New | Package option, and type com.programming.kotlin.chapter01:

Setting up the package name

Below the kotlin folder, you should see a new one appear, matching what was typed earlier. Right click on that, choose New | Kotlin File/Class, and type Program.kt:

Creating Program.kt file

We are now ready to start typing our Hello World! Use the same code we created earlier in the chapter. You should notice the Kotlin brand icon on the left-hand side of the file editor. If you click on it, you will get the option to run the code, and if you look at the bottom of your IntelliJ window you should see the text Hello World! printed out:

Hello World! program

Well done! You have written your first Kotlin program. It was easy and quick to set up the project and code, and to run the program. If you prefer, you can have a Maven rather than a Gradle project. When you choose New | Project, you have to select Maven from the left-hand side and check Create from archetype while choosing org.jetbrains.kotlin:kotlin-archetype-jvm from the list presented:

Maven project

 

Eclipse and Kotlin


There might be some of you who still prefer Eclipse IDE to IntelliJ; don't worry, you can still develop Kotlin code without having to move away from it. At this point, I assume you already have the tool installed. From the menu, navigate to Help | Eclipse Marketplace, look for the Kotlin plugin, and install it (I am working with the latest distribution: Eclipse Neon).

Once you have installed the plugin and restarted the IDE, you are ready to create your first Kotlin project. From the menu, choose File | New | Project and you should see the following dialog:

New Kotlin project

Click the Next button to move to the next step and, once you have chosen the source code location, click the Finish button. This is not a Gradle or Maven project! You can choose one of the two, but then you will have to manually modify the build.gradle or pom.xml, as we did manually in the Kotlin with Gradle and Kotlin with Maven sections of this chapter. Similar to the IntelliJ project, click on the src folder, choose New package, and name it com.programming.kotlin.chapter01. To add our Program.kt, you will need to right-click on the newly created package, select New | Other, and select Kotlin | Kotlin File from the list. Once the file has been created, type the simple lines of code to print out the text to the console. You should have the following result in your Eclipse IDE:

Hello World! with Eclipse

Now you are ready to run the code. From the menu select Run | Run. You should be able to trigger the execution, and in the Console tab at the bottom of your IDE you should see the Hello World! text printed out.

 

Mixing Kotlin and Java in a project


Using different languages within the same project is quite common; I came across projects where a mix of Java and Scala files formed the code base. Could we do the same with Kotlin? Absolutely. Let's work on the project created earlier, Kotlin with Gradle. You should see the following directory structure in your IntelliJ (the standard template for a Java/Kotlin project):

Project layout

You can place Java code within the java folder. Add a new package to the java folder with the same name as the one present in the kotlin folder: com.programming.kotlin.chapter01. Create a New | Java class named CarManufacturer.java and use this code for the purpose of the exercise:

    public class CarManufacturer { 
      private final String name; 
      public CarManufacturer(String name) { 
        this.name = name; 
      } 
      public String getName() { 
        return name; 
      } 
    } 

What if you want to add a Java class under the kotlin subfolder? Let's create a Student class similar to the previous one and provide a field name for simplicity:

    public class Student { 
      private final String name; 
      public Student(String name) { 
        this.name = name; 
      } 
      public String getName() { 
        return name; 
      } 
    } 

In the main function, let's instantiate our classes:

    fun main(args: Array<String>) { 
      println("Hellow World!") 
      val student = Student("Alexandra Miller") 
      println("Sudent name:${student.name}") 
      val carManufacturer = CarManufacturer("Mercedes") 
      println("Car manufacturer:${carManufacturer.name}") 
    } 

While the code compiles just fine, trying to run it will throw a runtime exception, saying that it can't find the Student class. We need to let the Java compiler look for code under the src/main/kotlin folder. In your gradle.build, add the following instruction:

    sourceSets { 
      main.java.srcDirs += 'src/main/kotlin' 
    } 

Now we can compile and run the program:

$gradle jar
$ java -jar build/libs/chapter01-1.0-SNAPSHOT.jar

As your Kotlin code gets bigger, compilation will slow down since it will have to go and recompile each file. There is a way to speed it up, though: by only compiling files changed between builds. The easiest way to enable this is to create a file called gradle.properties alongside build.gradle and add kotlin.incremental=true to it. While the first build will not be incremental, the following ones will be, and you should see your compilation time cut down quite a bit.

Maven is still, probably, the most used build system on the JVM. So let's see how we can achieve our goal of mixing Kotlin and Java code in Maven. Starting with IntelliJ, choose New | Project, pick Maven as the option, and look for kotlin-archetype-jvm from the list of archetypes. We already covered this, so it should be a lot easier the second time around. We now have a project.

From the project tree, you will notice that there is no java folder source code created. Go ahead and create src/main/java, followed by the namespace folder com.programming.kotlin (this will be a subfolder of the java one). You will notice that right-clicking on the java folder won't give you the option to create a package. The project is not yet configured to include Java code. But first, what makes Maven handle Kotlin code? If you open the pom.xml file and go to the plugins section, you will notice the kotlin plugin:

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

To add Java code to the mix, we need to set a new plugin that will be able to compile good old Java:

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

The Kotlin compiler has to run before the Java compiler to get it all working, so we will need to amend the Kotlin plugin to do just that:

    <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> 
              <sourceDir>${project.basedir}/src/main/java</sourceDir> 
            </sourceDirs> 
          </configuration> 
        </execution> 
        <execution> 
          <id>test-compile</id> 
          <goals> 
            <goal>test-compile</goal> 
          </goals> 
          <configuration> 
            <sourceDirs> 
              <sourceDir>${project.basedir}/src/main/kotlin</sourceDir> 
              <sourceDir>${project.basedir}/src/main/java</sourceDir> 
            </sourceDirs> 
          </configuration> 
        </execution> 
      </executions> 
    </plugin> 

To be able to produce the executable JAR for the code we are about to write, we need yet another Maven plugin:

    <plugin> 
      <groupId>org.apache.maven.plugins</groupId> 
      <artifactId>maven-jar-plugin</artifactId> 
      <version>3.0.2</version> 
      <configuration> 
        <archive> 
          <manifest> 
            <addClasspath>true</addClasspath> 
            <mainClass>com.programming.kotlin.HelloKt</mainClass> 
          </manifest> 
        </archive> 
      </configuration> 
    </plugin> 

The preceding code will give you a JAR containing just your code; if you want to run it then you need the extra dependencies to the classpath:

    <plugin> 
      <groupId>org.apache.maven.plugins</groupId> 
      <artifactId>maven-assembly-plugin</artifactId> 
      <version>2.6</version> 
      <executions> 
        <execution> 
          <id>make-assembly</id> 
          <phase>package</phase> 
          <goals> <goal>single</goal> </goals> 
          <configuration> 
            <archive> 
              <manifest> 
                <mainClass>com.programming.kotlin.HelloKt</mainClass> 
              </manifest> 
            </archive> 
            <descriptorRefs> 
              <descriptorRef>jar-with-dependencies</descriptorRef> 
            </descriptorRefs> 
          </configuration> 
        </execution> 
      </executions> 
    </plugin> 

Now we are in a position to add the classes from the previous example (the CarManufacturer and Student classes) and change the main class to contain the following:

    val student = Student("Jenny Wood") 
    println("Student:${student.name}") 
    val carManufacturer = CarManufacturer("Honda") 
    println("Car manufacture:${carManufacturer.name}") 

This is not ready yet. While compiling will go well, trying to execute the JAR will yield an error at runtime about the Student class not being found. The Java compiler needs to know about the Java code sitting under the kotlin folder. For that, we bring in another plugin:

    <plugin> 
      <groupId>org.codehaus.mojo</groupId> 
      <artifactId>build-helper-maven-plugin</artifactId> 
      <executions> 
        <execution> 
          <phase>generate-sources</phase> 
          <goals><goal>add-source</goal></goals> 
          <configuration> 
            <sources> 
              <source>${project.basedir}/src/main/kotlin</source> 
            </sources> 
          </configuration> 
        </execution> 
      </executions> 
    </plugin> 

Finally, we are in a position to compile and run the code. Executing the commands in a terminal will end up printing three lines in the output:

$ mvn package
$ java -jar target/chapter01-maven-mix-1.0-SNAPSHOT-jar-with-dependencies.jar
 

Summary


This chapter has showed you how you can set up your development environment with the tools required to build and run Kotlin code. Now you are able to run and execute the examples created in the rest of the book, as well as experiment with your own Kotlin code.

In the next chapter you will delve into the basic constructs you will use daily when you code in Kotlin.

About the Authors

  • Stephen Samuel

    Stephen Samuel is an accomplished developer with over 17 years of experience. He has worked with Java throughout his career, and in the past 5 years has focused on Scala. He has a passion for concurrency and Big Data technologies. Having spent the last few years in investment banking, he is currently working with Kotlin on a major Big Data investment project. Stephen is also active in the open source community, being the author of several high profile Scala and Kotlin libraries.

    Browse publications by this author
  • Stefan Bocutiu

    Stefan Bocutiu is a Big Data consultant with over 13 years of experience in software development. He enjoys coding in Scala, C#, and has a passion for stream processing technologies. With the team at DataMountaineer-he focuses on providing scalable, unified, real-time data pipelines allowing reactive decision making, analytics, and Hadoop integration.

    Stefan is passionate about motorsports, and while his racing skills are not good enough to allow him to compete, he tries to attend as many MotoGP races as possible. When he is not coding, he can be found at the climbing wall or at the gym. Occasionally, hiking and scrambling trips are on his calendar, and during the winter season, skiing trips are a must for him.

    Browse publications by this author

Latest Reviews

(11 reviews total)
more easy to buy than amazon
Quite a few mistakes in the text (I have stopped logging them). Quite hard to follow especially when some examples introduce other languages and/or bytecode comparisons into the equation. This, from a Kotlin beginner standpoint, makes things very confusing and very indigestible to say the least. Well, on the whole and from my standpoint, not an easy book to read from start to end (I have actually stopped reading it at chapter 5). but, although quite old now and missing some important topics such as Coroutines, I am sure it'll be useful as a reference to poke around to help answer more advanced questions I could ask myself in the future.
To learn Kotlin with this book is a good experience.

Recommended For You

Hands-on Design Patterns with Kotlin

Make the most of Kotlin by leveraging design patterns and best practices to build scalable and high performing apps

By Alexey Soshin
Hands-On Data Structures and Algorithms with Kotlin

Understand and solve complex computational problems and write efficient code with Kotlin

By Chandra Sekhar Nayak and 1 more
Hands-On Object-Oriented Programming with Kotlin

Learn everything you need to know about object-oriented programming with the latest features of Kotlin 1.3

By Abid Khan and 1 more
Learning Concurrency in Kotlin

Take advantage of Kotlin's concurrency primitives to write efficient multithreaded applications

By Miguel Angel Castiblanco Torres