Hibernate 5 Kotlin Quick Start

This tutorial will get you using Hibernate with Kotlin quickly!

I have run into situations where I just simply want to write a simple application that has Hibernate support, without having to use a full stack such as Spring Boot. It’s not hard to get going, but there are a few things to think about such as configuring Hibernate properly and managing your own transactions. The good thing is that this doesn’t take a lot of effort, as I will show you in the following tutorial.

Dependencies

To get started, here is a basic pom.xml file that will show you what dependencies you need.

dependencies {
    compile 'org.hibernate:hibernate-java8:5.4.4.Final'
    compile 'org.hibernate:hibernate-c3p0:5.4.4.Final'
    compile 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.41'
    compile 'org.jetbrains.kotlin:kotlin-reflect:1.3.41'
    compile 'com.h2database:h2:1.4.199'
    compile 'commons-io:commons-io:2.6'
    compile 'org.apache.logging.log4j:log4j-api:2.12.1'
    compile 'org.apache.logging.log4j:log4j-core:2.12.1'
    testCompile 'org.jetbrains.kotlin:kotlin-test:1.3.41'
}

Properties File

Next we need a properties file that will hold our Hibernate configuration

driver=org.h2.Driver
url=jdbc:h2:~/roms
user=root
pass=root
dialect=org.hibernate.dialect.H2Dialect
showSql=false
formatSql=true
currentSessionContextClass=thread
ddlAuto=validate

# Needed for a connection pool
hibernate.c3p0.min_size=1000
hibernate.c3p0.max_size=2000
hibernate.c3p0.timeout=120
hibernate.c3p0.max_statements=2000

This properties file will create an embedded H2 database. It also defines a connection pool, which is required in programs that use multiple threads, which mine often  do. If you want to see the SQL that is generated, then you should flip the showSql property to true.

Entity Class

Hibernate maps objects to database tables, which means that we need an entity class.

data class AnEntity (
        @Id @GeneratedValue
        val id: Long? = null,
        val name: String? = null
)

Boot Strapping Hibernate

At this point, we are ready to begin configuring Hibernate.

Reading the Properties File

Let’s begin by reading our properties file into memory. Here is a nice little Kotlin function that we pull a properties file from the resource folder.

fun propertiesFromResource(resource: String): Properties {
    val properties = Properties()
    properties.load(Any::class.java.getResourceAsStream(resource))
    return properties
}

Convert Properties file to Hibernate Properties

Our next step is to read the information in the properties file and turn it into a Properties object that can be consumed by Hibernate. We can use Kotlin’s extension function feature to make this easy.

fun Properties.toHibernateProperties(): Properties {
    val hibernateProperties = Properties()
    hibernateProperties[Environment.DRIVER] = this["driver"]
    hibernateProperties[Environment.URL] = this["url"]
    hibernateProperties[Environment.USER] = this["user"]
    hibernateProperties[Environment.PASS] = this["pass"]
    hibernateProperties[Environment.DIALECT] = this["dialect"]
    hibernateProperties[Environment.SHOW_SQL] = this["showSql"]
    hibernateProperties[Environment.FORMAT_SQL] = this["formatSql"]
    hibernateProperties[Environment.CURRENT_SESSION_CONTEXT_CLASS] = this["currentSessionContextClass"]
    hibernateProperties[Environment.HBM2DDL_AUTO] = this["ddlAuto"]

    //C3PO
    hibernateProperties["hibernate.c3p0.min_size"] = this["hibernate.c3p0.min_size"]
    hibernateProperties["hibernate.c3p0.max_size"] = this["hibernate.c3p0.max_size"]
    hibernateProperties["hibernate.c3p0.timeout"] = this["hibernate.c3p0.timeout"]
    hibernateProperties["hibernate.c3p0.max_statements"] = this["hibernate.c3p0.max_statements"]

    return hibernateProperties
}

Building a Hibernate Configuration

Hibernate requires a configuration. We can use the Properties object that we made in the last step as input for creating a Hibernate configuration. Additionally, we need to supply class objects for any classes that we need Hibernate to manage. It’s best to supply this as a vararg.

fun buildHibernateConfiguration(hibernateProperties: Properties, vararg annotatedClasses: Class<*>): Configuration {
    val configuration = Configuration()
    configuration.properties = hibernateProperties
    annotatedClasses.forEach { configuration.addAnnotatedClass(it) }
    return configuration
}

Build a SessionFactory

The SessionFactory is the outcome of all of this work. It requires a Configuration in order to be created, but once you have a Configuration, it’s easy to get going in Hibernate.

fun buildSessionFactory(configuration: Configuration): SessionFactory {
    val serviceRegistry = StandardServiceRegistryBuilder().applySettings(configuration.properties).build()
    return configuration.buildSessionFactory(serviceRegistry)
}

Transactions

Hibernate is often used in environments where a container, such as Spring, manages your transactions automatically. In this case, we need to manually manage transactions, but Kotlin makes it really easy to eliminate the boiler plate code that would normally be required. Here is a nice little function that allows you to manage your transactions.

fun <T> SessionFactory.transaction(block: (session: Session) -> T): T {
    val session = openSession()
    val transaction = session.beginTransaction()

    return try {
        val rs = block.invoke(session)
        transaction.commit()
        rs
    } catch (e: Exception){
        logger.error("Transaction failed! Rolling back...", e)
        throw e
    }
}

Shutdown Hook

The final house keeping item is to make sure that we close our SessionFactory when we are finished. We can tap into the JVM’s shutdown hooks to make sure that our database connection has been closed properly.

fun addHibernateShutdownHook(sessionFactory: SessionFactory)  {
    Runtime.getRuntime().addShutdownHook(object: Thread() {
        override fun run() {
            logger.debug("Closing the sessionFactory...")
            sessionFactory.close()
            logger.info("sessionFactory closed successfully...")
        }
    })
}

Demonstration

Let’s wrap this up with a nice little demonstration program that puts all of this into action!

fun main(){
    val properties = propertiesFromResource("/database.properties")
    properties["url"] = "jdbc:h2:mem:test" //Override the properties to make an in memory db

    val configuration = buildHibernateConfiguration(properties.toHibernateProperties(), AnEntity::class.java)
    val sessionFactory = buildSessionFactory(configuration)
    addHibernateShutdownHook(sessionFactory)

    sessionFactory.transaction { session ->
        session.save(AnEntity(name = "Birdie"))
    }

    val entity = sessionFactory.transaction { session ->
        session.createQuery("from AnEntity").uniqueResult() as AnEntity
    }

    println(entity)
}

Sources

https://hibernate.org/orm/documentation/5.0/

