Hamid Fadishei's Blog

March 22, 2012

ZK MVVM Design Pattern and Server-Side Paging

Filed under: Java — fadishei @ 1:34 pm
Tags: , , ,

MVVM (Model/View/ViewModel) is a brilliant variant of the well known MVC (Model/View/Controller) design pattern. ZK has recently added support for this pattern. For an intruduction to MVVM in ZK you may want to see this page.
On the other hand, server-side paging is a technique for showing a huge list of records without fetching and transferring all the data from database to the client. ZK has some good documents and tutorials for implementing this technique using MVC pattern. But so far I could not find any good tutorial for pagination in MVVM projects. Thus I decided to have a short howto for that in my blog. I assume that you are familiar with ZK and Spring framework.
Assume you want to show a list of people in your rich Internet application. The Person POJO is defined as follows:

package ir.fadishei.examples.zk.paging.model;

public class Person
{
	Integer id;
	String firstName;
	String lastName;
	
	// Setters and getters come here
}

The example WITHOUT server-side paging

First, I show how you display the list of people without server-side paging. This will fetch all the records and transfer them to the client which is not a good idea in case of huge lists. I will use my favorite library, myBatis, for mapping between my sqlite person database table and the Person POJO. You may want to use other ones like Hibernate instead.

package ir.fadishei.examples.zk.paging.model;

import java.util.List;
import org.apache.ibatis.annotations.Select;

public interface PersonMapper
{
	@Select("SELECT * FROM person)
	List<Person> getPersons();
}

Now we write a ZUL page for displaying the people list:

<?variable-resolver class="org.zkoss.zkplus.spring.DelegatingVariableResolver"?>
<zk>
<window title="List of people" border="normal" width="600px" apply="org.zkoss.bind.BindComposer" viewModel="@id('vm') @init('ir.fadishei.examples.zk.paging.viewmodel.PersonVM')">
	<vbox hflex="true">
		<listbox model="@bind(vm.persons)" hflex="true" height="200px" mold="paging">
			<listhead>
				<listheader label="Id"/>
				<listheader label="First Name"/>
				<listheader label="Last Name"/>				
			</listhead>
			<template name="model" var="person">
				<listitem >
					<listcell label="@bind(person.id)"/>				
					<listcell label="@bind(person.firstName)"/>
					<listcell label="@bind(person.lastName)"/>
				</listitem>
			</template>
		</listbox>
	</vbox>
</window>
</zk>

Finally, we need the ViewModel for brdging the view to the model:

package ir.fadishei.examples.zk.paging.viewmodel;

import ir.fadishei.examples.zk.paging.model.Person;
import ir.fadishei.examples.zk.paging.model.PersonMapper;
import java.util.List;
import org.zkoss.zk.ui.select.annotation.WireVariable;

public class PersonVM
{
	@WireVariable
	PersonMapper personMapper;

	public List<Person> getPersons()
	{
		return personMapper.getPersons();
	}
}

The example with server-side paging

Now we modify the previous example for making it able to paginate at server side. First of all, we should change the database mapper to be able to fetch a specific page from person table. It should also have a method that returns the total number of records. This is required to find out the total number of pages displayed in the view:

package ir.fadishei.examples.zk.paging.model;

import java.util.List;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

public interface PersonMapper
{
	@Select("SELECT * FROM person limit #{limit} offset #{offset}")
	List<Person> getPersonPage(@Param("offset") Integer offset, @Param("limit") Integer limit);

