License Maven Central

linkki is an open source web framework to build great looking business applications in pure Java with minimal effort.

When to use

linkki might be the perfect fit for you if you have the following requirements:

  • You have UI pages that have to reflect a large domain model with complex business logic.

  • You don’t want to spend too much time and effort in the development of the UI. This is often the case if the application tries to fully automate processing, leaving the UI only for those use cases that require manual interaction by back-office staff.

  • You prefer to code both domain logic and UI in Java.

You can use linkki with plain Java, with Spring Boot, Spring inside an application server or JEE.

Conceptual Overview

Domain Model

linkki is a framework to build the UI layer for a business application. The only assumption about the business layer is that you use a domain (entity) model to capture the structure of the business data.


linkki is a server side framework that can support different UI frameworks. Therefore it is divided into an UI framework independent core and UI framework specific modules like linkki-core-vaadin-flow. Linkki's core module is UI framework independent, but it needs a UI framework specific implementation to work. We offer such implementations based on Vaadin, which allows you to write UI in Java. The layouts and widgetsets are provided by Vaadin. It also handles the whole communication between the browser and the server.

However, the code has only very few direct dependencies to Vaadin API when using linkki. Most of the interaction with Vaadin is encapsulated by linkki.


The fundamental building blocks for a linkki UI are sections. A section is defined as a group of related (input) fields/controls. For example, a section might contain the data about a person such as name and date of birth. The fields for the address such as country, city and street might be grouped together in another section. linkki provides standard layouts for the sections to give the UI a consistent look and to speed up your development. The following screenshot shows the two mentioned example sections.


Annotated Presentation Model Objects

Presentation model objects (aka view model) as explained by Martin Fowler are used to provide data for the UI and to process data changed in the UI. To put it simple, you can write one PMO for each section when using linkki. Section PMOs are annotated with annotations that define how a section looks. At runtime, linkki creates the (Vaadin) layouts and controls based on the annotations.

The following is the PMO code for the partner data section shown above.

@UISection(caption = "Partner")
public class PartnerSectionPmo {

    private Partner partner;

    public PartnerSectionPmo(Partner partner) {
        this.partner = partner;

    @UITextField(position = 1, label = "Name", width = "20em")
    public String getName() {
        return partner.getName();

    public void setName(String newName) {

    @UIDateField(position = 2, label = "Date of Birth")
    public LocalDate getDateOfBirth() {
        return partner.getDateOfBirth();

    public void setDateOfBirth(LocalDate newDateOfBirth) {

Data binding

To move the data from the UI controls through your PMOs to the domain model and back, linkki provides a data binding mechanism.

Each time the user changes the data in a field, linkki calls the appropriate setter method in the PMO. For example if the user changes the person’s name, setName(newName) is called. In the same way, getName() provides the name displayed in the control. The following diagram illustrates the interaction between User Interface and Business Layer.

manual data binding

Straight through data binding

In the sample code above, the PMO reads and updates the domain model. As you can see, the code is already repetitive with only two fields. To reduce the overhead in code, linkki allows you to bind the controls directly to properties in the domain model if you don’t need to apply any transformation or calculation to the displayed data. The following is a shorter PartnerSectionPmo which uses the above explained linkki feature.

@UISection(caption = "Partner")
public class PartnerSectionPmo {

    private Partner partner;

    public PartnerSectionPmo(Partner partner) {
        this.partner = partner;

    public Partner getPartner() {
        return partner;

    @UITextField(position = 1, label = "Name", width = "20em", modelAttribute = "name")
    public void name() {
        // just binding

    @UIDateField(position = 2, label = "Date of Birth", modelAttribute = "dateOfBirth")
    public void dateOfBirth() {
        // just binding

Instead of the getter and setter method you just need to write a placeholder method and declare the attribute/property name in the annotation. Additionally, you have to provide an annotated method that returns the model object. linkki then binds the controls directly to the domain model. The mechanism also supports more than one model object per section.

linkki data binding

Binding all properties defining visual behavior

linkki is not only able to bind field values to PMO properties but can also bind other typical aspects such as enabled state, visible state and the available values shown in a combo box. In fact, all properties of a UI control can be bound this way.

To demonstrate this, we extend our previous example: A partner might now be either a person or a company. The date of birth field should then only be enabled for persons. Here is the new section and the code for enabling the date of birth field depending on the type of person.

input field with code
    @UIDateField(position = 2, label = "Date of Birth", modelAttribute = "dateOfBirth", enabled = DYNAMIC)
    public void dateOfBirth() {
        // model binding

    public boolean isDateOfBirthEnabled() {
        return partner.getType() == PartnerType.NATURAL_PERSON;

In the date of birth annotation, the enabled attribute specifies that the enabled state of the control should change dynamically. linkki uses a naming convention to find the method that calculates the dynamic state. In this case, the calculation is done in the method isDateOfBirthEnabled().

dynamically enabled field

Well-structured UI Code

UI code written using linkki has a very clear structure. Each section is defined by one PMO. If you name your PMO classes after the section headlines, you can find the relating code of any given section in seconds even if you are unfamiliar with the code base.

Testable UI logic

PMOs are plain old Java objects. Except for linkki annotations, they don’t need any dependency to infrastructure code. So it is very simple and straightforward to write tests for your PMOs.

What else?

There is a lot more that helps you to build a whole business application such as:

  • Simple API to create tables with dynamic content

  • Automatic highlighting of inputs based on validation logic defined in the business layer

  • Support of PMO based creation of sections in dialogs

  • An overall application layout with an application menu