https://kotlinlang.org/docs/reference/

Software Security

A brief introduction to software security.

The software is an integral part of our lives, but time and time again, we hear on the news about data breaches. The frequency of such breaches seems to increase on a regular basis as well as the scale and impact of them. This may lead some people to think that software protection isn’t taken seriously. However, in my experience, there seem to be other reasons for insecure software. In this post, I will attempt to explain my experiences regarding software defense. While the reasons for insecure software are endless, a few categories seem to come to mind. Let’s walk through some of the more common ones and see if we can figure out the reasons for insecure software.

Iron Triangle

1920px-Project-triangle-en.svg

Every software project has three constraints that determine how much work can be done on the system. Those constraints are:

  • Scope
  • Resources (Cost)
  • Time

Scope refers to the work that is going to be done on the project. A project that has a large scope will require more work and conversely, a project that has a smaller scope requires less work. Resources are materials, money, people, and other inputs that are needed in order to develop a project. It is related to scope in the sense that more scope will require more resources, but keep in mind that inefficient project management can also lead to resources being wasted as well. Finally, there is time. Every project has deadlines and eventually the customer will want the deliverables.

All three of these resources are not finite. For example, you can ask for more time and resources, and likewise, the customer may wish to increase the scope of the project. However, this usually is a request for more features, not protection. Ensuring that system safety is something that everyone tends to pay lip service too, but until someone has actually experienced an incident, they are more likely to think of it as an afterthought rather than adopt a security first mentality.

Safety is a nonfunctional requirement and it requires time, resources, and scope to implement it properly. Hence, the iron triangle tends to get in the way of defense. It is often difficult to quantify the value of software assurance to stakeholders and thus, it can generally be seen as an uphill battle to encourage stakeholders to pay for it. Unlike features, protection isn’t something that users tend to see. A user simply expects safety to be present in the software. This leads to our next issue when it comes to creating safe IT systems.

Lack of Awareness

Security-And-Privacy

Management, users, and developers generally lack a proper understanding of secure IT systems, and this can lead to data breaches, denial of service, or other issues that impact the confidentiality, availability, and integrity of the system. While there are many reasons for this, a lack of security professionals in the workforce is certainly a problem. According to ISC2, there is a shortage of 3 million cybersecurity workers.

When we work with security aware people, we are more likely to become more aware of cybersecurity ourselves. However, a lack of cybersecurity people leads to a lack of voice at the table. For example, if management is planning out a system, they may not fully appreciate what is required in order to make a fully secured system unless there is somebody present to explain the cost, requirements, needs, and people resources that are needed to make a safe IT system.

Likewise, developers are under constant pressure to bring working code to the customer, but again, may not have the time, resources, training, or experience in order to make sure that they are producing a robust IT system. A lack of exposure to safety experts hinders a developer’s exposure to security and increases a lack of awareness. Project deadlines imposed by management may lead to developers skipping protection altogether in order to produce features for the customer. While many developers will acknowledge the importance of security, they rarely have a chance to learn about secure coding practices or even tend to overly rely on third-party libraries for safety.

Users are also a problem when it comes to cybersecurity. Many users simply do not follow safe IT practices. For example, users are constantly told not to use the same password for multiple websites yet many users do this on a regular basis. Web browsers will normally warn people not to browse to a site that has a certificate configuration issue, yet this is another thing that people are known to do. Finally, many people aren’t even aware that they should not connect to public WIFI hot spots without using a VPN. All of this leads to problems that can create information leakages.

There may not even be good engineering solutions to these problems. For example, when I write a website for a client, I will often download a list of known leaked passwords. Hackers love to publish such lists on the internet since they can be used in dictionary attacks. By using such a list myself, I can create code that prevents a user from using such a password and hopefully prevent brute force attacks. The problem is that they violate Psychological Acceptability because the user may be trying to use a password that conforms with the password requirements but still isn’t acceptable because it’s in the leaked password list. It can also create an illusion of defense since the password blacklist needs to be updated on a regular basis.

Of course, there are endless examples of a lack of safety awareness. The point is that such a lack of awareness impacts the quality of an IT system since there is a lack of knowledge as to how to secure a system. When project managers, developers, and users lack the expertise to secure a system, it will inevitably result in an IT system that is weak. Training and practice are the antidotes to such problems. The more that we train and expose people to secure IT practices, the stronger our systems will become.

Lack of Security Culture

2009-12-12-08.21

Lack of culture can certainly be related to a lack of awareness, but it can also come from attitudes and values in the organization. An organization will promote a safe IT culture when protection is brought up in meetings and acted upon. Unfortunately, many organizations lack the leadership that is necessary to build strong and safe systems and this results in weak systems.

An organization can look at software protection as a forethought or as an afterthought. In other words, they can be proactive or reactive. While common sense may dictate that we should be proactive, the reality is that many organizations tend to react to an incident. There are several (and this is non-exhaustive) reasons for this.

Attackers Strike Anytime

An attacker of a system has the luxury of being to strike at will at any time. The defender of a system has to be on guard twenty-four hours a day, seven days a weak. Most of an attacker’s time is spent in reconnaissance, which means that they are exploring the system and looking for weaknesses. Attackers have a variety of tools that they can use such as dumpster diving, social engineering, or using scripts.

Ultimately, it is the attacker that gets to decide when to conduct an attack and often times, the attack isn’t discovered until after it is complete and the damage is done. A good attacker will even cover their tracks by manipulating logs or masquerading as legitimate users so that they can keep coming back. While organizations can take preventative action to limit such an attack, the reality is that complete protection is utopian and eventually an attack will succeed. This will lead to a reactive approach to defense.

Cost

Securing a software system has a cost associated with it and the cost is generally seen as overhead. Preventative costs such as penetration testing, red team / blue team exercises, and phishing simulations may be seen as too expensive or unnecessary. Many managers are conditioned to believe that shareholder value is the only stakeholder that matters in an organization and may disregard anything that doesn’t maximize shareholder value. Furthermore, a lack of penalties and enforcement from the government may mean that managers disregard IT protection since a data breach may only impact users and not the manager.

In other words, managers may not see the benefits of safety as outweighing the risks. The cost of prevention is generally known upfront since you can easily request a quote from a penetration testing organization. However, the cost of a breach is generally known until after it occurs. This can cause management to become reluctant to pay for prevention and may lead to them taking a risk instead.

Lack of Expertise

A lack of expertise goes hand in hand with a lack of awareness that was discussed above. However, if we don’t have people in the organization that is trained in cybersecurity, then chances are high that we won’t have a safety culture either. Without training expertise, an organization will not know how to promote a safety culture in the first place, which leads to a reactive stance when it comes to addressing incidents.

