Simon has posted 6 posts at DZone. View Full User Profile

Test Driving the MVVM Pattern with ZK Ajax

10.20.2011
| 6230 views |
  • submit to reddit

Introduction


This article is the latest in a series demonstrating alternative GUI Design Patterns using the ZK RIA AJAX framework. Two previous articles used the Model-View-Presenter and Model-View-Controller patterns in the context of implementing a simple "todo reminders" screen. This article showcases the Model-View-ViewModel pattern to implement the same simple screen.

The example code for this article is with the ZkToDo2 project hosted on SourceForge under the ZKForge project. The code is built with Maven and aims to be self installing. The code will even run itself in an embedded Servlet container which Maven will download and launch. All you need is either the command-line Maven build system or a Maven plug-in for your chosen IDE. The easiest way to get started with the code is to build and run the application on the command-line using only a stock Maven distribution using the instructions here. Alternatively the steps to checkout, build, run and debug the application using Eclipse with the m2eclipse Maven Eclipse plug-in are here.

Why UI Design Patterns?


When building a system it is convenient to discuss the requirements in terms of the screens. Yet the screens of a system are likely to change all the way up to go-live and beyond. This happens because the presentation is incidental to what the user of the system is logically doing; know as the Use Case or User Story (e.g. user buys a book). Whilst features evolve slowly over time the screens may vary rapidly between project iterations. Separating business application logic from screen update logic makes for supple code.

Organising the UI business logic code into a separate layer with no compile time dependencies on UI framework code allows for easer JUnit test coverage. The separation of concerns of "Business Logic" from "Rendering Logic" makes it easier to both enhance application functionality and to re-arrange screens. In contrast putting application Use Case logic directly inside of screen rendering classes makes for a more rigid and brittle code-base.

The Model-View-ViewModel Pattern


The core concept of GUI Design Patterns is "separated presentation". The references section below includes a link to Martin Fowler's excellent discussion of this topic. Many design patterns have both a View and a Model logical layer. The well know pattern MVC introduces a Controller layer to mediate between the Model and the View. The Model-View-ViewModel pattern replaces the concept of a Controller with a ViewModel. A ViewModel is an POJO model of the application logic; it is the naked UI business logic without a screen. On top the naked logic we bind one or more active screens. The key to this approach is a UI framework Binder. This article will describe how the ZK Binder technology animates the View to render the changed state of the ViewModel. The key role of the UI framework Binder gives rise to an alternative name for this pattern: Model-View-Binder (MVB).

The diagram above shows the logical layering of the MVVM pattern. The View layer is the ZK Desktop and its supporting Binder which will be described below. Commands are fired from the View into the ViewModel in response to user actions. The changing data and state of the ViewModel is then loaded back into the View to show the effects of the commands.

The DomainModel below the ViewModel comprises of the application services, JPA entities and the related data access logic of a typical application business tier. The book "POJOs In Action" by Chris Richardson gives an excellent introduction on using test driven development to build a well layered DomainModel. The sample application uses Spring and Hibernate JPA for its internal layering and the Detached Entity pattern (no DTOs).

The Example Screen


The MVVM version of the "todo reminders" screen is defined within the single file zktodo_c.zul. Here is a screenshot:


The screen renders a collection of Reminder objects which are JPA entities stored in the database:
@Entity @Table(name = "REMINDER"
public class Reminder {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "REMINDER_ID")
    private Long id;
 
    @Column(name = "NAME")
    private String name = "";
 
    @Column(name = "PRIORITY")
    private int priority = 0;
 
    @Column(name = "DATE")
    private Date date = new Date(System.currentTimeMillis());
 
    ... // setters and getters, equals and hashcode, constructors
}
The syntax of the ZUL file is a dialect of XUL:
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" ?>
<?init class="org.zkforge.zktodo2.binding.CommandBinderInit"?>
<?variable-resolver class="org.zkoss.zkplus.spring.DelegatingVariableResolver" ?>
<zk xmlns="http://www.zkoss.org/2005/zul">
<window>
<listbox id="list" multiple="true" rows="12"
        model="@{toDoViewModel.reminders, load-after='add.onClick,update.onClick,delete.onClick'}"
        selectedItem="@{toDoViewModel.selectedReminder}">
    <listhead>
        <listheader label="Item" />
        <listheader label="Priority" width="80px" />
        <listheader label="Opened" width="90px" />
    </listhead>
    <listitem self="@{each=reminder}">
        <listcell label="@{reminder.name}"/>
        <listcell label="@{reminder.priority}"/>
        <listcell label="@{reminder.date, converter='org.zkforge.zktodo2.DateFormatConverter'}"/>
    </listitem>
