Tag: builder

From Java Builders to Kotlin DSLs

From Java Builders to Kotlin DSLs

From Java Builders to Kotlin DSLs

Introduction

DSLs – Domain Specific Languages – are an ever trending topic in Kotlin circles. They allow us to flex some of the most exciting language features while accomplishing more readable and maintainable solutions in our code.

Today I’d like to show you how to implement a certain kind of DSL – we’re going to be wrapping an existing Java Builder in Kotlin. No doubt you’ve come across the builder pattern in Java before, for example if you’re an Android developer, you must’ve used an AlertDialog.Builder, an OkHttpClient.Builder, or a Retrofit.Builder at some point. Wrapping a builder like this is a good exercise in just pure DSL design. All you have to worry about is designing the API you provide with your wrapper, since all the implementation for whatever your DSL provides its users is already done inside the builder!

Our example case

It just so happens that I’m the creator and maintainer of a library that does this very thing, and a small part of its implementation is what we’re going to be using as our example. The original library is the wonderful and hugely popular MaterialDrawer by Mike Penz, which allows you to create complex, good looking, and customized navigation drawers in your application, all via various Builder objects in Java, with no XML writing involved on your part. This is what my library, MaterialDrawerKt provides a convenient Kotlin DSL wrapper for.

The Builder API

Let’s take a look at the drawer we’re going to be creating in our example.

android_drawer

Here’s the code, using the builders in the original API:

DrawerBuilder()
        .withActivity(this)
        .withTranslucentStatusBar(false)
        .withDrawerLayout(R.layout.material_drawer_fits_not)
        .addDrawerItems(
                PrimaryDrawerItem()
                        .withName("Home")
                        .withDescription("Get started here!"),
                PrimaryDrawerItem()
                        .withName("Settings")
                        .withDescription("Tinker around")
        )
        .withOnDrawerItemClickListener { view, position, drawerItem ->
            when(position) {
                0 -> toast("Home clicked")
                1 -> toast("Settings clicked")
            }
            true
        }
        .withOnDrawerListener(object: Drawer.OnDrawerListener {
            override fun onDrawerSlide(drawerView: View?, slideOffset: Float) {
                // Empty
            }

            override fun onDrawerClosed(drawerView: View?) {
                toast("Drawer closed")
            }

            override fun onDrawerOpened(drawerView: View?) {
                toast("Drawer opened")
            }
        })
        .build()

In this code, we’ve…
– set the Activity we want the drawer to appear in,
– made some layout adjustments so that the drawer is below the ActionBar,
– created just two menu items with names and descriptions,
– set a listener where we can handle item selections by position, using a SAM conversion to implement a single method interface,
– added a listener to detect drawer movement, using an object expression, because the necessary interface has multiple methods.

We saw two different builders used here, namely, the DrawerBuilder and PrimaryDrawerItem classes. While their builder syntax actually looks pretty decent and readable, we’ll see that a DSL can do even better.

Note that you can check out the entire working demo project for this article on GitHub here. See the commit history to follow the article step by step as we build our DSL.

Creating instances

Let’s start small. We’ll want to create a drawer with a drawer {} call, let’s implement just that.

fun Activity.drawer(dummy: () -> Unit) {
    DrawerBuilder()
            .withActivity(this)
            .build()
}

We’ve defined our first function as an extension on Activity, so that it’s available when we’re in one, and it can access the Activity instance as this without us having to pass it in explicitly.

Now, we should add our PrimaryDrawerItem instances. This syntax would be nice for a start:

drawer {
    primaryItem()
    primaryItem()
}

To get this, we’ll need a primaryItem function that’s only available within the drawer block, and that somehow adds an item to the DrawerBuilder we’ve already created.

To be able to call methods on our DrawerBuilder instance before we build() it, we’ll introduce a new wrapper class that holds it:

class DrawerBuilderKt(activity: Activity) {
    val builder = DrawerBuilder().withActivity(activity)

