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

Using Desktop MVC Patterns with ZK, Spring & JPA

03.12.2009
| 42689 views |
  • submit to reddit

The Application Layering

The layering of the UI controller bean, application model bean, service bean and data access bean is defined within the Spring configuration file as follows:

    <bean id="basicDao" class="org.zkforge.zktodo2.BasicDao" />

<bean id="reminderService" class="org.zkforge.zktodo2.ReminderService"
p:basicDao-ref="basicDao"
/>

<bean id="toDoModel" class="org.zkforge.zktodo2.ZkToDoModelImpl"
p:reminderService-ref="reminderService" scope="session"/>

<bean id="toDoControllerV2" class="org.zkforge.zktodo2.ZkToDoControllerV2"
p:toDoModel-ref="toDoModel" scope="prototype"
/>

The controller is provided with a model bean. The model bean is provided with a service bean. The service bean is provided with a data access bean. The service bean and data access bean have default scope so they will be singleton objects. The model bean has session scope. This will cause Spring to keep one and only one instance of the bean associated with the users HTTP session. The controller bean has prototype scope. This causes a new bean to be instantiated for each page that is rendered. Setting the scopes in this manner allows the model bean and the controller beans to be stateful. The control beans state is related to the Java Desktop defined within the page. The model beans state is related to the users web session and may be shared across many screen controllers in a large application.

The ZkToDo2 sample application is very small with only one bean in each layer and a 1-to-1 relationship between each layer. Within a larger application there would be multiple beans in each layer across the width of a complex application. The layering then allows for 1-to-many, many-to-1 and many-to-many configurations to encourage maximum code re-use and a clear separation of responsibility between classes and layers of the application.

The Controller Class

The above ZUML screen file defines an inert page with no application behaviours. Behaviour is to be provided by our controller class. The window tag has an "apply" attribute set to "${toDoControllerV2}". This requests that the ZK framework pre-processes the Java Window object of the Java Desktop with the object referenced by the variable toDoControllerV2. The Spring variable resolver has been included near the top of the page. The introduction of the Spring variable resolver gives a complete integration with the spring framework. All we need to do is define beans within Spring's configuration and we can reference beans by name within our ZUML screen file. The toDoControllerV1 bean is defined by this entry within the file spring-config.xml:

<bean id="toDoControllerV2" class="org.zkforge.zktodo2.ZkToDoControllerV2" 
p:toDoModel-ref="toDoModel" scope="prototype"/>

The class of the toDoControllerV2 bean is ZKToDoControllerV2. The scope of the bean is "prototype". This means that Spring will instantiate a new bean each and every time ZK asks for a bean of that name. This occurs each time the ZUML page is loaded. The controller configuration specifies that it requires a bean named "toDoModel". The bean "toDoModel" is also referenced within the ZUML file. Here is an extract of the controller class:

public class ZkToDoControllerV2 extends GenericForwardComposer {

protected Textbox name;
protected Intbox priority;
protected Datebox date;
protected Listbox list;
protected ListModelList listModelList;

public void onClick$add(org.zkoss.zk.ui.event.Event e) {
// ...
}
public void onClick$update(org.zkoss.zk.ui.event.Event e) {
// ...
}

public void onClick$delete(org.zkoss.zk.ui.event.Event e) {
// ...
}
}

ZkToDoControllerV2 subclasses GenericForwardComposer. GenericForwardComposer is an optional ZK support class explicitly designed to support the MVC pattern. Code within the GenericForwardComposer class will automatically wire our ZkToDoControllerV2 controller object to the user interface components defined within the ZUML file. The autowiring is done via ZK matching the names and types within our Java class to the XML elements and IDs defined within our ZUL file.