</listbox>
<vbox>
    <hbox>
     Item:<textbox cols="40" constraint="no empty"
        value="@{Model.selectedReminder.name, load-after='add.onClick,delete.onClick'}"/>
     Priority:<intbox id="priority" cols="1" constraint="no empty"
        value="@{toDoViewModel.selectedReminder.priority, load-after='add.onClick,delete.onClick'}"
        />
     Date:<datebox id="date" cols="14" constraint="no empty"
        value="@{Model.selectedReminder.date, load-after='add.onClick,delete.onClick'}"
        onChange="@{Model, converter='org.zkforge.zktodo2.binding.InputEventCommandConverter'}"/>
    </hbox>
    <hbox id="buttons">
         <button id="add" label="Add" width="36px" height="24px" onClick="@{toDoViewModel}"/>
         <button id="update" label="Update" width="46px" height="24px" onClick="@{Model}"/>
         <button id="delete" label="Delete" width="46px" height="24px" onClick="@{toDoViewModel}"/>
    </hbox>
</vbox>
</window>
</zk>
The ZK framework is built upon Java Servlet technology. The ZUL page is parsed to create it a desktop of Java components on the server. This is then rendered as DHTML to the browser. User interactions with the DHTML are fired as AJAX events back to the server. Changes to the desktop made by the Java AJAX event handler code are automatically rendered into the browser. In this manner a Rich Internet Application can be programmed directly with Java logic running on the server.

Near the top of the page the AnnotateDataBinder and CommandBinder page initiators are applied to the screen:
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" ?>
<?init class="org.zkforge.zktodo2.binding.CommandBinderInit"?>
These binders read the declarative databindings syntax "@{binding}" within the page and bind the annotated ZK components onto our Java code. The targets of the bindings is the variable "toDoViewModel". As there is no component within the page with this ID the variable will be resolved to a Spring bean with that name. This was achieved by including the spring variable resolver near the top of the page:
<?variable-resolver class="org.zkoss.zkplus.spring.DelegatingVariableResolver" ?>

Within the spring configuration file spring-context.xml the "toDoViewModel" bean and its dependencies are defined as follow:

<bean id="toDoViewModel" class="org.zkforge.zktodo2.ZkToDoViewModel"
    p:reminderService-ref="reminderService" scope="desktop" />
 
<bean id="reminderService" class="org.zkforge.zktodo2.ReminderService"
    p:basicDao-ref="basicDao" />
 
<bean id="basicDao" class="org.zkforge.zktodo2.BasicDao" />

A key nature of the "toDoViewModel" bean is that it has "desktop" scope. Desktop scope is a custom Spring scope defined by the ZKSpring integration library. This will cause Spring to keep one and only one instance of the bean associated with the users ZK Desktop defined by the ZUL page. The model bean is provided with a service bean "reminderService". The service bean is provided with a data access bean "basicDao". The service bean and data access bean have default scope so they will be singleton objects. Setting the scopes in this manner allows the model bean to be stateful bean servicing a ZK desktop over many AJAX interactions.

Published at DZone with permission of its author, Simon Massey.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Simon Massey replied on Mon, 2011/12/05 - 9:10am

 

ZK MVVM has now been giving a major uplift with the new ZK6 "ZK Bind" features!

Envisage ZK 6: The Next Generation Data Binding System

Hello ZK MVVM

 

Long live the binder! 

Simon

Simon Massey replied on Mon, 2011/12/05 - 9:11am

 

The sample code for this project has now moved to GitHub: 

https://github.com/simbo1905/ZkToDo2

 

 

Simon Massey replied on Tue, 2013/05/14 - 3:19pm

And here is the latest version of the code (using new ZK6 features) running on the Heroku cloud: 

http://glowing-light-1070.herokuapp.com/presentationmodel.zul 

The code will get shutdown if it has no activity for a while. So you have to wait away for the process to startup automatically if you are accessing after it has been shutdown.The warm up takes a while but after that it seem quite lively.

Simon

Rick Reumann replied on Sat, 2012/02/11 - 4:33pm

Just looking for a place to THANK YOU for the great work with https://github.com/simbo1905/ZkToDo2  - It hits the perfect sweet spot for someone wanting to getting into ZK using spring, maven, jpa AND with the new ZK6 binding stuff which is really impressive.

Many sample apps out there either show too much and typically with outdated examples (which ends up just confusing the newbie) or they show too little (making the app not very practical for when you really want to get started building a 'real' app.

Awesome job!

Simon Massey replied on Fri, 2012/07/13 - 12:41am in response to: Rick Reumann

Rick, 

Thanks for your kind words. It is great to hear when someone has found some inspiration in the code. 

Simon

Simon Massey replied on Thu, 2012/12/27 - 1:38pm

The source code from this article is now the subject of a design patterns article covering mvvm, mvc, and mvp patterns called Implementing event-driven GUI patterns using the ZK Java AJAX framework 

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.