    internal fun build() {
        builder.build()
    }
}

We’ll update our original drawer function to create an instance of this wrapper class. We’ll also modify its parameter – by making the setup function an extension on our own class, the client of the DSL will be placed in a new scope inside the lambda passed to the drawer function, where the methods of DrawerBuilderKt become available, as we’ll see in a moment.

fun Activity.drawer(setup: DrawerBuilderKt.() -> Unit) {
    val builder = DrawerBuilderKt(this)
    builder.setup()
    builder.build()
}

You might have spotted that we’ve marked our own build method internal – this is because the only call to it will be the one inside the drawer function. Hence, there’s no need to expose it to the clients of our library.

The visibility of builder is another story – we’ll have to keep this public so that our library stays extensible. We could make it internal for the purpose of us implementing wrappers around the built-in drawer items, but that would mean that nobody else could add their own custom drawer items to the DSL – something you could do with the original library. This is functionality we don’t want to strip from our clients.

Now we can finally add the primaryItem function we were planning earlier. To make this available inside the lambda passed to drawer, we could make it a member of the DrawerBuilderKt class. Modifying this class for every new drawer item type we add, however, seems like an odd thing to do. The various types of drawer items should in no way affect how the drawer itself works.

We can instead use the same mechanics as clients would use to create custom drawer items. We’ll get a neat, decoupled design by adding primaryItem as an extension function:

fun DrawerBuilderKt.primaryItem() {
    builder.addDrawerItems(PrimaryDrawerItem())
}

We can now add blank drawer items to our drawer!

Setting properties

Before we get to setting the name and description of our drawer items with the DSL, we have the properties of DrawerBuilder to take care of, as we’ve seen in the very first code snippet. This is the syntax we’ll create for these:

drawer {
    drawerLayout = R.layout.material_drawer_fits_not 
    translucentStatusBar = false
}

These, of course, will be properties on the DrawerBuilderKt class so that they’re available in the right scope.

Since the original builder doesn’t let us access the values we’ve set, what we’ll need to create are essentially write-only properties. These properties won’t have backing fields to store values, all they’ll do is forward the calls to the appropriate builder methods.

Unfortunately, Kotlin only has properties that can be both read and written (var) and read-only ones (val). We’ll solve this by using a var, and throwing an exception when someone tries to read these properties. We’ll also include Kotlin’s powerful @Deprecated annotation that lets us mark using the getters an error, so that clients are stopped from doing so at edit/compile time, rather than just getting the runtime exception:

class DrawerBuilderKt(activity: Activity) {
    ...

    var drawerLayout: Int
        @Deprecated(message = "Non readable property.", level = DeprecationLevel.ERROR)
        get() = throw UnsupportedOperationException("")
        set(value) {
            builder.withDrawerLayout(value)
        }
}

Alternatives for setting properties

Now, we can move on to customizing the drawer items themselves. The obvious solution here is to continue with the same syntax style as before:

drawer {
    primaryItem {
        name = "Home"
        description = "Get started here!"
    }
}

We know how to do this by creating a wrapper class around PrimaryDrawerItem, and then adding a couple non-readable properties, just like we did before. But let’s do something more interesting, and create this alternative syntax:

drawer {
    primaryItem(name = "Home", description = "Get started here!")
}

This is also pretty straightforward, we’re just calling a function that has two parameters, and using named parameters for readability. Let’s add these parameters to primaryItem then. We’ll also throw in default values so that they’re each optional:

fun DrawerBuilderKt.primaryItem(name: String = "", description: String = "") {
    val item = PrimaryDrawerItem()
            .withName(name)
            .withDescription(description)
    builder.addDrawerItems(item)
}

This, of course, isn’t a feasible method for adding dozens of properties to an item we’re constructing with our DSL, adding a wrapper around the PrimaryItemClass with separate write-only properties that can be set in a setup lambda is still the way to go for most things.

However, this is a nice way to lift some very basic or commonly set properties to a more prominent position in the code. Here’s what the DSL could look like with some more properties implemented:

