Learn Kotlin Programming - Second Edition

4 (3 reviews total)
By Stephen Samuel , Stefan Bocutiu
  • Instant online access to over 8,000+ 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 is a general-purpose programming language used for developing cross-platform applications. Complete with a comprehensive introduction and projects covering the full set of Kotlin programming features, this book will take you through the fundamentals of Kotlin and get you up to speed in no time.

Learn Kotlin Programming covers the installation, tools, and how to write basic programs in Kotlin. You'll learn how to implement object-oriented programming in Kotlin and easily reuse your program or parts of it. The book explains DSL construction, serialization, null safety aspects, and type parameterization to help you build robust apps. You'll learn how to destructure expressions and write your own. You'll then get to grips with building scalable apps by exploring advanced topics such as testing, concurrency, microservices, coroutines, and Kotlin DSL builders. Furthermore, you'll be introduced to the kotlinx.serialization framework, which is used to persist objects in JSON, Protobuf, and other formats.

By the end of this book, you'll be well versed with all the new features in Kotlin and will be able to build robust applications skillfully.

Publication date:
May 2019
Publisher
Packt
Pages
514
ISBN
9781789802351

 

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 example for every language—the famous Hello World!. In order to do this, 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 look at the typical way of programming using the integrated development environments (IDEs) and build tools available.

