ZK with Spring DAO and JDBC Part II

From Documentation
DocumentationSmall Talks2006JulyZK with Spring DAO and JDBC Part II
ZK with Spring DAO and JDBC Part II

Author
Andrew Ho, Principal Engineer, Potix Corporation
Date
July 16, 2006
Version
Version 2.1.1 or later
(Use the org.zkoss package instead of the com.potix package.)


Access Spring Beans in ZK the easy way

In the previous smalltalk ZK with Spring DAO and JDBC, we have shown you how to use ZK with Spring DAO beans and access persistent data via JDBC sql code. In this article, according to the same sample application, we want to show you how to access a Spring bean object by its id in zscript and EL expression the easy way.

The sample project use the eclipse as programming environment. The Tomcat is the web server. And MySQL is the database system to store data. For details on how to setup these environment, please see "Develop ZK Applications with Eclipse" . If you don't know how to install the spring framework into ZK, you can see the previous smalltalk for details.

The <?variable-resolver?> directive

ZK provides a variable-resolver directive that application developers can specifies the resolver class that will be used by the zscript interpreter to resolve unknown variables. Based on such mechanism, the ZK Team has implemented a variable resolver class that would automatically resolve the Spring bean objects by their ids defined in spring-config.xml . Thus the zul page now can use the Spring beans seamlessly in zscript or EL expression just like using general ZK components.

<?xml version="1.0" encoding="UTF-8"?>
<?page title="Task Lists"?>
<?variable-resolver class="com.potix.zkplus.spring.DelegatingVariableResolver"?>

<window id="taskListWnd" title="Task List" border="normal" width="500px">

    ...
    
</windows>

Note that the DelegatingVariableResolver class is packed inside another jar file zkplus.jar, so you have to copy it to the directory along with other ZK jar files. In our sample code environment, we copied all ZK libraries into $PRJ/WebContent/WEB-INF/lib.


Usage of Spring DAO

We list the oringal taskDAO definition in spring-config.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN/EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
  ...	
  
  <bean id="taskDAO" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    <property name="transactionManager">
      <ref bean="transactionManager"/>
    </property>
    
    <property name="target">
      <ref bean="taskDAOTarget"/>
    </property>
    
    <property name="transactionAttributes">
      <props>
        <prop key="insert*">PROPAGATION_REQUIRED, ISOLATION_READ_COMMITTED</prop>
        <prop key="update*">PROPAGATION_REQUIRED, ISOLATION_READ_COMMITTED</prop>
        <prop key="delete*">PROPAGATION_REQUIRED, ISOLATION_READ_COMMITTED</prop>
        <prop key="find*">PROPAGATION_REQUIRED, ISOLATION_READ_COMMITTED, readOnly</prop>
      </props>
    </property>
  </bean>
</beans>
  • You can use the spring object as a reference variable by its "id" in the zscript directly.
  • From the sample project's taskList.zul
  • When the taskList.zul is first time loaded, all tasks have to be listed in the page through the help of spring DAO. The taskDAO is the spring bean's id and we can use taskDAO.findAll() directly to find all tasks inside zscript. The render(...) function will try to list all founded tasks into the list box.
<?xml version="1.0" encoding="UTF-8"?>
<?page title="Task List"?>
<?variable-resolver class="com.potix.zkplus.spring.DelegatingVariableResolver"?>

<window id="taskListWnd" title="Task List" border="normal" width="500px">
  <attribute name="onCreate"><![CDATA[
	render(taskDAO.findAll());
  ]]></attribute>
...


  • If the user clicked the "New..." button, we popup the task.zul dialog to add a task into database and refresh all tasks.
...
<button label="New...">
  <attribute name="onClick"><![CDATA[
	Window win = (Window)Executions.createComponents("task.zul", null, null);
	win.doModal();
	if (win.getAttribute("OK") != null) 
	  render(taskDAO.findAll());
  ]]></attribute>