	@Select("SELECT COUNT(*) FROM person")
	Integer getPersonCount();
}

Next, we modify the view and remove the paging capability from the listbox. instead, we add a separate paging component:

<?variable-resolver class="org.zkoss.zkplus.spring.DelegatingVariableResolver"?>
<zk>
<window title="List of people" border="normal" width="600px" apply="org.zkoss.bind.BindComposer" viewModel="@id('vm') @init('ir.fadishei.examples.zk.paging.viewmodel.PersonVM')">
	<vbox hflex="true">
		<paging pageSize="@load(vm.pageSize)" totalSize="@load(vm.totalSize)" activePage="@save(vm.activePage)"/>
		<listbox model="@bind(vm.persons)" hflex="true" height="200px">
			<listhead>
				<listheader label="Id"/>
				<listheader label="First Name"/>
				<listheader label="Last Name"/>				
			</listhead>
			<template name="model" var="person">
				<listitem >
					<listcell label="@bind(person.id)"/>				
					<listcell label="@bind(person.firstName)"/>
					<listcell label="@bind(person.lastName)"/>
				</listitem>
			</template>
		</listbox>
	</vbox>
</window>
</zk>

Our ViewModel should get activePage from view and give pageSize, totalSize, and active page contents to the view:

package ir.fadishei.examples.zk.paging.viewmodel;

import ir.fadishei.examples.zk.paging.model.Person;
import ir.fadishei.examples.zk.paging.model.PersonMapper;
import java.util.List;
import org.zkoss.bind.annotation.NotifyChange;
import org.zkoss.zk.ui.select.annotation.WireVariable;

public class PersonVM
{
	int pageSize = 10;
	int activePage = 0;
	@WireVariable
	PersonMapper personMapper;
	
	public int getTotalSize()
	{
		return personMapper.getPersonCount();
	}
	
	public Integer getPageSize()
	{
		return pageSize;
	}

	@NotifyChange("persons")
	public void setActivePage(int activePage)
	{
		this.activePage = activePage;
	}

