Close
Back

Vaadin ♡ Kotlin

Kotlin, the new kid in the family of JVM-based languages, is slowly but steadily capturing hearts of many Java developers. All the while finding its way to many prominent Java-related projects, such as Android, Spring and Gradle. It is indeed possible to use Vaadin with Kotlin as well!

I recently wrote a series of articles which not only explain the ideas behind the Vaadin DSL and JPA integration, but also explores ways of Kotlin language features replacing the traditional Spring/JavaEE approach.

1. The DSL

For the impatient, here is a taste of how Vaadin would benefit from having Kotlin support. First, DSL, or Domain Specific Language, or writing your UI in Kotlin:

@AutoView
class CrudView: VerticalLayout(), View {
  // you can restrict the values by writing the following expression.
  // This is an example of a SQL DSL:
  private val personsDataProvider = jpaDataProvider<Person>()
     .and { Person::age between 20..60 }

  init {
    setSizeFull()
    horizontalLayout {
      createButton = button("Create New Person (Ctrl+Alt+C)") {
        onLeftClick { 
          createOrEditPerson(Person(created = Date())) 
        }
        clickShortcut = Ctrl + Alt + C
      }
      button("Generate testing data", { generateTestingData() })
    }
    // the JPA list demo - shows all instances of a particular JPA entity,
    // allow sorting and filtering
    personGrid = grid(Person::class, dataProvider = personsDataProvider) {
      expandRatio = 1f; setSizeFull()
      // example of a custom renderer which converts value to a
      // displayable string.
      column(Person::created) {
        setConvertingRenderer { it!!.toInstant().toString() }
      }
      // show these columns, and in this order. Note the static
      // Person property references
      showColumns(Person::id, Person::name, Person::age, 
          Person::dateOfBirth, Person::maritalStatus, Person::alive,
          Person::created)
      // add additional columns with buttons
      addColumn({ "Show" }, ButtonRenderer<Person>(
          { event -> PersonView.navigateTo(event.item) }))
      addColumn({ "Edit" }, ButtonRenderer<Person>(
          { event -> createOrEditPerson(event.item) }))
      addColumn({ "Delete" }, ButtonRenderer<Person>(
          { event -> deletePerson(event.item.id!!) }))
      // you can even auto-generate filter bar.
    }
  }
}

This code produces the following UI:

(This is taken from Vaadin-on-Kotlin's example project: CrudView.kt, so you can already explore these ideas for yourself)

The advantage of using Kotlin DSL over defining the UI via Java code is the inherently visible structure - it is clear how components are nested in one another. That is the same advantage that is often said to be an advantage of markup languages over Java code. The advantage over Design htmls is that this is statically-typed Kotlin code, so the compiler will check the correctness for us, and there is no need to waste CPU cycles to parse the html. You can also use any for loops and parametrization as you like, and you can easily employ I18N.

The Kotlin DSL code may look undecipherable at first, but what if Vaadin Designer could render a read-only view of this view?

2. Database Access

Using blocks, you can define a db function which will run given block in a transaction, thus allowing you to write the Delete button as follows:

button("Delete") {
  onClick { db { em.delete(person) } }
}

Or attach find methods directly to your JPA entities:

@Entity
data class Person(...) {
  companion object {
    fun findAll(): List<Person> = db { em.findAll<Person>() }
    fun findByName(name: String): List<Person> = db {
      em.createQuery("...").resultList 
    }
  }
}

This will allow you to write expressions like val zaphods = Person.findByName("Zaphod") and helps you avoid the necessity of creating @Transactional DAOs.

3. Service directory and discovery

You can use Kotlin's extension mechanism to attach properties to a pre-agreed object. Think the Services object (and Session object) in a common project:

object Services {}
object Session {}

Every module can then add a service simply as follows:

val Services.weatherForecast: WeatherForecastService get() = ...
val Session.loggedInUser: User get() = ...

You just fire up your IDE, write Services., press Ctrl+Space and watch the IDE Kotlin plugin do the magic and auto-complete the services for you. No further need for injections!

There are also a couple of interesting efforts to bring an even better Kotlin experience to Vaadin:

  1. The Kaadin library - an open-source so-called DSL library to create Vaadin UIs in pure Kotlin. The Kaadin page at https://nfrankel.github.io/kaadin/ lists many interesting examples of DSL-modeled UIs. Supports Vaadin 7.7.x

  2. The Karibu-DSL is also a DSL library, but it targets Vaadin 8.1.x instead. You can check out the online demo of the example application.

  3. Vaadin-on-Kotlin is a more complete way of creating apps with Vaadin and Kotlin, since it not only offers Vaadin DSL, but it also allows for integration with JPA (both DataProvider and JPAContainer), publishing your own REST services, and allows you to build a complete web app running on pure Servlet containers. Supports Vaadin 8.x including v7 compatibility mode.

If you’d like to shape the future of Vaadin-Kotlin integration, please join the development of those libraries. Just trying them out and providing bug reports or enhancement requests is the easiest way to join the effort!

Read the full Vaadin apps in Kotlin tutorial

Comments
Trackback URL:

Add Comment
Who's the author of this post? I see a photo and a description, but no name.
Posted on 6/27/17 4:48 AM.
Apologies, my profile was incomplete. Fixed, thanks! emoticon
Posted on 6/28/17 7:47 AM in reply to Robert Mikes.