primaryItem(name = "Games", description = "Ready, player one?") {
    iicon = FontAwesome.Icon.faw_gamepad
    identifier = 3
    selectable = false
}

Listeners

We know how to add properties to our DSL, now let’s see how we can go about listeners. We’ll start with the easy one, setting the OnDrawerItemClickListener to handle item clicks for a given position in the drawer. Here’s our goal:

drawer {
    onItemClick { position ->
        when (position) {
            0 -> toast("Home clicked")
            1 -> toast("Settings clicked")
        }
        true
    }
}

onItemClick will be a method in DrawerBuilderKt, and it will take a lambda parameter that can be called when the original listener fires:

class DrawerBuilderKt(activity: Activity) {
    ...

    fun onItemClick(handler: (view: View?, position: Int, drawerItem: IDrawerItem<*, *>) -> Boolean) {
        builder.withOnDrawerItemClickListener(handler)
    }
}

We’re making use of SAM conversion with the call to the withOnDrawerItemClickListener method of the builder here. The usual SAM conversion syntax would have us passing in a lambda that gets transformed to the OnDrawerItemClickListener interface, but instead, we’re going just a small step further, and we’re passing in the handler parameter which has the appropriate function type for a conversion.

We’ll simplify the above method a bit, by taking a lambda which only gets the position passed to it, as clients will usually only care about that parameter. We’re using SAM conversion again, this time with a regular lambda, because we want to ignore some parameters when calling our simpler handler parameter.

class DrawerBuilderKt(activity: Activity) {
    ...

    fun onItemClick(handler: (position: Int) -> Boolean) {
        builder.withOnDrawerItemClickListener { _, position, _ -> handler(position) }
    }
}

Of course, having only this version of the method would hide functionality of the original library, so in the real wrapper library, I’ve included both of these.

Complex listeners

Last but not least, let’s see what we can do about the OnDrawerListener in our example. This interface has three methods, so the previous, simple solution won’t work here. As always, let’s start with the syntax we want to achieve. Not that we’re only setting two of the three methods that the interface defines.

drawer {
    onClosed {
        toast("Drawer closed")
    }
    onOpened {
        toast("Drawer opened")
    }  
}

As you can see, it would be nice to be able to specify either one or multiple of the methods of the interface independently of each other. We know that we’ll want to define three methods to take the appropriate handler lambdas, very similarly to what we did before:

class DrawerBuilderKt(activity: Activity) {
    ...

    fun onOpened(handler: (drawerView: View) -> Unit) {
        // TODO implement
    }

    fun onClosed(handler: (drawerView: View) -> Unit) {
        // TODO implement
    }

    fun onSlide(handler: (drawerView: View, slideOffset: Float) -> Unit) {
        // TODO implement
    }
}

The question is how to pass these handlers to the builder we’re holding. We can’t make a withOnDrawerListener call in each of them and create an object that wraps just that one handler, as the object created there would always implement just one of the three methods.

What I came up with for this is an object property in our DrawerBuilderKt wrapper class that implements the OnDrawerListener interface, and delegates each of these calls to one of its properties.

class DrawerBuilderKt(activity: Activity) {
    ...

    private val onDrawerListener = object : Drawer.OnDrawerListener {
        var onSlide: ((View, Float) -> Unit)? = null

        override fun onDrawerSlide(drawerView: View, slideOffset: Float) {
            onSlide?.invoke(drawerView, slideOffset)
        }

        var onClosed: ((View) -> Unit)? = null

        override fun onDrawerClosed(drawerView: View) {
            onClosed?.invoke(drawerView)
        }

        var onOpened: ((View) -> Unit)? = null

        override fun onDrawerOpened(drawerView: View) {
            onOpened?.invoke(drawerView)
        }
    }
}

All our previous methods have to do then is to set these properties when they’re called:

class DrawerBuilderKt(activity: Activity) {
    ...

