Blog

Building web apps with Vaadin and Kotlin

By  
Martin Vyšný
·
On May 31, 2017 7:53:00 AM
·

Kotlin, the new kid in the family of JVM-based languages, is slowly but steadily capturing the hearts of many Java developers while finding its way to many prominent Java-related projects, such as Android, Spring, and Gradle. Using Vaadin Flow with Kotlin to build web apps is also possible!

I recently wrote a series of articles explaining the ideas behind the Karibu DSL and JPA integration and exploring ways of Kotlin language features to replace the traditional Spring/JavaEE approach.

1. The DSL

For the impatient, here is a taste of how Vaadin would benefit from having Kotlin's support. First, use DSL or Domain Specific Language, or write 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:

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 a 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 of 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() = ...

Fire up your IDE, write Services., press Ctrl+Spaceand 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 for the Vaadin Flow framework. 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 offers Vaadin DSL and 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.

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.

Martin Vyšný
Martin Vyšný: Vaadiner since Sep 2016. Prefers pragmatic approach to programming, strives to write a clean, simple, intuitive, easy-to-understand OOP code, without any clever hacks. Loves Vaadin and Kotlin.
Other posts by Martin Vyšný