The MVP (model-view-presenter) is a solid architecture pattern for Vaadin projects of all sizes. However there are many ways to achieve it. I would like to have a MVP architecture in my Vaadin projects and use the cool features of the Vaadin framework and its eco-system like a WYSIWYG editor for UI layout or the official Vaadin CDI add-on for dependency injection and standard JEE messaging.

Some words on the Model-View-Presenter pattern (aka theory)

When choosing a fitting architecture for your web applications, you often seek to separate the business logic from the user interface code and try to maximize the amount of code that is testable with automated unit or user interface tests. The MVP pattern is a good choice for these tasks. When searching for the MVP pattern on the web, you will find many sites that will explain the 2 variations of the MVP pattern: the “passive view” and the “supervising controller” (so I won’t cover the theory of this pattern in detail).

I prefer to use the “passive view” variation of the MVP architecture pattern, where the view is passive and does not update the model attributes. It supports a test-driven
approach much better than the “supervising controller”, because the view simply concentrates on the behaviour of UI elements and showing the correct data. It does not have to deal with data synchronisation between model and view or business logic as this is placed in the presenter.

I would like to sum up the MVP approach I use in my projects in this figure:

MVP overview

 

When I first heard about MVP and wanted to try it out for an upcoming project, I needed to find out, how to archieve a clear separation of concerns and tried to sum it up with ansering the question: “Who does what in MVP?”

The Model:

  • holds the data model (and nothing else)
  • grants access to all model attributes with getters and setters
  • can send messages to the presenter (to inform him that the model has been updated)

The View:

  • contains or gives access to the UI elements (input fields, select boxes…)
  • contains the behaviour of all elements of the current view (Click-Listeners, Value-Change-Listeners…)
  • sends messages to the presenter (to inform him that the user has done something on the UI)

The Presenter:

  • calls backend services
  • contains or executes the business logic
  • sets the values for the data model
  • calls view methods to refresh the user interface

The sample project

To show the usage of MVP I created a small Vaadin 8 project that I also used to explain the usage of CDI and the Navigator class of the Vaadin framework. You can view and download the code from https://bitbucket.org/mekaso/vaadin-cdi-mvp/branch/vaadin8

As a difference to many other MVP fueled projects I found on the web I do not create the layout of the UI (layouts, labels, input fields…) in the view programatically. I want to use a WYSIWYG editor (if possible) for creating the user interface. Vaadin offers the very good Vaadin designer as the official WYSIWYG editor, but you can also use the very cool Javade add-on. I created the UI for the sample project with Javade and imported the classes into the project (so that you will not find any unnecessary dependencies in the project).

The glue between M and V and P

As you can see in the architecture picture on this page, the presenter is the center of MVP (it should be called MPV). It holds references to the model and the view and is able call the public methods of these classes. In other (Java) words: The presenter class has the model and the presenter as attributes that are automatically injected by CDI.

@NormalViewScoped
public class MasterPresenter {
  @Inject
  private MasterView view;
  @Inject
  private MasterViewModel model;
  @Inject
  private PersonService service;
  ...
}

The model and view do not hold references to the presenter (or each other). The are loosely coupled (to the presenter) and communicate by sending messages. Lets see the Java code for the communication between view and presenter:

Java code for the view:

@CDIView(VIEW_NAME)
public class MasterView extends CustomComponent implements View {
  private static final long serialVersionUID = 1L;
  public static final String VIEW_NAME = "";
  @Inject
  private javax.enterprise.event.Event<InitViewEvent> presenterLauncher;
  
  private MasterLayoutImpl layout;
  
  @PostConstruct
  public void init() {
    this.layout = new MasterLayoutImpl();
  }
  
  @Override
  public void enter(ViewChangeEvent event) {
    super.setCompositionRoot(this.layout.getRootComponent());
    initComponents();
    addViewBehaviour();

    this.initViewEventLauncher.fire(new InitViewEvent());
  }
}

It is important to know that the Vaadin framework calls and initializes the view first (and not the presenter). First the CDI container will call the init method (because it is annotated with @PostConstruct), then it will call the enter method (every time a user enters the view). In the enter method of the view we initialize the UI components, define how they behave and call the presenter through a CDI event. The presenter will receive this event with a method that uses the @Observes annotation:

@NormalViewScoped
public class MasterPresenter {
  ...
  public void init(@Observes InitViewEvent event) {
    this.view.showVersion(this.service.versionInfo());
    this.model.setPersonList(this.service.findAll());
    this.view.fillPersonTableWithData(this.model.getPersonList());
  }
}

The init(@Observes …) method will be executed to perform the business logic (load some data using a service), fill the model with the data from the backend and finally tell the view to update a table with the model’s data. By using this strategy you have separated the business logic calls (the presenter’s duty) from the UI logic (the views job) and you are able to write unit tests for all UI classes.

If we did everything correct and let model, view and presenter do just what they are supposed to do, a good way (but not the only way) to verify the implementation of our MVP architecture, is to check the imports of our MVP classes.

Model imports

  • the model pojo classes
  • CDI scope annotation (e. g. @Dependent or @ApplicationScoped)

View imports

  • can import all classes of the Vaadin UI packages: import com.vaadin.ui.*
  • CDI scope and event annotations: import com.vaadin.cdi.CDIView, javax.enterprise.event.Event…

Presenter imports

  • the backend services
  • the corresponding model and view classes
  • CDI scope and event annotations: import com.vaadin.cdi.NormalViewScoped, import javax.enterprise.event.Observes…

The good thing about this pattern is, that it makes sense for all kinds and sizes of Vaadin projects (that are not completely trivial). In the next blog post I will show, how to write unit tests for this CDI driven MVP approach.

By Meik Kaufmann

I am a certified oracle enterprise architect and like to share my knowledge and experience that I gain in the projects I am working on.

2 thoughts on “A practical guide to MVP for Vaadin”
  1. Nice article!

    You mention @NormalViewScoped or @NormalSessionScoped for the Presenter. When do you use what? I expect @NormalViewScoped, because this is consistent with @CDIView

    1. @NormalSessionScoped was just a typo in the MVP overview image (I will correct that pretty soon). You should use @NormalViewScope for your presenter classes. Using a SessionScope will only force you to also use SessionScope for model and view classes. This would increase session size needlessly. As you said @NormalViewScoped works nicely with @CDIView.

Leave a Reply to Ronald Muller Cancel reply

Your email address will not be published. Required fields are marked *