If we compare the Java and ZUML listings above we find matches for "name", "priority", "data" and "list". In addition the types within the Java code match the Components defined within the ZUL file. ZK will inject references to the named screen Components into our controller class. The Java listing also defines three event handlers. The signatures of the event handlers are similar to the standard ZK "onClick" event handler. The method names start with "onClick" and end with the ID of a button defined within the ZUL file. ZK will bind the three controller methods as event handlers on the corresponding button components. Without any JavaScript AJAX programming when the user clicks on the buttons of our user interface our pure Java code will run on the server.

The Service & Data Layers

Here is an extract of the ReminderService class:

public class ReminderService {

@Transactional(readOnly=true)
public List findAll(){
List events = this.basicDao.findAll(Reminder.class);
return(List) events;
}

@Transactional(readOnly=false,propagation = Propagation.REQUIRED)
public void persistEvent(Reminder reminder){
this.basicDao.persist(reminder);
}

@Transactional(readOnly=false,propagation = Propagation.REQUIRED)
public void deleteEvent(Reminder reminder) throws EntityNotFoundException {
this.basicDao.remove(Reminder.class, reminder.getId());
}

@Transactional(readOnly=false,propagation = Propagation.REQUIRED)
public void mergeEvent(Reminder reminder) throws EntityNotFoundException {
this.basicDao.merge(reminder);
}
}

The reminderService has Spring transaction annotations to define the transactional semantics of the business logic. The sample application is very simple and does not define many database operations within each service method. In a larger system that must perform a set of data operations in an atomic manner the use of transactions would be of greater importance to ensure data integrity. The transaction annotations are activated by a single line in the spring-config.xml file:

<tx:annotation-driven />

This tx annotation tag does not name a specific transaction manager to use. So by convention Spring will use a bean called transactionManager to honour the transaction annotations of the service bean. We may wish to change the transaction manager and data source between running JUnit tests within an IDE and deployment to an application server. So these beans are separated out into a file called dataSourceContext.xml.

The final part of the spring configuration is the JPA EntityManagerFactory:

<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
p:persistence-xml-location="classpath:META-INF/persistence.xml"
p:data-source-ref="dataSource"
>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
p:showSql="true"
p:generateDdl="true">
</bean>
</property>
<property name="jpaProperties">
<value>
hibernate.ejb.naming_strategy=org.hibernate.cfg.ImprovedNamingStrategy
hibernate.dialect=
hibernate.hbm2ddl.auto=
</value>
</property>
</bean>

<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

The configuration defines a Hibernate JPA EntityManagerFactory that uses our dataSource bean defined within dataSourceContext.xml. The use of PersistenceAnnotationBeanPostProcessor provides the glue between our JPA entity manager and our BasicDao bean.

The BasicDao class has been taken from the Loom framework source code along with the Spring+JPA configuration outlined above. The pagination support of the class has been removed as it was not required for this sample application. It is recommended that readers study the original Loom class and surrounding packages which provide richer behaviour than was needed to implement zktodo2.

The Model Classes

The model class encapsulates the state and behaviour of the business layers of the system. The model class is stateful in nature and can be reused amongst multiple screen and multiple controllers within a larger application. The model class utilizes the service layer of the application to sync its state with the database.

An explicit model interface for the sample application is here with the implementation here. The interface is shown below:

package org.zkforge.zktodo2;

import java.util.List;

public interface ZkToDoModel {

public abstract void deleteEvent(Reminder reminder)
throws EntityNotFoundException;

public abstract List findAll();

public abstract void mergeEvent(Reminder reminder)
throws EntityNotFoundException;

public abstract void persistEvent(Reminder reminder);

//used by selectedItem="@{controller.selectedReminder}" and others
public abstract Reminder getSelectedReminder();

//used by selectedItem="@{controller.selectedReminder}" and others
public abstract void setSelectedReminder(Reminder reminder);

//used by model="@{controller.reminders}"
public abstract List getReminders();

}

Notice that the Model class holds the "selected reminder" which is the reminder that the current user is editing.

ZK Databindings

Databindings are declarative bindings. Within the application the JPA Annotations provide a declarative binding between our POJOs and the database tables. The ZK databindings feature provides declarative bindings between POJOs and UI Components. An extract highlighting the databindings within the ZUML screen file is shown here:

...
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" ?>
<?variable-resolver class="org.zkoss.zkplus.spring.DelegatingVariableResolver"?>
...
<listbox id="list" multiple="true" rows="4" model="@{toDoModel.reminders}" selectedItem="@{toDoModel.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>
...
Item:<textbox id="name" cols="40" constraint="no empty" value="@{toDoModel.selectedReminder.name}"/>
Priority:<intbox id="priority" cols="1" constraint="no empty" value="@{toDoModel.selectedReminder.priority}"/>
Date:<datebox id="date" cols="14" constraint="no empty" value="@{toDoModel.selectedReminder.date}"/>

In the listing above the page has an "init" instruction referencing the AnnotateDataBinderInit class. Preprocessing the page with AnnotateDataBinderInit causes the zul properties containing "@{binding}" declarative bindings to be bound onto the application POJOs. Collectively the databindings show how to render the initial state of the screen and how to write UI input from the edit area into the selected POJO.

The databindings for the Listbox initially reads from "@{toDoModel.reminders}" and writes to "@{toDoModel.selectedReminder}" when an item is selected from the list by the user. The variables are resolved to our Spring bean via the Spring variable resolver. ZK reflects on the class of the model bean and maps the bindings onto the methods "toDoModel.getReminders()" and "toDoModel.setSelectedReminder(...)" methods.

Within the Listbox there are bindings which define how to render each Reminder object into a set of Listcells within a Listitem. The self="@{each=reminder}" binding sets up a loop variable "reminder" that is set for each reminder within the list loaded from the database. For each reminder object in the list a new Listitem is instantiated. The bindings such as "@{reminder.name}" applied to the Listcells map the getters of the reminder object onto the setters on the Listcell objects.

Below the Listbox the selected reminder is rendered into the edit area using bindings such as "@{toDoModel.selectedReminder.name}". ZK resolves this to the "getName()" method of the selected reminder object.

Putting It All Together

The effect of the databindings is that when you load the page ZK will call the model bean method to load the reminders from the database and will then render them into the list. When the user clicks on a reminder within the list its data appears within the edit area. No bespoke code is required to do this as ZK does it automatically as directed by the databindings. If you edit the name of the reminder in the edit area, then tab away, the name of the reminder shown within the list changes. This is because both the listcell and edit area is bound to the POJO so ZK keeps all three in synch. ZK knows that the POJO name has changed so it will automatically update the ListCell at the same time as it updates the POJO. Once again no bespoke code has been written to achieve this effect.

It is also important to know that the Java POJO on the server has been updated. There is no "web page post" when writing user interfaces with ZK. The ZK framework has fired AJAX events asynchronously to the server and has called the setters on our Java objects without having to write a single line of Javascript or Java. ZK gives us the illusion that our Java desktop and application Java objects are being rendered directly into the browser window without any Servlet or DHTML programming. In reality ZK is implemented as a set of pure Servlets and a JavaScript library. The ZK developers have done all of the Servlet and DHTML programming to give us a pure Java Desktop programming environment that is "painted" into a browser window without any browser plug-ins.

When you click the Update button ZK will run the Java method of the controller class that it has automatically bound to the event handler of the button. The POJO is already on the server and has already been updated by ZK via AJAX when the user has input data into the edit area. There is no need to write any boiler-plate code to copy the strings out of a web-request and call setters on our POJO. As the POJO is already fully up to date we simply have to add code into the Java event handler of the controller to flush the modified POJO to the database. Here is the controller event handler method that is called when we click the Update button:

	public void onClick$update(Event e) {
Reminder selectedReminder = this.toDoModel.getSelectedReminder();
if( selectedReminder != null ){
ListModelList listModelList = (ListModelList)this.list.getModel();
try {
this.toDoModel.mergeEvent(selectedReminder);
} catch (EntityNotFoundException exception){
int index = list.getSelectedIndex();
listModelList.remove(index);
alert("Reminder "+selectedReminder.getName()+" has been deleted by another user.");
if( listModelList.size() > 0 ){
selectedReminder = (Reminder)listModelList.get(0);
list.setSelectedIndex(0);
name.setValue(selectedReminder.getName());
date.setValue(selectedReminder.getDate());
priority.setValue(selectedReminder.getPriority());
} else {
selectedReminder = null;
}
}
List reminders = toDoModel.findAll();
listModelList.clear();
listModelList.addAll(reminders);
}
}