What to do about it?

Of course, the above methods are not exhaustive by any means. There are real hurdles that need to be overcome in order to have an organization adopt a security-first mindset. However, there are a few things that can certainly help to produce software that is more secure. The first one is a commitment to protection.

When it comes to making a commitment to defense, it means that the organization has to be committed to producing truly secure software. This starts at the highest levels of leadership by setting an example. Senior management must take the time to educate themselves about IT security and understand what it means to be a secure organization. They must also include safety awareness and training as part of the interview process or training process in order to ensure that staff is trained in security practices. This may mean a change in recruiting and hiring practices.

It also means that a security policy is continually evaluated to ensure that it is up to date, works for the organization, and is acted upon. The U.S. government, Microsoft, and other large organizations often have publicly available models to follow, so it’s not as if an organization needs to start from the beginning. For example, OWASP has the SAMM project that is available for anyone who needs information on how to get started. You can also consider hiring consultants or investing in training for employees also.

Practice is also important. While having an incident response plan is important, it also just as important to go through the plan. A plan is simply a piece of paper until it is acted upon and in the event of an incident, people may not have time to read and understand what is expected of them. This is why proper preparation and planning is important.

Upfront security planning will also help to improve the security of software. For example, it’s important for an organization to conduct threat modeling, attack surface analysis, and security planning. This will help developers understand that is needed for them in order to create a safe and robust system and it will also improve security awareness and culture in the organization.

Follow through is critical as well. An organization must always be checking their work for security flaws. This can be achieved using techniques such as internal and external security audits, red hat / black hat exercises, and penetration testing. An organization can also conduct simulated social engineering attacks as well. Adding any such steps to the software engineering processes is bound to improve the security of the system and make the IT world a better and safer place.

Sources

“The iron triangle of planning”, Tareq Aljaber

“Cybersecurity Skills Shortage Soars, Nearing 3 Million”, ISC2 Management

“Dictionary Attack”, Wikipedia

Psychological Acceptability, Michael Gegick and Sean Barnum

Three uses for Kotlin When

Three uses for Kotlin When

Replace the if when

By Patrick Luck

Introduction

The kotlin when extension function is part of the Kotlin standard library and it is used to replace both the switch statement as well as the if-else statements. It is critical that you understand when to use the kotlin when function because when used properly, when can greatly increase the readability of your code. There are three primary different uses where using kotlin when is practical. The first case is comparing a value and then executing the proper branch of code when a true condition has been found. The second involves returning a value based on a try condition. Finally, when is also useful for exception handling.

Like switch and if-else, kotlin when allows you to specify a default case that will execute when none of the specified conditions have been found. A default case is optional as long as when is not being used to return a value. In other words, should you use the kotlin when function to return a value, you will be forced to include an else block in the function or the compiler will flag an error. However, as long as you are not returning a value by using kotlin when, you will not be required to have a default case. Let’s take a look at a few examples of using when in a real program.

Executing a block of code based on a condition

fun throwException(name : String)

fun throwException(name: String){
    when (name) {
        "RuntimeException" -> throw RuntimeException("RuntimeException")
        "IllegalArgumentException" -> throw IllegalArgumentException("IllegalArgumentException")
        "IndexOutOfBoundsException" -> throw IndexOutOfBoundsException("IndexOutOfBoundsException")
        else -> println("Not an exception")
    }

}

Explanation

Here is a function that throws an exception based on the name String parameter. In this case, we are using the kotlin when function to replace a switch or an if-else-else-if block. As you can see, the kotlin when function makes the code highly readable. We start by passing the name variable to when which allows the function to compare the value in name to the values listed on the left side of the ->. Our first value is “RuntimeException” so when name == “RuntimeException” the code to the right of the -> will execute and a RuntimeException is thrown.

The same logic holds true for the two other cases as well. When name == “IllegalArgumentException” the code to the right of -> next to “IllegalArgumentException” is executed and an IllegalArgumentException is thrown by the JVM. The same is also the case for “IndexOutOfBoundsException”.

Finally, we also have an else in this when function. The else acts like a default in a Java switch statement or as an else in an if block. In our case, when name isn’t “RuntimeException”, “IllegalArgumentException”, or “IndexOutOfBoundsException”, then the code to the right of the -> next to the else block executed and we print “Not an exception” to the console.

Exception Handling

fun handleException(name : String)

fun handleException(name : String){
    try {
        throwException(name)
    } catch (e : Exception){
        when (e) {
            is IllegalArgumentException -> println("Handling an IllegalArgumentException")
            is IndexOutOfBoundsException -> println("Handling an IndexOutOfBoundsException")
            is RuntimeException -> println("Handling a Runtime Exception")
        }
    }
}

Explanation

This is an example of when we are using the kotlin when function for exception handling. Developers who are familiar with Java will likely remember using multiple catch blocks for each kind of exception that they wanted to handle. Every kind of unique exception type had to have its own catch block until Java 7 when multi-catch handlers were introduced for when you wanted to use the same code to handle different exception types. However, using a unique catch block for every kind of or groups of exceptions was cumbersome and lead to a lot of boiler plate in your code.

Kotlin addressed this issue by allowing the when function to be combined with the is operator. Keep in mind that “is” is used to compare the type of an object with a class to see if object is of a specific type and return true or false accordingly. That means we have a boolean operation here which allows it to be used with when. For example, when e is IllegalArgumentException, we execute the code to the right of the -> and print “Handling an IllegalArgumentException”. Not only does this improve the readability of the code by allowing for a plain english construct, but we also do away with all of the catch blocks that we would have needed in Java.

Returning a value

fun returnFromWhen(name : String): Class?

fun returnFromWhen(name : String): Class? {
    return when(name){
        "RuntimeException" -> RuntimeException::class.java
        "IllegalArgumentException" -> IllegalArgumentException::class.java
        "IndexOutOfBoundsException" -> IndexOutOfBoundsException::class.java
        else -> {
            println("Returning a null value")
            null
        }
    }
}

Explanation

Our final case is for using when to return a value. This is a powerful construct because it allows us to avoid declaring intermediate variables in a function just for the purpose of returning a value. It also allows us to avoid multiple exit points in a function which many developers consider to be a bad practice since it can be prone to bugs.

Since when is a function, it can be combined with the return keyword to return a value. Should you decide to use this feature, you will need to keep in mind that the returning value needs to be the last statement in a block of code following the -> in each case of the when. The type of return value also had to be declared in the calling function as well, which is what we have in the function declaration.