	public List<Person> getPersons()
	{
		return personMapper.getPersonPage(activePage*pageSize, pageSize);
	}
}

Alternatively, you could handle onPaging event of the paging component instead of binding its activePage to the ViewModel. But I think this would be a little messier!

June 27, 2010

AGI Gosub Command Support in Asterisk-Java

Filed under: Asterisk,Java — fadishei @ 4:36 am

Today, I had my first experience of contributing to an open-source project. The story is that a few weeks ago when I needed to execute an AGI Gosub command, I found out this command is not implemented in Asterisk-Java yet. Thus I decided to do some coding myself. I sent the result to the project’s JIRA by opening a new feature issue. Kindly, Stefan Reuter (funder of Asterisk-Java) appreciated the work and helped me to improve it. Finally, the new Gosub command added to the SVN and will be available in the 1.0.0 release.

The Gosub Command

This command has been added to Asterisk since 1.6 version. It lets you to call a subroutine in your dialplan from AGI script. You can also pass some optional arguments to the subroutine. Although an AGI developer may find this feature useful in several situations, personally I most benefit from gosub command in indirectly calling applications for whom no dedicated AGI command is available. An example is doing a “Queue” application as exec(“Queue”, …) may not give you all the expected behavior.

As an example of using this command, consider that you have this simple subroutine in your dialplan:

[inside]
exten => 190,1,AGI(agi://localhost/gosub.agi)

[sub-hello]
exten => s,1,NoOp(arg1: ${ARG1})
exten => s,n,NoOp(arg2: ${ARG2})
exten => s,n,Playback(hello-world)
exten => s,n,Return()

Then you can call this subroutine like this:

public class TestGosub extends BaseAgiScript
{
        public void service(AgiRequest request, AgiChannel channel) throws AgiException
        {
                answer();
                streamFile("silence/1");
                gosub("sub-hello", "s", "1", "a", "b");
                hangup();
        }
}

As it can be seen in the code, the first three arguments to the gosub method are the context, extension, and priority you want to call. The rest of parameters are optional arguments that will be available in the subroutine as variables ${ARG1}, ${ARG2}, etc.

Some Introductory Information

For people who are not familiar with Asterisk, I would like to add the following paragraphs.

Aboute Asterisk

Asterisk is an open-source software-based PBX system that lets you do telecommunications works on a Linux box. You can build auto-attendants, call centers, help desks, IVRs, VoIP providers etc with Asterisk.

About AGI

As a programmer, you can command at your will to an Asterisk box what to do. This feature is available through a standard language for talking between Asterisk and your program known as Asterisk Gateway Interface (AGI). This feature, along with another similar functionality known as Asterisk Manager Interface (AMI) makes a software developer capable of implementing almost any imaginable telecommunications application. An example application is one that reads out your new emails to you when you call it. Another application can be an IVR that dynamically adjusts its menu items based on user requirements.

About Asterisk-Java

Asterisk-Java is a library for doing AGI from Java programs. Personally, I think Asterisk-Java turns telecommunications application development into fun!

January 5, 2010

Spring Load-time Weaving on Tomcat: Does It Really Work?

Filed under: Java,Spring,Tomcat — fadishei @ 5:44 am

Are you frustrated in making the Spring load-time weaving (LTW) work on Tomcat application server? Then keep reading as the process is explained below.

Inversion of Control

Spring is an “Inversion of Control” (IoC) container. IoC lets the developers of a class (bean) relax from thinking how to satisfy the dependencies for the class. Dependencies will be “injected” into the bean by the container.  For example, a bean may need to be a client of a web service. Then the developer does not have to think about how to get the stub for the web service. The only thing he has to do is to provide a means to get the dependency from the container, for example by providing the container with a property setter for the stub, and take it for granted. More information about IoC and DI can be found here.

Load-Time Weaving

Sometimes, your beans are created outside of the container. Then, the framework can not simply inject their dependencies. One solution is to get the dependencies yourself by making your bean “application-context-aware”. However, this will result in foregoing the IoC. Another solution is to make your bean @Configurable and use weaving to inject the dependencies at load-time, or at compile-time. More information on LTW in Spring can be found here.

The Environment

Spring framework has recently released the stable 3.0 version. I use this version in this tutorial, along with Tomcat 6.0 as the applications server. The source code as an Eclipse project can be found here. This is a very simple web application which will say hello to a name that is specified as a bean property in the spring context. The property will be injected using load-time weaving.

Step 1- Project Dependencies

The needed libraries for running the example:

aspectjweaver-1.6.7.jar
commons-logging-1.1.1.jar
log4j-1.2.15.jar
spring-asm-3.0.0.jar
spring-aspects-3.0.0.jar
spring-beans-3.0.0.jar
spring-context-3.0.0.jar
spring-core-3.0.0.jar
spring-expression-3.0.0.jar
spring-transaction-3.0.0.jar
spring-web-3.0.0.jar

Step 2- Make the Bean Configurable

This code shows how I made my ultra-simple Person bean configurable:

package ir.fadishei.test.ltw;

import org.springframework.beans.factory.annotation.Configurable;

@Configurable
public class Person
{
	private String name;

	public String getName()
	{
		return name;
	}

	public void setName(String name)
	{
		this.name = name;
	}

	public String toString()
	{
		return name;
	}
}

Step 3- The Spring Context

Here is the simplistic configuration:

<beans
	xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="
		http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/aop
		http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
		http://www.springframework.org/schema/context
		http://www.springframework.org/schema/context/spring-context.xsd">

	<context:spring-configured />
	<context:load-time-weaver aspectj-weaving="autodetect"/>

	<bean class="ir.fadishei.test.ltw.Person" scope="prototype">
		<property name="name" value="Timon"/>
	</bean>

</beans>

Step 4- Change the Tomcat Class Loader

Somtimes people fail to make LTW work on Tomcat by missing this step. The default Tomcat class loader does not support class transformation. You’ll need to use the one provided by Spring. First you should copy the spring.instrument.tomcat-3.0.0.jar to the lib folder of your tomcat installation. then use this context.xml to tell the web application server to use the new class loader:

<Context path="/ltwdemo">
    <Loader loaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader"/>
</Context>

Step 5- Run

Run the web server and browse the following page. You should see the Hello <name>! message, in which name should be what provided in the bean definition.

http://localhost:8080/ltwdemo/

The source code of this tutorial as an Eclipse project

Blog at WordPress.com.