Kotlin is a Java virtual machine (JVM) language, and so the compiler will emit Java bytecode. Because of this, naturally, Kotlin code can call Java code, and vice versa! Therefore, you need to have the Java Development Kit (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 at least compatible with Java 6. 

In this chapter, you will learn how to do the following:

  • 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
 

Technical requirements


Throughout this book,  all the code examples will run with 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 Chapter 7, Null Safety, Reflection, and Annotations, the examples will draw heavily on classes provided by the reflection API. This API is available through the kotlin-reflect.jar located on maven central at https://search.maven.org/search?q=a:kotlin-reflect.

Additionally, the code snippets used in this book can be found on GitHub at the following repository https://github.com/PacktPublishing/Programming-Kotlin.

 

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, the stable release of Kotlin is 1.3.31. 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.3.31, scroll to the bottom of the page, and download and unpack the ZIP archive, kotlin-compiler-1.3-31.zip, to a known location on your machine. The output folder will contain a directory called binwith all the scripts required to compile and runKotlinon Windows, Linux, or macOS. You need tomakesure thebinfolder location is part of your system path in order to callkotlincwithout having to specify the full path.

If your machine runs Linux or macOS, 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.3.31

Alternatively, if you are using macOS and you have homebrew installed, you could run the following 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 other than 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, as follows (include-runtime is a flag for the compiler to produce a self-contained and runnable JAR by including the Kotlin runtime in 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. Make sure that your JAVA_HOME variable is set and added to the system path:

$ java -jar HelloWorld.jar

The code is pretty straightforward. 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, as follows (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 in 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 following bytecode that was generated, if you haven't already done so. To be more specific, look at line 3. It invokes a method to validate the fact that the args variable is not null; therefore, if you compile the code without asking for the runtime to be bundled in, and then try to run it, you will get an exception:

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

The runtime footprint is very small; at approximately 800 K, you 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, as follows:

$ 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 that involves passing a flag to the Kotlin compiler, as follows:

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

The preceding code will include the runtime when assembling the final JAR file.

 

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 people prefer to test their methods quickly, but you should always write unit tests rather than using the REPL to validate that the output is correct.

Note

Note: REPL is the common name when referring to an interactive shell, and is an abbreviation for read, evaluate, print, loop.

You can start the REPL by adding dependencies to the classpath in order to make them available within the instance. To look at 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, as follows:

$ kotlinc-jvm -cp joda-time-2.9.4/joda-time-2.9.4.jarWelcome 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

Running the preceding code will execute the now function of the DateTime class provided by the Joda library. The output is simply the current date and time.

 

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 files that are 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. Note the predefined variable args, which contains all the incoming parameters passed when it is invoked. You might wonder what the ? character is doing there. If you are familiar with the C# language and you know about nullable classes, you already know 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 that the script is available, it can be invoked by running the following command:

$ 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 developer). 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 for it 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, albeit limited ones, 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 effort to configure support for it. First, let's see how you can list the available templates by executing the following command:

$ 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:basicgroovy-libraryjava-librarypomscala-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, as shown in the following screenshot. 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. To do this, add the following snippet to the top of your file:

    buildscript {
      ext.kotlin_version = '1.3.31'
      repositories {
        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 (refer to the 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 we have done 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 {
      mavenCentral()
    } 
    dependencies { 
      compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" 
      testCompile 'io.kotlintest:kotlintest-runner-junit5:3.3.2' 
    } 

Now, let's create the file named HelloWorld.Kt. This time, we will set a namespace and 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 Chapter 12, Microservices with Kotlin.

From the Terminal, run the following command:

$ 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.ktpackage com.programming.kotlin.chapter01fun main(args: Array<String>) {  println("Hello World!")}

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

$ 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 file. First, we need to create a manifest file and set the main class, as follows; 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 the dependency for kotlin-stdlib, as well as kotlin-runtime, into the JAR. 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, run the following command in an empty directory:

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

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 src/test/java/com/programming/kotlin, and create the src/main/kotlin directory (the subdirectory structure matches the namespace name), as shown in the following code:

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

<properties> 
  <kotlin.version>1.3.31</kotlin.version> 
  <kotlin.test.version>3.3.2</kotlin.test.version> 
</properties> 
<build>
  <sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
  <testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory> 
  <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 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 where 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-runner-junit5</artifactId> 
          <version>${kotlin.test.version}</version> 
          <scope>test</scope> 
        </dependency> 
      </dependencies>

It is now time to add theHello World!code; this step is similar to the one we took earlier when we discussed Gradle, as you can see from the following code:

$ 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 using the following code:

$ 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, as follows:

$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 result JAR and produce what is called a fat jar. For that, however, another plugin needs to be added, as shown in the following code:

    <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, as follows:

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

The result of executing this command is to launch the JAR and execute the program.

 

IntelliJ and Kotlin


Coding using Vim/nano is not everyone's first choice. Working without the help of an IDE with its code completion, IntelliSense, shortcuts for adding files, or refactoring code can prove challenging depending on how 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 over the course of this book, the free version is sufficient. If you don't already have it installed, you can download it from https://www.jetbrains.com/idea/download.

From version 15.0 onward, 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 box.

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, click Create new project. You will then see a dialog window from which you should select Gradle from the left-hand side section;. Then, check the Kotlin(Java) option from the right-hand side, as shown in the following screenshot:

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, click the New button and navigate to where your 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 asks you to provide the Group Id and Artifact Id. Let's go with com.programming.kotlin and chapter01, respectively. Once you have entered these fields, you can move to the next step of the process where you tick the Use auto-import flag and Create directories for empty directory roots automatically options. Carry on to the next step, where you will be 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 see the outcome shown in the following screenshot:

Hello World! basic project

With the kotlin folder selected, right-click, select the New | Package option, and type com.programming.kotlin.chapter01, as shown in the following screenshot:

Setting up the package name

You should see a new folder appear below the kotlin folder, matching what was typed earlier. Right-click on that, chooseNew|Kotlin File/Class, and typeProgram.kt, as shown in the following screenshot:

Creating the Program.kt file

We are now ready to start typing our Hello World! string. 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, as shown in the following screenshot:

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 then 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 selecting org.jetbrains.kotlin:kotlin-archetype-jvm from the list presented, as shown in the following screenshot:

Maven project

As the screenshot shows, the Maven option should be selected from the various archetypes.

 

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, select 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 file, as we did in the Kotlin with Gradle and Kotlin with Maven sections of this chapter. As you did with the IntelliJ project, click on the src folder, select New package, and name it com.programming.kotlin.chapter01. To add our Program.kt file, you will need to right-click on the newly created package, select New | Other, and then 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. If it is successful, you should see the Hello World! text printed out in theConsoletab at the bottom of your IDE.

 

Mixing Kotlin and Java in a project


Using different languages within the same project is quite common; I have encountered 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 we created earlier in the Kotlin with Gradle section. You should see the following directory structure in your IntelliJ (the standard template for a Java/Kotlin project):

 

Project layout

You can place the 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. Navigate to New | Java class named CarManufacturer.java and use the following 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, as shown in the following code:

    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 using the following code:

    fun main(args: Array<String>) { 
      println("Hellow World!") 
      val student = Student("Alexandra Miller") 
      println("Student 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 build.gradle, add the following instruction:

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

Now, we can compile and run the program, as follows:

$ 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. However, we can speed it up by only compiling the files that were 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 widely 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 folder). 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, as shown in the following code:

    <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, as follows:

    <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, as follows:

    <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, as shown in the following code:

    <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 in relation to the classpath, as follows:

    <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 manufacturer = CarManufacturer("Honda") 
    println("Car manufacturer:${manufacturer.name}") 

This is not ready yet. While compiling will go well, trying to execute the JAR will yield an error at runtime due to 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, as shown in the following code:

    <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. First, we package up the JAR using the Maven package command. Then, we execute this assembled JAR, as follows: 

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

Running these commands will result in the print statements being executed and outputted to the console.

 

Summary


This chapter described how you can set up your development environment with Gradle, Maven, IntelliJ, or Eclipse. Now, you are able to run and execute the examples given in the rest of the book, as well as experiment with your own Kotlin code.

In Chapter 2, Kotlin Basics, we will delve into the basic constructs you will use on a daily basis when coding 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

(3 reviews total)
Always good, Nice way To learn
Excellent book. Packt's specials rock!
je n'ai pas obtenu de livre de remplacement à l'achat de JavaEE6 .

Recommended For You

Book Title
Access this book and the full library for just $5/m.
Access now