The kotlin when function works the same as it does in the other two cases. We pass a variable to it and then compare it to the separate cases. The only difference is that the final statement in the code of the -> needs to be a return value of some sort. In our case, we are returning Class objects that extend from RuntimeException. Our function has also been declared as nullable so that we can return null. After each case in the when block, we return a Class object, except for the else case which returns null.

You will notice also that the else part has { } that wraps multiple statements. This can always be done with the kotlin when function and will allow you to execute a block of code when it is needed.

Conclusion

As you may have noticed, the kotlin when function is a great tool to use when you need to increase the readability of your code by allowing you to avoid if else statements. It is also more powerful than the Java switch statement, as you are free to use any boolean condition in the when statement. The most common patterns for using kotlin when is to execute a block of code, exception handling, and returning a value.

Many developers execute a block of code using kotlin when just as if they are using a Java switch statement. In this case, we are checking a value against different conditions and then acting accordingly. Using kotlin when in this fashion is more flexible than using a switch statement, because you are not limited to just numeric or String values. Kotlin when allows you to do any legal comparisons which makes it more powerful than a Java switch statement.

The kotlin when function is also used to avoid a messy list of catch blocks when you are handling exceptions. Instead, you can use the “is” operator to check the type of your exception object and respond as needed to the exception. This allows for more compact exception handling than what you can normally achieve in Java.

Finally, since kotlin when is a function, you can use it to return a value. This allows you to avoid having multiple exit points in your function and you can avoid needing to declare an unnecessary variable. Once again, this makes your code more concise and readable that what you can normally achieve in other programming languages.

Github

You can find the entire code for this post at https://github.com/archer920/Koltin-When-Exception

Sources

  1. https://kotlinlang.org/docs/reference/control-flow.html
  2. http://www.baeldung.com/kotlin-when
  3. https://www.programiz.com/kotlin-programming/when-expression
  4. https://antonioleiva.com/when-expression-kotlin/
  5. https://www.tutorialkart.com/kotlin/when-expression-in-kotlin/

Consuming REST with Spring and Kotlin

Spring 5 came with official support for Kotlin, a JVM language developed by Jetbrains which focuses on code clarity and conciseness. Many web applications today are a mockup of content from other websites, which are usually exposed with a web service. Consuming a web service is really easy when you use Spring’s RestTemplate class. This tutorial is an adaptation of the one found here, which has been modified to use the Kotlin language.

Project Structure

You will want to setup your project with a folder structure that is similar to the one shown in the screenshot below.

consuming_rest

build.gradle

Next you will want to use a dependency management system, either gradle or maven, which will see to the details of downloading your dependencies. We use gradle in this tutorial.

buildscript {
    ext.kotlin_version = '1.2.30'

    repositories {
        mavenCentral()
    }
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath("org.springframework.boot:spring-boot-gradle-plugin:2.0.1.RELEASE")
    }
}

group 'com.stonesoupprogramming'
version '1.0-SNAPSHOT'

apply plugin: 'kotlin'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

bootJar {
    baseName = 'gs-consuming-rest'
    version =  '0.1.0'
}

repositories {
    mavenCentral()
}

dependencies {
    compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
    compile group: 'org.jetbrains.kotlin', name: 'kotlin-reflect', version: '$kotlin_version'
    compile("org.springframework.boot:spring-boot-starter")
    compile("org.springframework:spring-web")
    compile("com.fasterxml.jackson.core:jackson-databind")
}

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

ConsumingRest.kt

Now we are going to write a simple Kotlin application which will make an HTTP GET request to a server and deserialize the JSON into Kotlin object. We will use two data classes and then write a main function. Here is the code.

package com.stonesoupprogramming

import com.fasterxml.jackson.annotation.JsonIgnoreProperties
import org.springframework.web.client.RestTemplate

/**
 * The following data classes are instantiated by Jackson and converted from JSON to
 * objects. Normally, the class needs to have all of the properties in the JSON, but
 * we can change this by using the ignoreUnknown = true argument
 */
@JsonIgnoreProperties(ignoreUnknown = true)
data class Value(var id: Long = 0, var quote: String = "")

@JsonIgnoreProperties(ignoreUnknown = true)
data class Quote(var type : String = "", var value : Value? = null)

fun main (args : Array){
    //Create a new RestTemplate and use getForObject to make a GET request
    //to the server and return an instance of Quote representing the response
    val quote = RestTemplate().getForObject("http://gturnquist-quoters.cfapps.io/api/random", Quote::class.java)

    //Print the response to the console
    println(quote)
}

Our application begin by declaring two data classes which are Value and Quote. We annotate these classes with @JsonIgnoreProperties which allows the JSON deserializer to skip over JSON properties that are not present in our data classes. Otherwise, we would get a runtime exception. The JSON deserializer uses reflection (java based) to instantiate objects from the data classes so we need some form of a default constructor. We can do this a number of different ways in Kotlin, but I chose to use default values the properties in the data classes.

Next we have a main function. It starts by creating a new RestTemplate object and calling its getForObject method. The getForObject requires a web address and a class of the object to return. Then we call println on the returned Quote object to print the output to the console.

RestTemplate has methods for just about every HTTP verb so while this example only uses GET, you can do POST, PUT, DELETE and other common web requests.

Output

The output will different every time you run the application, but here is what I got when I ran it.