    fun onOpened(handler: (drawerView: View) -> Unit) {
        onDrawerListener.onOpened = handler
    }

    fun onClosed(handler: (drawerView: View) -> Unit) {
        onDrawerListener.onClosed = handler
    }

    fun onSlide(handler: (drawerView: View, slideOffset: Float) -> Unit) {
        onDrawerListener.onSlide = handler
    }
}

Of course, we’ll still have to pass this object to the builder at some point – we’ll do that after the setup lambda passed to drawer has already done its work, and it calls our DrawerBuidlerKt.build() method:

class DrawerBuilderKt(activity: Activity) {
    val builder = DrawerBuilder().withActivity(activity)

    internal fun build() {
        builder.withOnDrawerListener(onDrawerListener)
        builder.build()
    }

    ...
}

Result

As a reminder, here’s the builder code we started the article with:

DrawerBuilder()
        .withActivity(this)
        .withTranslucentStatusBar(false)
        .withDrawerLayout(R.layout.material_drawer_fits_not)
        .addDrawerItems(
                PrimaryDrawerItem()
                        .withName("Home")
                        .withDescription("Get started here!"),
                PrimaryDrawerItem()
                        .withName("Settings")
                        .withDescription("Tinker around")
        )
        .withOnDrawerItemClickListener { view, position, drawerItem ->
            when(position) {
                0 -> toast("Home clicked")
                1 -> toast("Settings clicked")
            }
            true
        }
        .withOnDrawerListener(object: Drawer.OnDrawerListener {
            override fun onDrawerSlide(drawerView: View?, slideOffset: Float) {
                // Empty
            }

            override fun onDrawerClosed(drawerView: View?) {
                toast("Drawer closed")
            }

            override fun onDrawerOpened(drawerView: View?) {
                toast("Drawer opened")
            }
        })
        .build()

And then here’s the final DSL we’ve put together:

drawer {
    drawerLayout = R.layout.material_drawer_fits_not
    translucentStatusBar = false

    primaryItem(name = "Home", description = "Get started here!")
    primaryItem(name = "Settings", description = "Tinker around")

    onItemClick { position ->
        when (position) {
            0 -> toast("Home clicked")
            1 -> toast("Settings clicked")
        }
        true
    }
    onClosed {
        toast("Drawer closed")
    }
    onOpened {
        toast("Drawer opened")
    }
}

I hope this serves as a good example of how much better looking and more expressive a DSL can be than builder style solutions. Another benefit is how much easier making changes in the DSL is, which of course becomes apparent when you’re actually making them (but worrying about placing commas in the right places, for example, is in the past).

Conclusion

Thank you for sticking with me for this entire journey. I hope you got a good feel for how to design your own DSLs (always write down your desired syntax first!), and how to structure your DSL implementations.

If you’re interested in more, I recommend checking out the source of the actual MaterialDrawerKt library, as it deals with many more advanced concepts that I couldn’t fit in this post. Among other things, it uses generics and inheritance heavily to deal with MaterialDrawer‘s complex hierarchy of built-in drawer item types, restricts function calls and property accesses to the appropriate levels of the DSL hierarchy, and much more. I might cover these in a future article.

Additionally, you can find another article covering the process of writing a DSL here, and another article about more general DSL design here.

But this is it for now, and with that, it’s now your time to go and start creating your own DSLs. Good luck!

Márton is a Kotlin enthusiast from Hungary, currently working as an Android developer at AutSoft, while still pursuing a master’s degree in computer engineering. Brags a lot about being ranked third in the top users list of the Kotlin tag on Stack Overflow.

Please follow and like this Blog 🙂
Web Applications with Kotlin ktor

Web Applications with Kotlin ktor

Introduction

Disclaimer: This ktor article was originally published in the Dzone Web Development Guide, which can be downloaded here.

