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

Advertisements

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

Python Simple Dialogs

Applications typically have to request input from the user from time to time. Python and tkinter have built in dialogs that help you ask the user basic questions. These dialogs also provide validation to help make sure that the user enters valid input. This is an example program that shows off askquestion, askfloat, askinteger, and askstring.

from tkinter import *
from tkinter.messagebox import askquestion, showinfo
from tkinter.simpledialog import askfloat, askinteger, askstring


class AskDialogDemo(Frame):
    def __init__(self, master=None, cnf={}, **kw):
        super().__init__(master, cnf, **kw)
        self.pack()
        Button(self, text='Ask a Question', command=self.askquestion_demo).pack(side=LEFT, fill=BOTH, expand=YES)
        Button(self, text='Ask for a Float', command=self.askfloat_demo).pack(side=LEFT, fill=BOTH, expand=YES)
        Button(self, text='Ask for an Integer', command=self.askinteger_demo).pack(side=LEFT, fill=BOTH, expand=YES)
        Button(self, text='Ask for a String', command=self.askstring_demo).pack(side=LEFT, fill=BOTH, expand=YES)

    def askquestion_demo(self):
        answer = askquestion('Question', 'Do you like corn?')
        if answer:
            showinfo('Answer', answer)
        else:
            self.canceled()

    def askfloat_demo(self):
        num = askfloat('Float', 'Enter a decimal number')
        if num:
            showinfo('Float', 'You entered {}'.format(num))
        else:
            self.canceled()

    def askinteger_demo(self):
        num = askinteger('Integer', 'Enter a whole number')
        if num:
            showinfo('Integer', 'You entered {}'.format(num))
        else:
            self.canceled()

    def askstring_demo(self):
        str = askstring('String', 'Enter a string')
        if str:
            showinfo('String', 'You entered {}'.format(str))
        else:
            self.canceled()

    def canceled(self):
        showinfo('Canceled', 'You canceled')


if __name__ == '__main__':
    AskDialogDemo().mainloop()

Explanation

askquestion

You use askquestion to ask the user a basic yes or no question. It takes two arguments: one for the title, and the other is for the question. The returned value will be a string containing yes or no.

answer = askquestion('Question', 'Do you like corn?')

askfloat

The askfloat function returns decimal numbers. It will also perform validation that makes sure the user enters a valid float. The function will either return the float that the user entered or it will return None if they hit cancel.

num = askfloat('Float', 'Enter a decimal number')

askinteger

This function works like askfloat but it returns integers.

num = askinteger('Integer', 'Enter a whole number')

askstring

You can use askstring to get a string value from the user. It will return None if the user enters a blank string and hits Ok or Cancel.

str = askstring('String', 'Enter a string')

Python Advanced Quit Button

Object orientated programming fits extremely well with GUI programming. Using OOP, we can easily make reusable GUI components. This post shows off a quit button that confirms if the user really wants to exit the application. I got the idea from Programming Python: Powerful Object-Oriented Programming. Here is my implementation of the idea followed by the explanation.

from tkinter import *
from tkinter.messagebox import *


class TkQuitButton(Frame):
    def __init__(self, master=None,
                 auto_pack=True,  # Pack the widget automatically?
                 dialog_title='Confirm',  # Title text for the askyesno dialog
                 dialog_message='Are you sure you want to quit?',  # Message for the askyesno dialog
                 button_text='Quit',  # The quit button's text
                 quit_command=Frame.quit,  # Callback command for when the user wants to quit
                 cnf={}, **kw):

        super().__init__(master, cnf, **kw)
        # Store our fields for later user
        self.quit_command = quit_command
        self.dialog_message = dialog_message
        self.dialog_title = dialog_title
        self.quit_button = Button(self, text=button_text, command=self.quit)

        # Notice that self.quit_button is exposed. This can be useful for when
        # the client code needs to configure this frame on its own
        if auto_pack:
            self.pack_widget()
    
    # This let's us override the packing        
    def pack_widget(self):
        self.pack()
        self.quit_button.pack(side=LEFT, expand=YES, fill=BOTH)

    def quit(self):
        # Call the askyesno dialog
        result = askyesno(self.dialog_title, self.dialog_message)
        if result:
            # if they quit, then execute the stored callback command
            self.quit_command(self)