14:47:14.091 [main] WARN org.springframework.http.converter.json.Jackson2ObjectMapperBuilder - For Jackson Kotlin classes support please add "com.fasterxml.jackson.module:jackson-module-kotlin" to the classpath
14:47:14.156 [main] DEBUG org.springframework.web.client.RestTemplate - Created GET request for "http://gturnquist-quoters.cfapps.io/api/random"
14:47:14.247 [main] DEBUG org.springframework.web.client.RestTemplate - Setting request Accept header to [application/json, application/*+json]
14:47:14.321 [main] DEBUG org.springframework.web.client.RestTemplate - GET request for "http://gturnquist-quoters.cfapps.io/api/random" resulted in 200 (OK)
14:47:14.322 [main] DEBUG org.springframework.web.client.RestTemplate - Reading [class com.stonesoupprogramming.Quote] as "application/json;charset=UTF-8" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@cc43f62]
Quote(type=success, value=Value(id=1, quote=Working with Spring Boot is like pair-programming with the Spring developers.))

Conclusion

Here is the source document for this tutorial.

https://spring.io/guides/gs/consuming-rest/

You can get the code at my github at this address: https://github.com/archer920/consuming-rest

Kotlin Scheduling Tasks with Spring Boot

Kotlin is fully interoperable with Spring Boot which makes Spring and Kotlin a perfect companion to one another. Spring brings a high level platform that can be used for making just about any enterprise grade application, while Kotlin offers language features that make your code concise and readable. Both Kotlin and Spring do a great job of reducing boilerplate in your code so that you can write an application quickly and get to the point.

This tutorial is based on Scheduling Tasks found on the Spring website is an adapation of the tutorial for Kotlin. We will be using Kotlin, Spring Boot, and Gradle. You can find the code here.

Project Structure

You should setup your project to use this folder structure.

scheduling_tasks

build.gradle

Here is the full code for your gradle.build file. Notice that will bring in both Kotlin and Spring libraries so that we can build the project.

buildscript {
    ext.kotlin_version = '1.2.30'

    repositories {
        mavenCentral()
    }
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath "org.springframework.boot:spring-boot-gradle-plugin:2.0.1.RELEASE"
    }
}

group 'com.stonesoupprogramming'
version '1.0-SNAPSHOT'

apply plugin: 'kotlin'
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

repositories {
    mavenCentral()
}

bootJar {
    baseName = 'gs-scheduling-tasks'
    version =  '0.1.0'
}

sourceCompatibility = 1.8
targetCompatibility = 1.8

dependencies {
    compile "org.springframework.boot:spring-boot-starter"
    compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
    compile group: 'org.jetbrains.kotlin', name: 'kotlin-reflect', version: '1.2.30'
    testCompile "junit:junit"
}

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

SchedulingTasks.kt

Here is the Kotlin code followed by an explanation.

package com.stonesoupprogramming.schedulingtasks

import org.slf4j.LoggerFactory
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.scheduling.annotation.EnableScheduling
import org.springframework.scheduling.annotation.Scheduled
import org.springframework.stereotype.Component
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter

/**
 * Mark this class an injectable component so that the Spring environment will create
 * an instance of this class when it starts up.
 */
@Component
class ScheduleTasks {

    private val logger = LoggerFactory.getLogger(ScheduleTasks::class.java)

    /**
     * This @Schedule annotation run every 5 seconds in this case. It can also
     * take a cron like syntax.
     * See https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/scheduling/support/CronSequenceGenerator.html
     */
    @Scheduled(fixedRate = 5000)
    fun reportTime(){
        logger.info("The time is now ${DateTimeFormatter.ISO_LOCAL_TIME.format(LocalDateTime.now())}")
    }
}

@SpringBootApplication
//Required to tell Spring to run tasks marked with @Scheduled
@EnableScheduling
open class Application

fun main(args : Array){
    SpringApplication.run(Application::class.java)
}

When run, you will get this output on your console every five seconds.

2018-04-06 18:51:21.868  INFO 20294 --- [pool-1-thread-1] c.s.schedulingtasks.ScheduleTasks        : The time is now 18:51:21.865
2018-04-06 18:51:26.858  INFO 20294 --- [pool-1-thread-1] c.s.schedulingtasks.ScheduleTasks        : The time is now 18:51:26.858

Explanation

So how does the code work? The ScheduleTasks class is annotaded with @Component, which the Spring environment scans for on start up and instantiates the class. At this point, an instance of ScheduleTasks lives in the ApplicationContent. You will notice that the ScheduleTasks::reportTime function is annotated with @Scheduled which defaults to a fix rate or can use a CRON like syntax.

You can’t annotate a method and expect it to run without turning on scheduling. That is why the Application class is annotated with @EnableScheduling. This will tell Spring to scan all container managed classes and look for the @Scheduled annotation. The Spring environment will do the job of making sure that the methods run at the proper time.

Code

You can get the code for this tutorial at my GitHub: https://github.com/archer920/scheduling-tasks

Sources

https://spring.io/guides/gs/scheduling-tasks/
https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/scheduling/support/CronSequenceGenerator.html

Build a RESTful Web Service with Kotlin

Introduction

Spring and Kotlin combine together to create a powerhouse when it comes to rapid application development. The Spring project is a powerful framework that allows you to develop an application quickly with as little boilerplate and configuration code as possible. Kotlin is a language that is developed Jetbrains that focuses on code readability and conciseness. This guide will show you how to build a RESTful web service using Spring Boot and Kotlin.

Getting Started

We will use a Maven project to mranage the resources that this application will need. Your project will need the following folder skeleton before you can continue.

Maven

After you have created your project skeleton you can continue.

pom.xml

The pom.xml file is used by Maven to manage all of your project dependencies. You can copy and paste this code into your pom.xml file, which will pull in all of the Spring Boot and Kotlin dependencies.



    4.0.0

    stonesoupprogramming
    BuildingRESTfulWebService
    1.0-SNAPSHOT

    
        1.2.31
    

    
        org.springframework.boot
        spring-boot-starter-parent
        2.0.0.RELEASE
    

    
        
            org.jetbrains.kotlin
            kotlin-stdlib-jdk8
            ${kotlin.version}
        
        
            org.jetbrains.kotlin
            kotlin-reflect
            ${kotlin.version}
        
        
            org.reflections
            reflections
            0.9.10
        
        
            org.jetbrains.kotlin
            kotlin-test
            ${kotlin.version}
            test
        

        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
        
            com.jayway.jsonpath
            json-path
            test
        
    

    
        src/main/kotlin
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
            
                org.jetbrains.kotlin
                kotlin-maven-plugin
                ${kotlin.version}
                
                    
                        compile
                        compile
                        
                            compile
                        
                    
                    
                        test-compile
                        test-compile
                        
                            test-compile
                        
                    
                
                
                    1.8
                
            
        
    

    
        
            spring-releases
            https://repo.spring.io/libs-release
        
    
    
        
            spring-releases
            https://repo.spring.io/libs-release
        
    

Application.kt

Kotlin is a language that is meant to be concise, which plays to our advantage. We will hold all of our classes inside of the Application.kt file.

package com.stonesoupprogramming.spring.boot

import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
import java.util.concurrent.atomic.AtomicLong

/**
 * This class gets converted into JSON and serves as our data model.
 * We can use Kotlin's data class feature to make it only one line of code.
 */
data class Greeting (val id : Long, val content : String)

/**
 * The @RestController annotation tells the Spring Environment to
 * use this class to handle REST requests. That means that it will handle
 * HTTP requests but does not use a view technology to write the response.
 * Instead, an instance of Greeting is simply converted into JSON and written
 * to the HTTP response body.
 */
@RestController
class GreetingController {

    private val counter : AtomicLong = AtomicLong()

    /**
     * The @RequestMapping signals that this method will handle
     * HTTP requests to /greeting. We can narrow it down to GET, POST, PUT, etc
     * when we want different methods to handle different requests
     * at this endpoint.
     *
     * The name parameter is annotated with @RequestParam which has
     * two arguments. The name argument maps the request parameter name to
     * the name argument in this method. The defaultValue will populate
     * name with the value "World" if the request does not have a name argument.
     */
    @RequestMapping("/greeting")
    fun greeting(@RequestParam(value="name", defaultValue="World") name : String) : Greeting {
        return Greeting(counter.incrementAndGet(), "Hello $name")
    }
}

/**
 * The @SpringBootApplication is a meta annotation that makes
 * this application executable.
 */
@SpringBootApplication
open class Application

/**
 * Now we just need an entry point to the program.
 */
fun main(args : Array){
    SpringApplication.run(Application::class.java, *args)
}

Let’s break the code down into each piece.

Greeting

Greeting is a data class that has two fields, id and content. Kotlin introduced data classes to cut down on boilerplate code when using POJOs (Plain old java object). It will have all of the getters, equals, hashcode, and toString() as well as a constructor. This class will get converted into JSON and written to the response body later on in the application.

GreetingController

Spring works on a Model, View, Controller architecture so it uses Controller classes to map web requests to backend code. In this case, we are using @RestController to specify that we are not using a view technology to generate HTML and are instead going to write JSON to the HTML response body.

This class only has one method, greeting, which is annotated with @RequestMapping. You will use @RequestMapping to map HTTP requests to a method in the class. In our case, we are mapping all requests (GET, PUT, POST, DELETE) to /greeting to our greeting method. The greeting method has one argument, name, which is also annotated with @RequestParam.

The @RequestParam has two arguments, value which specifies the name of the argument in the request and the default value if the argument is not present in the request. In our case, we also called the request parameter name and we have it default to World. Inside of the method, we return a new instance of Greeting and then return it. The Spring environment will see to the details of converting it to JSON and writing it to the response.

Application

We also have an empty Application class that is marked with the @SpringBootApplication annotation. This is a meta-annotation that pulls in all of the annotations that are needed to make this program executable. We using it in the main function to start the program.

Finishing

After you start the application, you can point your browser to

http://localhost:8080/greeting and then http://localhost:8080/greeting?name=User to see the JSON output of this application.

Sources

https://spring.io/guides/gs/rest-service/

https://kotlinlang.org/docs/reference/

Source

The source code for this project is available on my github here: https://github.com/archer920/BuildingRESTfulWebService

Kotlin JDBC – RowSet Interface

The RowSet interface is a sub-interface of ResultSet and is used provide finer grade control over JDBC result sets. The RowSet interface has its own sub-interfaces that provide different features depending on the type of interface.

RowSet Sub-Interfavces

Interface Brief Description
JdbcRowSet A RowSet that is capable of being used as a JavaBeans component. The JdbcRowSet maintains a connection to the underlying database and makes the ResultSet scrollable and updateable.
CachedRowSet Caches rows in memory, allowing for the application to work on the ResultSet without maintaing an active connection to the database.
WebRowSet : CachedRowSet An extension of CachedRowSet, the WebRowSet provides XML capabilities
JoinRowSet : WebRowSet Extends WebRowSet to provide SQL JOIN capabilities.
FilterRowSet : WebRowSet Extends WebRowSet to provide filtering capabilities

Example Program

Below is an example program that demonstrates how to create an instance of RowSet.

pom.xml

<?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>OCJP-DB</groupId>
    <artifactId>ocjpdb</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <kotlin.version>1.2.10</kotlin.version>
        <main.class>stonesoupprogramming.MainKt</main.class>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.apache.derby</groupId>
            <artifactId>derby</artifactId>
            <version>10.14.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-stdlib-jre8</artifactId>
            <version>${kotlin.version}</version>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-test</artifactId>
            <version>${kotlin.version}</version>
            <scope>test</scope>
        </dependency>

    </dependencies>

    <build>
        <sourceDirectory>src/main/kotlin</sourceDirectory>
        <plugins>
            <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>
                <configuration>
                    <jvmTarget>1.8</jvmTarget>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>2.6</version>
                <configuration>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <mainClass>${main.class}</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.2.1</version>
                <executions>
                    <execution>
                        <phase>test</phase>
                        <goals>
                            <goal>java</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <mainClass>${main.class}</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

EmployeesRowset.kt

package stonesoupprogramming

import javax.sql.rowset.RowSetProvider

fun main (args : Array<String>){
    val rowSet  = RowSetProvider.newFactory().createWebRowSet()

    with(rowSet){
        //Connection information
        url = "jdbc:derby:stonesoup;create=true"
        username = "admin"
        password = "pw"

        //Command to execute against the database
        command = "SELECT * FROM BURGERS.EMPLOYEES"

        //Execute the command
        execute()

        //Output XML to standard out
        writeXml(System.out)
    }
}

Explanation

This program queries a table in the database and prints the XML to the standard out. We get an instance of WebRowSet by calling createWebRowSet() on line 6. Note that if we wanted a different kind of RowSet, we would just use the corresponding method on RowSetProvider. For example, if we wanted a JdbcRowSet, we would use createJdbcRowSet() instead of createWebRowSet().

The result is a RowSet object. Once we have a RowSet object, we start by populating its properties to establish a connection to the database. In this case, we pass a JDBC connection string, a username, and a password. Next, we set the command property with a SQL string.

The SQL is executed when call the execute() method. A connection is established to the database and then the RowSet object is populated with the results. Since we are using a WebRowSet, we can write the results to XML. The example program passes System.out as the output stream and the results appear on the console.

Kotlin JDBC – Savepoints

The JDBC connection object has the ability to create SavePoint objects that are used to rollback a transaction to a specific point in time. One possible use case is providing users the ability to have “Undo” options while working in a database client program. Of course, we can also use SavePoints in Exception handlers or other areas of the program as needed.

SavePoints are used when the connection’s autoCommit property is set to false. We create a SavePoint like so

val bob = connection.setSavePoint("Bob") //Name is optional

Later on, we can pass the SavePoint to the rollback() method on the connection object.

connection.rollback(bob)

Once the connection is rollback to a SavePoint, any work performed on the conncetion after the SavePoint is lost.

Below is an example program that demonstrates using SavePoints.

pom.xml

<?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>OCJP-DB</groupId>
    <artifactId>ocjpdb</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <kotlin.version>1.2.10</kotlin.version>
        <main.class>stonesoupprogramming.MainKt</main.class>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.apache.derby</groupId>
            <artifactId>derby</artifactId>
            <version>10.14.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-stdlib-jre8</artifactId>
            <version>${kotlin.version}</version>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-test</artifactId>
            <version>${kotlin.version}</version>
            <scope>test</scope>
        </dependency>

    </dependencies>

    <build>
        <sourceDirectory>src/main/kotlin</sourceDirectory>
        <plugins>
            <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>
                <configuration>
                    <jvmTarget>1.8</jvmTarget>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>2.6</version>
                <configuration>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <mainClass>${main.class}</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.2.1</version>
                <executions>
                    <execution>
                        <phase>test</phase>
                        <goals>
                            <goal>java</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <mainClass>${main.class}</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

Employees.kt

package stonesoupprogramming

import java.sql.Connection
import java.sql.DriverManager
import java.sql.ResultSet
import java.util.*

fun main(args: Array<String>) {
    val properties = Properties()

    //Populate the properties file with user name and password
    with(properties) {
        put("user", "admin")
        put("password", "pw")
    }

    //Open a connection to the database
    DriverManager
            .getConnection("jdbc:derby:stonesoup;create=true", properties)
            .use { connection ->
                //Set autoCommit to false to manually manage transactions
                connection.autoCommit = false

                createOrTruncateTable(connection)

                //Create an updatable result set
                val rs = connection
                        .createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE)
                        .executeQuery("SELECT * FROM BURGERS.EMPLOYEES")

                //Populate the table with data
                with(rs) {
                    moveToInsertRow()
                    updateInt("ID", 1);
                    updateString("NAME", "Bob")
                    insertRow()

                    val bob = connection.setSavepoint("Bob")

                    moveToInsertRow()
                    updateInt("ID", 2)
                    updateString("NAME", "Linda")
                    insertRow()

                    val linda = connection.setSavepoint("Linda")

                    moveToInsertRow()
                    updateInt("ID", 3)
                    updateString("NAME", "Tina")
                    insertRow()

                    val tina = connection.setSavepoint("Tina")

                    print("Enter Bob, Linda, or Tina => ")
                    val choice = readLine()

                    when (choice) {
                        "Bob" -> connection.rollback(bob)
                        "Linda" -> connection.rollback(linda)
                        "Tina" -> connection.rollback(tina)
                    }
                }
                //Commit the transaction
                connection.commit()


                //Read only queries are still transactions
                val rsq = connection
                        .createStatement()
                        .executeQuery("SELECT * FROM BURGERS.EMPLOYEES")
                with(rsq) {
                    while (next()) {
                        println("${getInt("ID")}\t${getString("NAME")}")
                    }
                }
                //So we need to commit this query also even though it doesn't change anything
                connection.commit()
            }
}

