ZKTM Small Talks |
ZK with Spring DAO and JDBC Part II |
| Simply Rich | Andrew Ho, Henri Chen Principal Engineer Potix Corporation July 16, 2006 |
org.zkoss package instead of the com.potix
package.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.
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.
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>
<?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>
...
...
<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>
...
...
<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>
...
<?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>
...
...
<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>


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");
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".