if __name__ == '__main__':
    TkQuitButton().mainloop()

This class extends the Frame class and packs a button into the frame. There are a few configuration properties that can be passed into the constructor. For example, we can auto_pack the widget so that it uses a default packing scheme. We can specifiy a custom title for the askyesno dialog as well as a custom message. The code even lets use customize the text of the button. We can also use a custom quit handler function should we choose to do so.

We can customize how the widget is packed in two different ways. The first way to access the quit_button property and call pack on it directly. This allows client code to change how this widget is packed into their GUIs. Alternatively, we can subclass this class and just override the pack_widget method.

The default quit implementation uses Tk’s askyesno dialog function to display a confirmation dialog to the user. It’s title and message are set to self.dialog_title and self.dialog_message properties. This allows use to customize what the user sees when the dialog is displayed. If the user presses yes, then we call the self.quit_command function which defaults to Frame.quit. Note that since self.quit is a method, we can customize this behavior by overriding it. Since we use a callback handler to exit the applicaiton, we can also customize how the application exits as well.

Tk Standard Dialogs

Applications generally need to show system dialogs to alert the user to events. In this post, we will cover the yes or no dialog, a warning dialog, information dialog, and an error dialog. Tk uses system calls to show dialogs that are native to the underlying platform. Therefore, dialogs on Windows will look like they should on Windows while Mac OS X dialogs will appear correct for that platform.

askyesno

The askyesno is a dialog that is used to present a user with a yes or no choice. It returns a boolean to the caller.

result = askyesno('Yes No Demo', 'Click on either yes or no')

yesno

showwarning

You use showwarning when you want to warn the user about something.

showwarning('Warning Demo', 'You have been warned')

warning

showinfo

This dialog is used to supply the user with information.

showinfo('Info Demo', 'This is some information')

info

showerror

You should use showerror when you need to report an error to the user.

showerror('Error Demo', 'This is an error')

error

Putting it Together

Standard dialog calls are a useful way to notify the user about something important. Since they block the program’s execution, the user is forced to interact with the dialog. This makes the dialogs ideal for forcing the user to read a message or make a choice. Below is a complete program that demonstrates all of the dialogs.

from tkinter import *
from tkinter.messagebox import *


def ask_yes_no_demo():
    result = askyesno('Yes No Demo', 'Click on either yes or no')
    if result:
        showinfo('Result', 'You clicked on Yes')
    else:
        showinfo('Result', 'You clicked on No')


def warning_demo():
    showwarning('Warning Demo', 'You have been warned')


def info_demo():
    showinfo('Info Demo', 'This is some information')


def error_demo():
    showerror('Error Demo', 'This is an error')


root = Tk()
Button(text='Ask Yes No', command=ask_yes_no_demo).pack(fill=X)
Button(text='Warning', command=warning_demo).pack(fill=X)
Button(text='Info', command=info_demo).pack(fill=X)
Button(text='Error', command=error_demo).pack(fill=X)
Button(text='Quit', command=(lambda: sys.exit(0))).pack(fill=X)
mainloop()

Tk — Toplevel

Toplevel widgets are non-root windows. In other words, Toplevel widgets are windows that appear outside of the application’s root window. We can use Toplevel widgets for items such as dialogs, color picker windows, or even dragging tabs into windows. Basically, anytime you need a window that isn’t part of the main application, you can use a Toplevel to create it.

Here is an example of a script that creates Toplevel windows everytime the Spawn button is clicked.

from tkinter import *

count = 0


def spawn_top_level(text):
    global count

    # Create a new window with a label
    win = Toplevel()
    Label(win, text=text, font=('Arial', 32, 'italic')).pack(expand=YES, fill=BOTH)

    count += 1


# This is the main application window
root = Tk()
Button(root,
       text='Spawn',
       command=(lambda: spawn_top_level('Top Level: {}'.format(count)))).pack()
Button(root, text='Quit', command=root.quit).pack()
root.mainloop()

The code creates Toplevel windows inside of the spawn_top_level() function. The window itself is created on line 10, and then we attach a Label to it on line 11. Notice how we pass win as the Label’s parent on line 11. This is how Tkinter knows where to attach the label. When the script is run, we get something like the screenshot below.

toplevel