private fun createOrTruncateTable(connection: Connection) {
    val metaData = connection.metaData
    if (!metaData.getTables(null, "BURGERS", "EMPLOYEES", null).next()) {
        connection
                .createStatement()
                .executeUpdate("CREATE TABLE BURGERS.EMPLOYEES (ID INT PRIMARY KEY, NAME VARCHAR(255))")
    } else {
        connection
                .createStatement()
                .executeUpdate("TRUNCATE TABLE BURGERS.EMPLOYEES")
    }
    connection.commit()
}

Explanation

Our program begins by establishing a connection, preparing a table, and creating an updatable ResultSet. We start inserting into the table beginning on line 32. Line 38 is where we create our first SavePoint, after inserting Bob into the table. Once we have the bob SavePoint established, we move on and insert Linda. Linda also gets a SavePoint (line 45), followed by Tina (line 52).

The user is present with a choice on line 55. When they enter Bob, the connection is rolled back to Bob, meaning that neither Linda or Tina are inserted into the database. When the user picks Linda, the connection is rolled back to the linda SavePoint, meaning that Bob and Linda are inserted into the database, but not Tina. If Tina is picked, then all three employees are inserted into the database. Line 64 commits the transaction and the inserts are performed into the database.

Kotlin JDBC – Rollback Transactions