When Google made Kotlin an official language for Android a few months ago at Google I/O, the language gained a lot of popularity in the Android world quickly. On the server side though, Kotlin is not as broadly adopted yet and some people still seem to be cautious when backend services are involved. Other developers are convinced that Kotlin is mature enough and can safely be used for any server application in which Java could play a role otherwise.
If you want to develop web apps with Kotlin, you can choose from various web frameworks like Spring MVC/WebFlux, Vert.x, Vaadin and basically everything available for the JVM. Besides the mentioned frameworks there’s also a Kotlin specific library available for creating web applications, called Kotlin ktor. After reading this article, you’ll know what ktor and its advantages are and how you can quickly develop a web application in Kotlin.

Kotlin ktor

The web application framework ktor, itself written in Kotlin, is meant to provide a tool for quickly creating web applications with Kotlin. The resulting software may be hosted in common servlet containers like Tomcat or standalone in a Netty for example. Whatever kind of hosting you choose, ktor is making heavy use of Kotlin Coroutines, so that it’s implemented 100% asynchronously and mainly non-blocking. ktor does not dictate which frameworks or tools to be used, so that you can choose whatever logging, DI, or templating engine you like. The library is pretty light-weight in general, still being very extensible through a plugin mechanism.
One of the greatest advantages attributed to Kotlin is its ability to provide type-safe builders, also known as Domain Specific Languages (DSL). Many libraries already provide DSLs as an alternative to common APIs, such as the Android lib anko, the Kotlin html builder or the freshly released Spring 5 framework. As we will see in the upcoming examples, ktor also makes use of such DSLs, which enable the user to define the web app’s endpoints in a very declarative way.

Example Application

In the following, a small RESTful (Not sure, if everyone will agree) web service will be developed with ktor. The service will use an in-memory repository with simple Person resources, which it exposes through a JSON API. Let’s look at the components.

Person Resource and Repository

According to the app’s requirements, a resource “Person” is defined as a data class and the corresponding repository as an object, Kotlin’s way of applying the Singleton pattern to a class.


data class Person(val name: String, val age: Int){
    var id: Int? = null
}

The resource has two simple properties, which need to be defined when a new object is constructed, whereas the id property is set later when stored in the repository.
The Person repository is rather unspectacular and not worth observing. It uses an internal data store and provides common CRUD operations.

Endpoints

The most important part of the web application is the configuration of its endpoints, exposed as a REST API. The following endpoints will be implemented:

EndpointHTTP MethodDescription
/personsGETRequests all Person resources
/persons/{id}GETRequests a specific Person resource by its ID
/personsDELETERequests all Person resources to be removed
/persons/{id}DELETERequests a specific Person resource to be removed by its ID
/personsPOSTRequests to store a new Person resource
/GETDelivers a simple HTML page welcoming the client

The application won’t support an update operator via PUT.

Routing with Ktor

Now ktor comes into play with its structured DSL, which will be used for defining the previously shown endpoints, a process often referred to as “routing”. Let’s see how it works:


fun Application.main() {
    install(DefaultHeaders)
    install(CORS) {
        maxAge = Duration.ofDays(1)
    }
    install(ContentNegotiation){
        register(ContentType.Application.Json, GsonConverter())
    }

    routing {
        get("/persons") {
            LOG.debug("Get all Person entities")
            call.respond(PersonRepo.getAll())
        }
    }
    // more routings
}

The fundamental class in the ktor library is Application, which represents a configured and eventually running web service instance. In the snippet, an extension function main() is defined on Application, in which it’s possible to call functions defined in Application directly, without additional qualifiers. This is done by invoking install() multiple times, a function for adding certain ApplicationFeatures into the request processing pipeline of the application. These features are optional and the user can choose from various types. The only interesting feature in the shown example is ContentNegotiation, which is used for the (de-)serialization of Kotlin objects to and from JSON, respectively. The Gson library is used as a backing technology.
The routing itself is demonstrated by defining the GET endpoint for retrieving all Person resources here. It’s actually straight-forward since the result of the repository call getAll() is just delegated back to the client. The call.respond() invocation will eventually reach the GsonSupport feature taking care of transforming the Person into its JSON representation. The same happens for the remaining four REST endpoints, which will not be shown explicitly here.