</button>
...


  • If the user clicked the "Delete" button, the selected task in the list box is deleted.
...
<button label="Delete">
  <attribute name="onClick"><![CDATA[
	Listitem lt = taskslb.getSelectedItem();
	if (lt == null)
	  return;

	t = lt.getValue();
	taskDAO.delete((com.potix.task.Task)t);
	lt.detach();
  ]]></attribute>
</button>
...


  • The task.zul
  • This task.zul dialog window is shared by "New" and "Edit" modes. We can judge which mode to go by fetching the arg.get("task"). If it's in "Edit" mode, the contents of the selected task will be bound to "title" and "description" textbox components.
<?xml version="1.0" encoding="UTF-8"?>
<?page title="Task"?>
<?variable-resolver class="com.potix.zkplus.spring.DelegatingVariableResolver"?>

<window id="taskWnd" title="Task" border="normal" width="300px">
  <zscript>
	com.potix.task.Task t = (com.potix.task.Task)arg.get("task");
  </zscript>
	
  <vbox>
	<grid>
	  <columns>
		<column width="150px"/>
		<column/>
	  </columns>
	  <rows>
		<row>
		  Title: <textbox id="title" value="${t != null ? t.title : ''}"/>
		</row>
		<row>
		  Description: <textbox id="description" rows="5" cols="25" value="${t != null ? t.description : ''}"/>
		</row>
	  </rows>
	</grid>
  </vbox>
  ...


  • When the "OK" button of the dialog is clicked, again we use the spring bean of the taskDAO to insert or update the task per its mode.
  ...
  <button label="OK">
	<attribute name="onClick"><![CDATA[
	  if (t == null) {
		//new
		t = new com.potix.task.Task();
		
		t.setTitle(title.getValue());
		t.setDescription(description.getValue());
		
		taskDAO.insert(t);
	  } else {
		//update
		t.setTitle(title.getValue());
		t.setDescription(description.getValue());
		
		taskDAO.update(t);
	  }
	  
	  taskWnd.setAttribute("OK", Boolean.TRUE);
	  taskWnd.detach();
	]]></attribute>
  </button>


Sample Project

  • You can download the eclipse project file, task.zip. (If you have the same project name in your eclipse, please delete the existed project first.)
  • Unpack it and open eclipse and do File/Import.../Existing Projects into Workspace.
  • The task's schema is in task/WebContent/task.sql and it's for MySQL database.
  • The taskList.zul will list all tasks and you can new, delete, or edit a task.
  • The task.zul is the dialog that end user can fill up or edit a task.
  • The "taskIncer" bean used MySQLMaxValueIncrementer to generate the primary key value of the "tasks" table.
  • You have to add the sample project, "task", into your "Tomcat v5.5 ..." server instance to test it.

E11.png

E22.png


Notes and Enhancements

The variable resolver is the last one called in a zuml page trying to resolve an unknown variable. Thus, it gets the lowest priority if the id happens to be the same with a zk component. Therefore, be careful about the id duplication issue.

If you want to "locate" a Spring bean that has defined in spring-config.xml via programming, you can still use the ZK's Spring utility class com.potix.zkplus.spring.DelegatingVariableResolver to get it (by bean's id).

	TaskDAO taskDAO = new com.potix.zkplus.spring.DelegatingVariableResolver().getVariable("taskDAO");


Summary

The ZK team has implemented a Spring bean variable resolver which allows accessing spring bean directly in zscript and EL expression. You can also get the Spring bean programmatically by utilizing the DelegatingVariableResolver utility class. To say it in one sentence: "Now you can use Spring beans in ZK seamlessly". Reference

1. Develop ZK Applications with Eclipse

2. ZK with Spring DAO and JDBC

3. ZUML Reference: The variable-resolver Directive

4. You need zk.2.0.0(included).




Copyright © Potix Corporation. This article is licensed under GNU Free Documentation License.