JDBC has the ability rollback transactions. This example shows how to rollback a transaction in the case of an exception. Exception rollbacks are a common pattern because in many cases, committing a transaction after an error can leave the database in an inconsistent state. Let’s take a look at a short example of how to rollback a transaction.

connection.autoCommit = false

createOrTruncateTable(connection)

//Create an updatable result set
val rs = connection
         .createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE)
         .executeQuery("SELECT * FROM BURGERS.EMPLOYEES")

try {
    /* Lines 32-46 omitted */

    //Commit the previous transaction (lines 32-46)
    connection.commit()

    //Now let's do an insert but have it fail
    with(rs){
        moveToInsertRow()

        updateInt("ID", 3)
        updateString("NAME", "Tina")

        insertRow()
    }
    throw Exception("Simulated")
} catch (e: Exception){
    println("Caught simulated exception. Rolling back...")

    //We can rollback the current transaction. Tina will never
    //get inserted into the database
    connection.rollback()
}

The above code fragement uses an expanded try-catch block. At the start of the code fragement, turn off autoCommit on the connection object and create an updatable ResultSet that let’s us insert rows into the database table. There is an ommitted portion of code that inserts some rows into the database.

Then we commit the first transaction. So far so good. The rows are entered cleanly into the database. Then our example continues by inserting another record into the table. Rather than committing the transaction, we instead throw an Exception to act as if something went wrong with the insertion.

The catch block found at the end of the code fragement shows what to do when an exception is thrown in the middle of a transaction. In our example, we notify the user that we are rolling back the changes. Then we call rollback() on the connection object. Rollback() resets the transaction and the program can act as if the last transaction never happened.

Complete Example

Below is a complete Kotlin program that shows the demonstration code in its entirety.

pom.xml

<?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>OCJP-DB</groupId>
    <artifactId>ocjpdb</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <kotlin.version>1.2.10</kotlin.version>
        <main.class>stonesoupprogramming.MainKt</main.class>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.apache.derby</groupId>
            <artifactId>derby</artifactId>
            <version>10.14.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-stdlib-jre8</artifactId>
            <version>${kotlin.version}</version>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-test</artifactId>
            <version>${kotlin.version}</version>
            <scope>test</scope>
        </dependency>

    </dependencies>

    <build>
        <sourceDirectory>src/main/kotlin</sourceDirectory>
        <plugins>
            <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>
                <configuration>
                    <jvmTarget>1.8</jvmTarget>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>2.6</version>
                <configuration>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <mainClass>${main.class}</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.2.1</version>
                <executions>
                    <execution>
                        <phase>test</phase>
                        <goals>
                            <goal>java</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <mainClass>${main.class}</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

Employees.kt

package stonesoupprogramming

import java.sql.Connection
import java.sql.DriverManager
import java.sql.ResultSet
import java.util.*