The majority of the code of that method is dealing with the exceptional case of discovering that the reminder has been deleted from the database by another user. The actual bespoke code to take the user input and call our back-end Java business logic to persist the input to the database can be simplified down to a single line of code:

this.toDoModel.mergeEvent(this.toDoModel.getSelectedReminder());

As all of the DHTML and Servlet programming has been handled by the ZK framework and our databindings mark-up we are free to focus on what is unique to our application. The source code of the project contains no bespoke Servlet or DHTML code only pure Java business logic. The Update logic above is within our prototype scoped controller bean which Spring instantiated and injected with a model bean. ZK injected references to the Java desktop Components defined within the ZUML page. ZK also bound the Java event handlers of the Components within the Java desktop to the event handlers defined within our controller bean. The model bean was given session scope so it is bound to the HTTPSession. Spring injected into the model bean a service bean. The service bean was given transactional annotations such that Spring will roll-back any database changes if an exception is thrown within the service call. Spring injected the data access bean into the service bean and configured the data access bean with a JPA entity manager.

Summary

In this article we introduced the ZkToDo2 sample application. The application makes use of the ZK support class GenericForwardComposer which provides explicit support for the Model-View-Controller pattern. The user interface defined in the ZUL file was wired to the controller class of the application automatically by matching elements and IDs within the ZUL file to member variable names and types within the controller class.

Integration with the Spring framework was demonstrated using the ZK support class DelegatingVariableResolver. Spring was used to create application layering through configuration using its support for the Inversion-Of-Control pattern. Logical layers for the UI controller bean, an application model bean, a singleton service bean and a singleton data access bean were configured via Spring. These layers provide a clear separation of concerns between the classes of the application. Spring support for transaction management was used to configure the database transaction boundaries of the service bean. Spring support for JPA was used to connect an EntityManager to the data access bean that was injected into the service bean.

The ZkToDo2 sample application uses an explicit Model class and ZK databindings. The introduction of an explicit model class provides for better encapsulation of the application business logic to facilitate code re-use between controllers. The introduction of ZK databindings removed much of the boiler-plate code required to initialize the UI and update application POJOs with user input.

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

zodix Moore replied on Thu, 2009/03/12 - 6:46am

Wow, really impressed how little programming is required!

ZK is the best Ajax framework I eve used. It re-defines the ease of use and the integration of Java!

Simon Massey replied on Thu, 2009/03/12 - 6:21pm

 

ZK was SourceForge project of the month for Feb 2009 with a write up here

rgds

Simon

 

David H. Ruwet replied on Thu, 2009/03/12 - 9:56pm

Great! it's an elegant way to realize MVC pattern. applaud for ZK framework.

Marcos de Sousa replied on Fri, 2009/03/13 - 8:26am

Massey,

Always doing great posts.

To those who use Java 5, your code really is very good.

But, it is always good show load on demand (sql paging) for performance purpose.

Now i am waiting for another great post from you.

Congratulation,

 

Simon Massey replied on Tue, 2009/03/17 - 12:24pm

Here is a link to a flash recording of the databinding working: http://screencast.com/t/K32n6eYk

Sandeep Musale replied on Tue, 2009/08/11 - 6:42am in response to: jame jack

Simon, ZK looks pretty good.... with a little programming ... Thanks for the post with right example... Cheers !!!

Comment viewing options

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