The HTML builder

Another cool feature of ktor is its integration with other Kotlin DSLs like the HTML builder, which can be found on GitHub. By adding a single additional dependency to a ktor app, this builder can be used with the extension function call.respondHtml(), which expects type-safe HTML code to be provided. In the following example, a simple greeting to the readers is included, which the web service exposes as its index page.


get("/") {
    call.respondHtml {
        head {
            title("ktor Example Application")
        }
        body {
            h1 { +"Hello DZone Readers" }
            p {
                +"How are you doing?"
            }
        }
    }
}

Starting the Application

After having done the configuration of a ktor application, there’s still a need to start it through a regular main method. In the demo, a Netty server is started standalone by doing the following:


fun main(args: Array) {
    embeddedServer(Netty, 8080, module = Application::main).start(wait = true)
}

The starting is made pretty simple by just calling the embeddedServer() method with a Netty environment, a port and the module to be started, which happens to be the thingy defined in the Application.main() extension function from the previously shown example.

Testing

A web framework or library is only applicable if it comes with integrated testing means, which ktor actually does. Since the GET routing for retrieving all Person resources was already shown, let’s have a look at how the endpoint can be tested.


@Test
fun getAllPersonsTest() = withTestApplication(Application::main) {
    val person = savePerson(gson.toJson(Person("Bert", 40)))
    val person2 = savePerson(gson.toJson(Person("Alice", 25)))
    handleRequest(HttpMethod.Get, "/persons") {
        addHeader("Accept", json)
    }.response.let {
        assertEquals(HttpStatusCode.OK, it.status())
        val response = gson.fromJson(it.content, Array::class.java)
        response.forEach { println(it) }
        response.find { it.name == person.name } ?: fail()
        response.find { it.name == person2.name } ?: fail()
    }
    assertEquals(2, PersonRepo.getAll().size)
}

This one is quite simple: Two resource objects are added to the repository, then the GET request is executed and some assertions are done against the web service response. The important part is withTestApplication(), which ktor offers through its testing module and makes it possible to directly test the Application.
The article presented basically everything worth knowing in order to get started with ktor web applications. For more details, I recommend the ktor homepage or the samples included in the ktor repository.

Takeaways

In this article we had a look at the Kotlin web service library ktor that provides simple tools for writing a light-weight web application in Kotlin very quickly. ktor makes heavy use of Kotlin’s beautiful features, especially DSLs, Coroutines and extension functions, all of which make the language and ktor itself so elegant. This mainly separates ktor from other powerful frameworks, which in fact can be used with Kotlin very smoothly, but, since not completely written in Kotlin, lack certain features you can find in ktor. It’s a great place to start with web applications because of its simplicity and ability to be extended with custom features if needed, following the principle “simple is easy, complex is available”.
The complete source code of the developed web application can be found on GitHub, it’s backed by a Gradle build.

Simon is a software engineer based in Germany with 7 years of experience writing code for the JVM and also with JavaScript. He’s very passionate about learning new things as often as possible and a self-appointed Kotlin enthusiast.

Please follow and like this Blog 🙂
Kotlin Function Literals with Receiver – Quick Introduction

Kotlin Function Literals with Receiver – Quick Introduction

Kotlin Function Literals with Receiver – The Foundation for DSLs and many Library Functions

Today I want to give a quick introduction to Kotlin Function Literals with Receiver. This concept is what makes Kotlin great for designing Domain Specific Languages as we know it from Groovy for example. Also, Kotlin’s standard library includes many functions which many of you have already used or at least seen probably: apply and with are the most prominent ones.

Read More Read More

Simon is a software engineer based in Germany with 7 years of experience writing code for the JVM and also with JavaScript. He’s very passionate about learning new things as often as possible and a self-appointed Kotlin enthusiast.

Please follow and like this Blog 🙂