fun main(args: Array<String>) {
    val properties = Properties()

    //Populate the properties file with user name and password
    with(properties) {
        put("user", "admin")
        put("password", "pw")
    }

    //Open a connection to the database
    DriverManager
            .getConnection("jdbc:derby:stonesoup;create=true", properties)
            .use { connection ->
                //Set autoCommit to false to manually manage transactions
                connection.autoCommit = false

                createOrTruncateTable(connection)

                //Create an updatable result set
                val rs = connection
                        .createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE)
                        .executeQuery("SELECT * FROM BURGERS.EMPLOYEES")

                try{
                    //Populate the table with data
                    with(rs) {
                        moveToInsertRow()

                        updateInt("ID", 1);
                        updateString("NAME", "Bob")

                        insertRow()
                        moveToInsertRow()

                        updateInt("ID", 2)
                        updateString("NAME", "Linda")

                        insertRow()
                    }
                    //Commit the transaction
                    connection.commit()

                    //Now let's do an insert but have it fail
                    with(rs){
                        moveToInsertRow()

                        updateInt("ID", 3)
                        updateString("NAME", "Tina")

                        insertRow()
                    }
                    throw Exception("Simulated")

                } catch (e: Exception){
                    println("Caught simulated exception. Rolling back...")

                    //We can rollback the current transaction. Tina will never
                    //get inserted into the database
                    connection.rollback()
                }


                //Read only queries are still transactions
                val rsq = connection
                        .createStatement()
                        .executeQuery("SELECT * FROM BURGERS.EMPLOYEES")
                with(rsq) {
                    while (next()) {
                        println("${getInt("ID")}\t${getString("NAME")}")
                    }
                }
                //So we need to commit this query also even though it doesn't change anything
                connection.commit()
            }
}

private fun createOrTruncateTable(connection: Connection) {
    val metaData = connection.metaData
    if (!metaData.getTables(null, "BURGERS", "EMPLOYEES", null).next()) {
        connection
                .createStatement()
                .executeUpdate("CREATE TABLE BURGERS.EMPLOYEES (ID INT PRIMARY KEY, NAME VARCHAR(255))")
    } else {
        connection
                .createStatement()
                .executeUpdate("TRUNCATE TABLE BURGERS.EMPLOYEES")
    }
    connection.commit()
}

Kotlin JDBC – Transactions

There are plenty of situations where databases need to execute a series of SQL statements together to maintain the integrity of the data. In such situations, either all of the statements must succeed or none of them must succeed. Bank accounts are a good example.

In many cases, a customer may have a savings account and a checking account. If a customer moves money from the savings account into the checking account, then two updates are required on two tables. If the update only succeeds on the savings account but fails on the checking account, then the customer’s money will disappear. That is less than ideal for the customer, so either both the checking and savings account tables must update, or the entire operation must fail.

Grouping SQL statements together is known as a transaction. We can manually manage our transactions in JDBC by setting the autoCommit property to false on the connection object. After we set autoCommit to false, we have to make sure to call commit() on the connection object after each transaction. Below is a simple Kotlin program that demonstrates transactions.

pom.xml

<?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>OCJP-DB</groupId>
    <artifactId>ocjpdb</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <kotlin.version>1.2.10</kotlin.version>
        <main.class>stonesoupprogramming.MainKt</main.class>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.apache.derby</groupId>
            <artifactId>derby</artifactId>
            <version>10.14.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-stdlib-jre8</artifactId>
            <version>${kotlin.version}</version>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-test</artifactId>
            <version>${kotlin.version}</version>
            <scope>test</scope>
        </dependency>

    </dependencies>

    <build>
        <sourceDirectory>src/main/kotlin</sourceDirectory>
        <plugins>
            <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>
                <configuration>
                    <jvmTarget>1.8</jvmTarget>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>2.6</version>
                <configuration>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <mainClass>${main.class}</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.2.1</version>
                <executions>
                    <execution>
                        <phase>test</phase>
                        <goals>
                            <goal>java</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <mainClass>${main.class}</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

Employees.kt

package stonesoupprogramming

import java.sql.Connection
import java.sql.DriverManager
import java.sql.ResultSet
import java.util.*

fun main(args: Array<String>) {
    val properties = Properties()

    //Populate the properties file with user name and password
    with(properties) {
        put("user", "admin")
        put("password", "pw")
    }

    //Open a connection to the database
    DriverManager
            .getConnection("jdbc:derby:stonesoup;create=true", properties)
            .use { connection ->
                //Set autoCommit to false to manually manage transactions
                connection.autoCommit = false

                createOrTruncateTable(connection)

                //Create an updatable result set
                val rs = connection
                        .createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE)
                        .executeQuery("SELECT * FROM BURGERS.EMPLOYEES")

                //Populate the table with data
                with(rs) {
                    moveToInsertRow()

                    updateInt("ID", 1);
                    updateString("NAME", "Bob")

                    insertRow()
                    moveToInsertRow()

                    updateInt("ID", 2)
                    updateString("NAME", "Linda")

                    insertRow()
                }
                //Commit the transation
                connection.commit()

                //Read only queries are still transactions
                val rsq = connection
                        .createStatement()
                        .executeQuery("SELECT * FROM BURGERS.EMPLOYEES")
                with(rsq) {
                    while (next()) {
                        println("${getInt("ID")}\t${getString("NAME")}")
                    }
                }
                //So we need to commit this query also even though it doesn't change anything
                connection.commit()
            }
}

private fun createOrTruncateTable(connection: Connection) {
    val metaData = connection.metaData
    if (!metaData.getTables(null, "BURGERS", "EMPLOYEES", null).next()) {
        connection
                .createStatement()
                .executeUpdate("CREATE TABLE BURGERS.EMPLOYEES (ID INT PRIMARY KEY, NAME VARCHAR(255))")
    } else {
        connection
                .createStatement()
                .executeUpdate("TRUNCATE TABLE BURGERS.EMPLOYEES")
    }
    connection.commit()
}

Let’s begin with the explanation. We start by connecting to the database (lines 12-20), then we set the connection’s autoCommit property to false (line 22). From this point on, we are responsible for managing our database transactions. Lines 63-75 create a table for us to work on in the database. It will either make a brand new table, or truncate an existing one.

We populate our table with data on lines 27-45 by creating an updatable ResultSet object and using it’s update methods. The ResultSet will prepare SQL insert statements. However, none of the rows get inserted into the database until line 47 when we call commit() on the connection object.

It’s worth noting that we have to call commit() on read only transactions also. So on lines 50-57, we read from the database to verify the inserts were performed. However, notice that on line 59, we still call commit() even though we haven’t actually changed anything. This is because the underlying database still considers a read only statement to be a transaction.