Integrating ZK and Spring Web Flow

Henri Chen, Principal Engineer, Potix Corporation
December 3, 2008

Introduction

This is the third article in a series regarding how to make Spring work with ZK Ajax framework. In the previous articles, this and this, we have discussed about how to secure ZK pages, ZK events, and Spring backend service methods using ZK and Spring Security 2.0 frameworks. In this article, we will demonstrate with an example the way to navigate a work flow with ZK, Spring Security, Spring MVC, and Spring Web Flow.

Spring Web Flow is the module of Spring for implementing flows. Basically, you define your Web page flows with a provided declarative flow definition language in XML configuration files. Then, per the definitions, Spring Web Flow engine transits the pages per the current page and user's action(e.g. when user press the next button). This article focus on illustrating the steps and ways how to configure the Web application and how to design the ZK pages such that ZK and Spring Web Flow work together seamlessly.

Demo

 

The Example

Same as in the previous articles, I borrowed the booking-faces sample(spring-webflow-2.0.3.RELEASE/projects/spring-webflow-samples/booking-faces/) provided by Spring Web Flow 2.0.3. It is a simple hotel searching and booking application. End users search hotels, pick one, and then book the hotel per the pre-defined work flow. The sample was implemented with JSF pages and I rewrote each JSF .xhtml page to a corresponding ZK .zul page and add necessary ZK libraries and configurations to make it work.

Deploy the war file

Download the zkspringwf.war file and deploy the war file to your servlet container. If you are using Tomcat 6.0, all you have to do is copy the war file to the webapps folder of the Tomcat server and then restart Tomcat. The zkspringwf.war war file shall deploy and create a new folder named zkspringwf (same name as the file) under the webapps. Now visit http://localhost:8080/zkspringwf/ and you shall see following page:

Configurations

Now lets start walking through the configurations:

/WEB-INF/zk.xml file: the ThreadLocal issue (IMPORTANT!)

The Spring Web Flow engine holds in the servlet thread serveral ThreadLocal variables for each request so the engine can refer it from time to time. These ThreadLocal variables contains important work flow related information and shall be accessiable any time. However, ZK by default spawns a new event thread for each event handling job. That is, the ZK event thread will not have such important ThreadLocal variables and the original assumption is broken.

Therefore, remember always to disable the ZK event thread mechanism entirly when use ZK with Spring. This tells the ZK framework NOT to spawn a new event thread for event handling and everyting shall back to it track. That is, configure the /WEB-INF/zk.xml file as follows:


<zk>
    ...
    <system-config>
        <disable-event-thread/>
    </system-config>
    ...
</zk>

/WEB-INF/web.xml

web.xml is the standard servlet configuration file. To make ZK and Spring works, you have to configure this file.


/WEB-INF/web.xml
<web-app ...>
    ...
    <!-- 
      - Spring configurations 
      -->
    <!-- The master configuration file -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/config/web-application-config.xml
        </param-value>
    </context-param>
    
    <!-- Enables Spring Security -->
     <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
      <filter-name>springSecurityFilterChain</filter-name>
      <url-pattern>/*</url-pattern>
    </filter-mapping>
    
    <!-- Loads the Spring web application context -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

      <!-- Serves static resource content from .jar files -->
    <servlet>
        <servlet-name>Resources Servlet</servlet-name>
        <servlet-class>org.springframework.js.resource.ResourceServlet</servlet-class>
        <load-on-startup>0</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Resources Servlet</servlet-name>
        <url-pattern>/resources/*</url-pattern>
    </servlet-mapping>
    
    <!-- The front controller of this Spring Web application, responsible for handling all application requests -->
    <servlet>
        <servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value></param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
        <url-pattern>/spring/*</url-pattern>
    </servlet-mapping>

    <!-- 
      - ZK configurations 
      -->
    <listener>
        <description>
        Used to cleanup when a session is destroyed</description>
        <display-name>
        ZK Session Cleaner</display-name>
        <listener-class>org.zkoss.zk.ui.http.HttpSessionListener</listener-class>
    </listener>

    <!-- ZK loder -->    
    <servlet>
        <description>
        ZK loader for ZUML pages</description>
        <servlet-name>zkLoader</servlet-name>
        <servlet-class>org.zkoss.zk.ui.http.DHtmlLayoutServlet</servlet-class>
        <init-param>
            <param-name>update-uri</param-name>
            <param-value>/zkau</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>zkLoader</servlet-name>
        <url-pattern>*.zul</url-pattern>
    </servlet-mapping>
    
    <!-- ZK update engine -->    
    <servlet>
        <description>
        The asynchronous update engine for ZK</description>
        <servlet-name>auEngine</servlet-name>
        <servlet-class>org.zkoss.zk.au.http.DHtmlUpdateServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>auEngine</servlet-name>
        <url-pattern>/zkau/*</url-pattern>
    </servlet-mapping>

    <!-- Default welcome files -->
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
    </welcome-file-list>
</web-app>
  • Spring configuration:
    1. The <context-param> tells Spring Framework context loader where to find the context parameter files.
    2. The <listener> ContextLoaderListener defines the Spring Framework context loader that will load and parse the context parameter files.
    3. The <filter> springSecurityFilterChain defines the entry servlet filter for Spring Secuirty filter chains.
    4. The <servlet> Resources Servlet defines the spring resource servlet which can be used to retrieve resource defined in library .jar files.
    5. The <servlet> Spring MVC Dispatcher Servlet defines the entry servlet for Spring Web Flow. Any URL starts with /spring/* will go through the Spring Web Flow controller

    The most important configuration might be the Spring MVC Dispatcher Servlet. It tell the servlet container that all URL that starts with /spring/* shall be served by this servlet. It is a dispatcher servlet so we will need extra configurations for Spring MVC and Spring Web Flow to bridge the work flow requests to real Spring Web Flow controller.

  • ZK Ajax framework configuration:
    1. The <listener> HttpSessionListener is used to cleanup the session when it is destroyed.
    2. The <servlet> zkLoader servlet is used to load a ZK page
    3. The <servlet> auEngine servlet is used to update a ZK page (Ajax update)

    This is a typical ZK application configuration. Nothing very special.

/WEB-INF/config/webmvc-config.xml

webmvc-config.xml is the additional configuration file specific to Spring MVC.


/WEB-INF/config/webmvc-config.xml
<beans ...>
    <!-- Maps request URIs to controllers -->            
    <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <value>
                /main=flowController
                /booking=flowController
            </value>
        </property>
        <property name="defaultHandler">
            <!-- Selects view names to render based on the request URI: e.g. /main selects "main" -->    
            <bean class="org.springframework.web.servlet.mvc.UrlFilenameViewController" />
        </property>
    </bean>

    <!-- Maps logical view names to real page URL (e.g. 'search' to '/WEB-INF/search.zul' -->
    <bean id="viewResolver" class="org.zkoss.spring.web.servlet.view.ZkResourceViewResolver">
        <property name="prefix" value="/WEB-INF/"/>
        <property name="suffix" value=".zul"/>
    </bean>
</beans>
  1. The <bean> SimpleUrlHandlerMapping works with Spring MVC will maps the request URI to real Controller. Here all the request URIs in the pattern /main and /booking would be dispatched to flowController(which is defined in webflow-config.xml configuration file. We will discuss it later).
  2. The <bean> viewResolver maps the logical view name returned by controller to real page URL. Note here the name viewResolver has to be given as is.

/WEB-INF/config/webflow-config.xml

webflow-config.xml is the configuration file specific to Spring Web Flow.


/WEB-INF/config/webflow-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:webflow="http://www.springframework.org/schema/webflow-config"
    xmlns:zksp="http://www.zkoss.org/2008/zkspring"
    xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
       http://www.springframework.org/schema/webflow-config
       http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.0.xsd
       http://www.zkoss.org/2008/zkspring
       http://www.zkoss.org/2008/zkspring/zkspring.xsd">

    <!-- Executes flows: the central entry point into the Spring Web Flow system -->
    <webflow:flow-executor id="flowExecutor">
        <webflow:flow-execution-listeners>
            <webflow:listener ref="jpaFlowExecutionListener" />
            <webflow:listener ref="securityFlowExecutionListener" />
        </webflow:flow-execution-listeners>
    </webflow:flow-executor>
    <!-- Installs a listener that manages JPA persistence contexts for flows that require them -->
    <bean id="jpaFlowExecutionListener"
        class="org.springframework.webflow.persistence.JpaFlowExecutionListener">
        <constructor-arg ref="entityManagerFactory" />
        <constructor-arg ref="transactionManager" />
    </bean>
    <!-- Installs a listener to apply Spring Security authorities -->
    <bean id="securityFlowExecutionListener"
        class="org.springframework.webflow.security.SecurityFlowExecutionListener" />

    <!-- The registry of executable flow definitions -->
    <webflow:flow-registry id="flowRegistry"
        flow-builder-services="zkFlowBuilderServices">
        <webflow:flow-location path="/WEB-INF/flows/main/main.xml" />
        <webflow:flow-location path="/WEB-INF/flows/booking/booking.xml" />
    </webflow:flow-registry>

        
    <!-- Configures the ZK Spring Web Flow integration -->
    <zksp:flow-controller id="flowController" flow-executor="flowExecutor"/>
    <zksp:flow-builder-services id="zkFlowBuilderServices" />
</beans>
  • Spring <webflow:> configuration(in red):
    1. The flowExecutor bean is the central entry point into the Spring Web Flow system. It adds two work flow listeners to handle the JPA data persistence and web flow security protection.
    2. The flowRegistry bean is the registry of work flow definitions. It tells the Spring Web Flow system where to find the flow definition file. Also, it specifies which flow-builder-service to use for these work flow definitions. Note here it uses zkFlowBuilderServices.
  • ZK Spring <zksp:> configuration(in blue):
    1. The flowController bean is the bridge between Spring MVC and ZK Spring Web Flow (flowExecutor). Note the name flowController has to be given as is.
    2. The zkFlowBuilderServices bean is where those real web flow services are (expression parsing, view resolving, type conversion, etc.)

    ZK adopts the Spring namespace configuration mechanism so all you need to do to enable the ZK Spring Web Flow Integration is by specifying these two beans.

Define a work flow

After finishing application configuration, it is time to define the work flow.


/WEB-INF/flows/main/main.xml
<flow xmlns="http://www.springframework.org/schema/webflow"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/webflow
    http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">
    
    <var name="searchCriteria" class="org.springframework.webflow.samples.booking.SearchCriteria" />
    
    <view-state id="enterSearchCriteria">
        <on-render>
            <evaluate expression="bookingService.findBookings(currentUser.name)" result="viewScope.bookings" />
        </on-render>
        <transition on="search" to="reviewHotels">
            <evaluate expression="searchCriteria.resetPage()" />
        </transition>
        <transition on="cancelBooking">
            <evaluate expression="bookingService.cancelBooking(componentScope.booking)" />
            <render fragments="bookingsFragment" />
        </transition>
    </view-state>
    
    <view-state id="reviewHotels">
        <on-render>
            <evaluate expression="bookingService.findHotels(searchCriteria)" result="viewScope.hotels" />
        </on-render>
        <transition on="sort">
            <set name="searchCriteria.sortBy" value="requestParameters.sortBy" />
            <render fragments="searchResultsFragment" />
        </transition>
        <transition on="previous">
            <evaluate expression="searchCriteria.previousPage()" />
            <render fragments="searchResultsFragment" />
        </transition>
        <transition on="next">
            <evaluate expression="searchCriteria.nextPage()" />
            <render fragments="searchResultsFragment" />
        </transition>
        <transition on="select" to="reviewHotel">
            <set name="flowScope.hotel" value="self.attributes.hotel" />
        </transition>
        <transition on="changeSearch" to="changeSearchCriteria" />
    </view-state>
    
    <view-state id="reviewHotel">
        <transition on="book" to="bookHotel" />
        <transition on="cancel" to="enterSearchCriteria" />
    </view-state>

    <subflow-state id="bookHotel" subflow="booking">
        <input name="hotelId" value="hotel.id" />
        <transition on="bookingConfirmed" to="finish" />
        <transition on="bookingCancelled" to="enterSearchCriteria" />
    </subflow-state>

    <view-state id="changeSearchCriteria" view="enterSearchCriteria" popup="true">
        <on-entry>
            <render fragments="hotelSearchFragment" />
        </on-entry>
        <transition on="search" to="reviewHotels">
            <evaluate expression="searchCriteria.resetPage()"/>
        </transition>
    </view-state>
            
    <end-state id="finish" />
    
</flow>

A work flow is defined in a separate XML configuration file. A work flow basically is composed of states. Inside each state, we can defined transition to tell the flow engine which state to go on some predefined action event. Also, you can do some evaluate in the life cycle of the work flow. However, I am not going to explain every tag used in this work flow definition file. I will focus on those tags that related to the mapping web pages. If you need to know more details, you can download the spring-webflow-reference.pdf from the Spring website.

  • <view-state>: define the view state. Each view-state is mapped to a real web page. The view resolver configured in zkFlowBuilderServices bean(configured in webflow-config.xml) is used to resolve the view-state id into a Spring MVC view name
  • <transition>: define the transition condition. The attribute on="action-event" tells when to trigger a flow transition, and the optional attribute to="target-state" tells which target state to go when the specified transition action event is fired. If attribute to is omitted, flow engine will keep in this state. In such case, there shall be generally at least an <evaluate> tag is specified. As for how to fire a transition action event in the zul page, I will explain later with an example zul page.
  • <evaluate:>: define the evaluation expression. Each <evaluate> tag request to evaluate the specified expression as defined in attribute expression. These expression can be evaluated as the Unified Epression Language(EL). Note that you can use all ZK implicit objects and accessible variables here including self, event, desktop, page, and so on. That is, you can write ZK page controll code in the flow definition file if you like.

Define an associated view-state page

Here we discuss the associatation between a zul page and a view state.


/WEB-INF/flows/main/enterSearchCriteria.zul
<?page title="ZK Spring: Hotel Booking Sample Application" complete="true" ?>
<?init class="org.zkoss.zk.ui.util.Composition" arg0="/WEB-INF/layouts/standard.zul"?>
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" arg0="./hotelSearch"?>
<?variable-resolver class="org.zkoss.spring.DelegatingVariableResolver"?>
<?taglib uri="http://www.zkoss.org/dsp/web/core" prefix="c" ?>
<zk:zk     xmlns="http://www.zkoss.org/2005/zk/native"       
    xmlns:zul="http://www.zkoss.org/2005/zul"
    xmlns:zk="http://www.zkoss.org/2005/zk">
    <zul:div id="hotelSearch" class="section" self="@{define(content) fragment(hotelSearchFragment)}">
        <span class="errors">
           <!-- <h:messages globalOnly="true" />  -->
        </span>
        <h2>Search Hotels</h2>
        <form id="mainForm">
            <fieldset>
                <div class="field">
                    <div class="label">
                        Search String:
                    </div>
                    <div class="input">
                        <zul:textbox id="searchString" value="@{searchCriteria.searchString}"
                            tooltiptext="Search hotels by name, address, city, or zip."/>
                    </div>
                </div>
                <div class="field">
                    <div class="label">
                        Maximum results:
                    </div>
                    <div class="input">
                        <zul:listbox id="pageSize" rows="1" mold="select" selectedItem="@{searchCriteria.pageSize}">
                            <zul:listitem forEach="" value="0" label=""/>
                        </zul:listbox>
                    </div>
                </div>
                <div class="buttonGroup">
                    <zul:button self="@{action(search)}" label="Find Hotels" onClick=""/>
                </div>
            </fieldset>
        </form>
    </zul:div>
    ...
</zk:zk>

Per the file name, you might have guessed this example view state page is associated to the view state enterSearchCriteria. Spring Work Flow maps a view state to a view state page URL by name convention. It is a combination of the view state id and the URL path of the work flow definition file.

Following is some important notes regarding a ZK view state page:

  • The <?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" ...?> is required. ZK Spring Web Flow Integration assumes it. Basically, any settable work flow variables shall be specified as annotated data binding. E.g. the @{searchCriteria.searchString} and the @{searchCriteria.pageSize} in this example page.
  • The <?variable-resolver class="org.zkoss.spring.DelegatingVariableResolver"?> is a must. ZK rendering engine and data binder use this resolver to resove work flow variables defined in the work flow configuration file.
  • The <zul:button self="@{action(search)}" .../> is how you trigger a view state transition. Simply specify a component action annotation in the form of @{action(action-event)} and you are done; where the action-event is the transition action event name. That is, in this example, when an end user click this button, it tells Spring Web Flow engine that a transition action event search is fired for the current view state. Per the transition definition, <transition on="search" to="reviewHotels">, the Spring Web Flow engine will transit view state page from current enterSearchCriteria view state to the reviewHotels view state.

Summary

The Spring Web Flow apparently is designed with page based navigation in mind. It provides some minor Ajax effects (e.g. Popup and Fragment) and that is all. Then what role can a rich Ajax framework like ZK play? A good practice might be that doing fine grain Ajax operations in a page with ZK event programming whilst doing coarse work flow page transitions with Spring Web Flow definition. However, you can also define <transition> without the to attribute and make it doing <evalute> only so it would work like a pure ZK event listener. It is all up to you and your applications' requirement.

We now have made Spring Web Flow work with ZK. The next step shall be focused on enabling injection of ZK components into Spring beans. Integrating different frameworks together has not been an easy job and I might miss something. We welcome your feedback and suggestions so we can make ZK Spring Integration better.

Download

Version

Applicable to ZK Spring Integragion Library 1.1RC (zkspring.jar) or later.

Applicable to ZK 3.5.2 and later.

Applicable to Spring Web Flow 2.0+

Download the example codes(.war file).

Comments
 
Jack Powe
2008-12-04

Cool! Just wonder if I can use Spring Web Flow with ZK. Now comes the article. Thanks.

Anonymous
2008-12-06

So... much... xml :o

henrichen
2008-12-08

Anonymous,

Yeah. It seems a natural of Spring programming. However, if you have checked xmls of the original Spring sample, you will find ZK add 5 more lines only :-) (The blue marked in web-flow.xml)

And basically, these are configuration files that you can copy and paste across applications.

Divyaa
2008-12-08

hi henrichen

in the past week i succeeded in creating a workspace with the sprign webflow sourc ean dspring source.. to understand how spring web flow works with jsf.. co zi assumed that would be the approach i would have to take to make webflow work with zk. i am so happy to see this article.. it makes my work so much easier. The one thing that i am happy abt is.. i do no tknow if i would have succeeded with the integration.. but atleast i was thinking in the rigth direction. so i am not that bad at understanding :) yippee.
Thanks a million this article will work work wonders for my assignment. Will update you once i have the application up and working .
c ya

Anonyomous
2008-12-08

I agree that this is a symptom of SWF. I've got a number of years of spring experience and still can't stomach SWF (except maybe the nice DSL that grails have provided on top of it). I just couldn't help commenting though, that using ZK and SWF is combining two of the most XML heavy frameworks out there, and I don't personally like it (that's not to say i wouldn't use it where appropriate).

Divyaa
2008-12-08

hi

i have a small query.. when i try to run the sample code i get the following error. Please can you help me sort this out .. thank you

SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Failed to import bean definitions from relative location [webflow-config.xml]
Offending resource: ServletContext resource [/WEB-INF/config/web-application-config.xml]; nested exception is org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: Line 89 in XML document from ServletContext resource [/WEB-INF/config/webflow-config.xml] is invalid; nested exception is org.xml.sax.SAXParseException: cos-nonambig: "http://www.zkoss.org/2008/zkspring":form-login and "http://www.zkoss.org/2008/zkspring":form-login (or elements from their substitution group) violate "Unique Particle Attribution". During validation against this schema, ambiguity would be created for those two particles.
at org.springframework.beans.factory.parsing.FailFastProblemReporter.error(FailFastProblemReporter.java:68)
at org.springframework.beans.factory.parsing.ReaderContext.error(ReaderContext.java:85)
at org.springframework.beans.factory.parsing.ReaderContext.error(ReaderContext.java:76)
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.importBeanDefinitionResource(DefaultBeanDefinitionDocumentReader.java:201)
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseDefaultElement(DefaultBeanDefinitionDocumentReader.java:147)
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:132)
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:92)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.registerBeanDefinitions(XmlBeanDefinitionReader.java:507)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:398)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:342)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:310)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:143)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:178)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:149)
at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:124)
at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:92)
at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:123)
at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:423)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:353)
at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:255)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:199)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:45)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3843)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4342)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525)
at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:926)
at org.apache.catalina.startup.HostConfig.deployDirectories(HostConfig.java:889)
at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:492)
at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1149)
at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:311)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)
at org.apache.catalina.core.StandardHost.start(StandardHost.java:719)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
at org.apache.catalina.core.StandardService.start(StandardService.java:516)
at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
at org.apache.catalina.startup.Catalina.start(Catalina.java:578)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
Caused by: org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: Line 89 in XML document from ServletContext resource [/WEB-INF/config/webflow-config.xml] is invalid; nested exception is org.xml.sax.SAXParseException: cos-nonambig: "http://www.zkoss.org/2008/zkspring":form-login and "http://www.zkoss.org/2008/zkspring":form-login (or elements from their substitution group) violate "Unique Particle Attribution". During validation against this schema, ambiguity would be created for those two particles.
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:404)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:342)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:310)
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.importBeanDefinitionResource(DefaultBeanDefinitionDocumentReader.java:190)
... 42 more
Caused by: org.xml.sax.SAXParseException: cos-nonambig: "http://www.zkoss.org/2008/zkspring":form-login and "http://www.zkoss.org/2008/zkspring":form-login (or elements from their substitution group) violate "Unique Particle Attribution". During validation against this schema, ambiguity would be created for those two particles.
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:236)
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:172)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:382)
at com.sun.org.apache.xerces.internal.impl.xs.XSConstraints.reportSchemaError(XSConstraints.java:315)
at com.sun.org.apache.xerces.internal.impl.xs.XSConstraints.fullSchemaChecking(XSConstraints.java:463)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.handleEndElement(XMLSchemaValidator.java:2246)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.endElement(XMLSchemaValidator.java:814)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanEndElement(XMLNSDocumentScannerImpl.java:713)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(XMLDocumentFragmentScannerImpl.java:1685)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:368)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:834)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:764)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:148)
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:250)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:292)
at org.springframework.beans.factory.xml.DefaultDocumentLoader.loadDocument(DefaultDocumentLoader.java:75)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:396)
... 45 more

Divyaa
2008-12-09

hi

i could resolv ethe error occuring, i just modified the zkspring.xsd in the jar zkspring.jar, i removed the choice element and set it to only on element that removed the ambiguity problem.
thanks again

Divyaa
2008-12-09

hi

i could resolve the above ambiguity error in the schema validation, i edited the choice element that comes in the zkspring.xsd to include only one option, and included the modified xsd in the zkspring.jar. that seems to have done the trick ..
Thank you

henrichen
2008-12-09

Divyaa,

Sorry, it is a invalid schema bug (zkspring.xsd). I have fixed it. The correct version at

http://www.zkoss.org/2008/zkspring/zkspring.xsd

Sorry for the inconvenience.

Amit
2008-12-10

Lot useful

simon
2008-12-12

Henri,

In the article you say "However, you can also define <transition> without the to attribute and make it doing <evalute> only so it would work like a pure ZK event listener. It is all up to you and your applications' requirement." Could you explain a bit more about this approach?

thx

Simon

Amit
2008-12-12

Hi Henri,

I m importing zkspringwf.war using Eclipse 3.4. and getting this error - "cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element 'zksp:flow-builder-services'. ". Though it worked with Eclipse Europa version 3.3.0.
Any idea??

Thanks in Advance for your help
Amit

henrichen
2008-12-15

Simon,

In <transition> if we do not specify the "to" attribute, the transition will not bring you to another state. Rather, it will do <evaluate> only. And in <evaluate>, we can access the ZK component in the EL expression, so make the <transition> some how like a ZK event handling code.

henrichen
2008-12-15

Amit,

I tried import the war file to Eclipse 3.4 (I just installed) and it works.

I guess might be some kind of xml schema cache issue. Did your computer link to the internet?

Amit
2008-12-15

Thanks Henri.

I changed Network settings in Eclipse and it worked for me.

Amit
2008-12-31

Hi Henri,

I am referring all zkspringwf.war jar libraries and application to develop one customized zk-webflow demo application.
I have defined my main.xml webflow and have one view state, and on "evaluate expression" I am calling one java function to execute.Like this

<view-state id="addProgramme" view="addProgramme">
<transition on="saveData" to="programmeDetails">
<evaluate expression="progController.zulCreateProgramme(externalContext,programmeDVO)" result="flowScope.programmeDetails"/>
</transition>
</view-state>

And from my addProgramme.zul Zk file I am calling transition "saveData" like this
<h:form>
<Some code>
<div align="center">
<button id="saveprogramme" label="Save" onClick="" self="@{action(saveData)}"/>
</div>
</h:form>
But this submit "savedata" is calling its "evaluate expression" twice.
Is there any configuration I am missing? As most of the thing I referred from zkspringwf.war application.

Thanks a lot in advance for your help

Amit

Prathamesh
2009-01-03

Hi Henri,

I am trying the code with zk version 3.5 using zkspringwf.war jar libraries with spring web-flow, but <zscript> tag inside the zul file is not resolving applicationContext bean ids. I tried with different variable-resolver (org.zkoss.spring.DelegatingVariableResolver & org.zkoss.zkplus.spring.DelegatingVariableResolver) but it has failed to resolve any bean from applicationContext but this application context bean ids I can recognize from java code.

Also standard zk elements like self or even the objects in the same zul file like listbox are not getting recognised inside <zscript> by their ids.
It shows error Inline execution of .... error.

When traced it shows error particularly at the ids which are not getting recognized like bean id or even the listbox id in the same zul file.

Please help me with this asap.

Thanks in advnace
Prathmesh

henrichen
2009-01-05

@Amit and @Prathmesh

Would you post your testing code to ZK forum? Let's discuss the issue there. Thanks.

http://www.zkoss.org/forum/index.zul#path%3DlistDiscussion%3BcategoryId%3D14%3B

Jethro
2009-02-03

How can I invocate web flow from a zscript or javascript?

I develop a zul page include a <form> tab contains a input area,when I enter some value and press enter key,the form is submited,it out of SWF control.

I think I can write some script in the onsubmit event and then return false to prevent the form submit,but how to invocate web flow in script?

wacker
2009-02-12

(1) The ajax login OK dialog will not work in IE if the login popup is triggered by a <zul:toolbarbutton> instead of a <zul:button>. You can simulate this by skipping the reviewHotel view-state.

Tried with:
* zk 3.5.2, 3.5.3-FL-2009-02-09 and 3.6.0-FL-2008-10-14
* zkspring.jar from the zksprinwf.war archive from this page

(2) Also tried with zkspring.jar from the current zk-Spring-bin-1.1.0.zip archive, but this time, the login popup doesn't close itself, even in Mozilla.

(3) I would recommend you to update the documentation in order to point out the difference between

org.zkoss.spring.DelegatingVariableResolver and

org.zkoss.zkplus.spring.DelegatingVariableResolver.

If the latter one is used on zul pages with ajax login popup, the login action will be unable to propagate the currentUser variable and the login status label will show "Welcome, | logout".

It took me days to figure this out and I would very happy if someone would be responsive.

(4) After the login popup dialog has closed, the logout link points to a 404 Error. Anyway, why is there no automatic redirection to the target of the action that triggered the login? Successfully ajax-logged-in, you have to click on "Book Hotel" again... annoying.

tgeber
2009-02-17

Hi,

how can I use the zk menubar together with spring web flow when the menubar is into the layout page. That means it isn't in a flow folder.
For example, how can I show a popup window when the user pushs the button on the menubar?

Thanks for your help and sorry for my bad english.
Regards tgeber

Amit
2009-02-19

I am getting the issue of
Offending resource: ServletContext resource [/WEB-INF/config/web-application-config.xml]; nested exception is org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Config
uration problem: Unable to locate Spring NamespaceHandler for XML schema namespace [http://www.zkoss.org/2008/zkspring]
Offending resource: ServletContext resource [/WEB-INF/config/webflow-config.xml]

at org.springframework.beans.factory.parsing.FailFastProblemReporter.error(FailFastProblemReporter.java:68)
at org.springframework.beans.factory.parsing.ReaderContext.error(ReaderContext.java:85)
at org.springframework.beans.factory.parsing.ReaderContext.error(ReaderContext.java:76)
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.importBeanDefinitionResource(DefaultBeanDefinitionDocumentReader.java:201)
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseDefaultElement(DefaultBeanDefinitionDocumentReader.java:147)
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:132)
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:92)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.registerBeanDefinitions(XmlBeanDefinitionReader.java:507)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:398)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:342)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:310)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:143)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:178)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:149)
at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:124)
at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:92)
at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:123)
at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:423)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:353)
at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:255)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:199)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:45)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3843)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4350)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525)
at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:924)
at org.apache.catalina.startup.HostConfig.deployDirectories(HostConfig.java:887)
at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:492)
at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1147)
at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:311)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)
at org.apache.catalina.core.StandardHost.start(StandardHost.java:719)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
at org.apache.catalina.core.StandardService.start(StandardService.java:516)
at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
at org.apache.catalina.startup.Catalina.start(Catalina.java:578)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
Caused by: org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Unable to locate Spring NamespaceHandler for XML schema namespace [http://www.zkos
s.org/2008/zkspring]
Offending resource: ServletContext resource [/WEB-INF/config/webflow-config.xml]

at org.springframework.beans.factory.parsing.FailFastProblemReporter.error(FailFastProblemReporter.java:68)
at org.springframework.beans.factory.parsing.ReaderContext.error(ReaderContext.java:85)
at org.springframework.beans.factory.parsing.ReaderContext.error(ReaderContext.java:80)
at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.error(BeanDefinitionParserDelegate.java:281)
at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1250)
at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1243)
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:135)
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:92)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.registerBeanDefinitions(XmlBeanDefinitionReader.java:507)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:398)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:342)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:310)
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.importBeanDefinitionResource(DefaultBeanDefinitionDocumentReader.java:190)
... 42 more
Feb 19, 2009 6:24:41 PM org.apache.catalina.core.StandardContext start

while deplying the war in tomcat.

If please some one can help me out.. its urgent

Samy
2009-03-06

<bean id="viewResolver" class="org.zkoss.spring.web.servlet.view.ZkResourceViewResolver">
<property name="prefix" value="/WEB-INF/"/>
<property name="suffix" value=".zul"/>
</bean>

the above will pickup the zul files from web-inf only... wat if i need zuls from other folders say folder1/folder2/zulFile.zul that is outside WEB-INF folder?

A developer
2009-04-25

First of all thanks for this excellent article....

I love ZK. I love core Spring framework. But I just hate Spring Web Flow. And I just cannot digest the integration of ZK and Spring web flow. Can someone please clarify my nderstanding and point me out where I am wrong...

Reasons:
(a) Spring Web flow- Just too much XML and too many xml tags & attributes to remember. Earlier, Core Spring was also XML heavy, but now the Java 5 Spring annotations has made life easier for developers, whereas using Spring Web flow will contain many XML with lots of tags and I am not finding any alternative of these xml with annotation.... .

(b) Spring Web flow's one of the advantage is, any Web GUI rendering technologies (JSF,ZK etc) can be hooked with it, as there will be no GUI rendering technology specific Java classes (coded by developer) are required. But in real life how many projects changes the GUI rendering technology frequently, once its chosen?

(c) Ok, Spring Web flow encourages the developer to code all Business Logic inside proper Service only....thats an advantage to adhere developers to standard that they accidentaly do not code business logic in the bridge class (Say, Composer class of ZK)...But with proper design and architecture the Services can be architected such a way, that they are self sufficient and course grained, such that from bridge class (Say, Composer class of ZK) the proper service can be invoked and no business logic is coded in bridge class.

If annotation based data binding is used with GenericForwardComposer class then the both way data binding also becomes pretty easy and the data model referred in Composer class serves an excellent way. So, effectively without referreing any zul based component inside Composer class only proper POJO based data model will be enough for most of the cases for both way data binding.

So, I prefer to use this approach and I will inject Spring Service class in my Composer and call it.

(d) Mixing of native html and zk tag will be required (at least the form tag ).

(e) ZK is an excellent framework for event based programming. As mentioned by Henri, at most AJAX effect is fragement and popup while using ZK-Spring Web Flow integration. But I use ZK and love ZK, for its ajax effects. For ex: Master Detail Grid - I can load the data in Master detail Grid on demand (when the detail is clicked).

I am not sure how I can achieve this with ZK-SpringWebFlow interation. Henri mentioned that <evaluate> tag can be used, without mentioning the "to" atribute in transition tag to get the effect of ZK's event based programming. I have not tried this option, but I feel that I have to either write Java code inside XML, or refer some other class where I have to deal with ZK components to get the data and then call the Service Layer (by using spring) and then repopulate ZK controls....Anyway this mixed approach will just confuse the developer and may be eventually the whole code base will become unmaintainable.

The above is just my wild guess and I may be totally wrong as I am really not able to understand how to use both WebFlow based model and ZK's event based model together in an elegant way. A detail example will help me to clear my confusion. Can anyone help me out in this reagard?

-----------------------------------

Just another thought:

For page to page navigation, can't I just use ZK specific API's like sendRedirect or forward or even create attach and detach zul pages either through Java class or use a simple custom XML (if I want my all navigation to be centralized in one xml).

say, I define a custom XML like the following and load it at startup in a singleton (Say: NavigationSingleton):

<navigations>
<navigation id="nav1" url="/sample1.zul" type="redirect" />
<navigation id="nav2" url="/sample2.zul" type="createComponent" detachEarlier="true"/>
</navigations>

...
The above XML is just an example and not contain all possible options which will be needed

abstract class MyComposer extends org.zkoss.zk.ui.util.GenericForwardComposer {

//The method is just an example and may be
//more parameters will be needed
protected void doNavigate(String id) {
//....
//...
Navigation nav = NavigationSingleton.getInstance().getNavigation(id);

//do the processing from the configuration received from nav object

}

}

class UseCaseSpecificComposer extends MyComposer {

//I do not want to navigate from page as
//I clicked on detail of a master detail grid
public void onOpen$myGridDetail(Event e) {
//do processing
//...
//do not call doNavigate()...
}

//In my button I just want to attach a new page
//and detach the earlier..but do not want to
//refresh the whole page
public void onClick$someButton1(Event e) {
//do processing
//...
doNavigate("nav2");

}

public void onClick$someButton2(Event e) {
//do processing
//...
doNavigate("nav2");

}
//other methods like doAfterCompose ...or any other

}

henrichen
2009-04-27

@A developer

I cannot agree more regarding your opinions on the Spring Web Flow XML configuration issue. When I tried to integrate the ZK and Spring Web Flow, I have found this and tried to "minimise" extra configuration required, say, only 5 more lines (see "blue" lines in my article :-)).

This complex are inherited from the Spring Web Flow. Or I shall say mostly from Spring-MVC. As I have mentioned, Spring-MVC is designed for "page-oriented" or "form-based" navigation which is invented before Ajax is popular; while ZK can do "event-oriented" navigation. Thus Spring Web Flow actually "limit" what ZK can do and what ZK Spring Web Flow can do.

We are actually designing a ZK Web Flow(WITHOUT Spring) and thinking some architecture similar to your "Just another thought:". Would you post this to ZK Forum or pass me a mail (henrichen AT zkoss DOT org) that we can exchange more ideas regarding this.

Saby
2009-04-27

Hi Henri,
You have pointed out that, flow transition can be triggered by putting self=@{action(goScreen1)} in a zul button. For whole page transition its working fine for button. Even by ommiting the “to” attribute I am able to keep the control in same page without transition. Here I can give expression and call some other class and pass the ZK event.

But I need to fire the same using some other actions like combobox onSelect. Grid’s <detail> tag’s onOpen etc. How can I do it?

I have tried the same using the following:

<combobox self="@{action(someState)}">

</combobox>


<grid>

<detail id="dtid" open="false" self="@{action(someState)}">

</detail>

</grid>
The flow xml snippet:

<view-state id="screen2Id" view="screen2">
<transition on="goScreen1" to="screen1Id"/>
<transition on="someState" >
<evaluate expression="sampleViewHelper.doProcess(event)"/>
</transition>
</view-state>

Now when I change any item in combo, nothing is happening. Clicking on detail control also not firing the event. But if I put the same code in button like the following my sampleViewHelper.doProcess is getting fired.

<button label="testAjax" self="@{action(someState)}"/>


Am I doing anything wrong here? Does the @{action(stateName)} works with any event with any control or its limited to few components like button, toolbarbutton etc? Is there any other construct exists for controls like combobox, detail etc to participate in Spring WebFlow events?

Thanks & Regards
Saby

henrichen
2009-04-28

@Saby,

The default accepted event is "onClick" so button works. For other event, use the following annotation:

<combobox self="@{action(someState, when=onChange)}">

</combobox>

Saby
2009-04-28

Hi Henri,

Thanks a lot for your prompt response. It worked.

Regards
Saby

M
2009-08-10

Hi Henry! Thanks for the example. It worked great until I updated the spring jars (spring framework 2.5.6, webflow 2.0.8 and security 2.0.5). The issue is located in the "org.springframework.webflow-2.0.8.RELEASE.jar". Due to a change of the constructor of the ServletMvcViewFactory the following error message appears:

org.springframework.web.util.NestedServletException: Handler processing failed; nested exception is java.lang.NoSuchMethodError: org.springframework.webflow.mvc.servlet.ServletMvcViewFactory.<init>(Lorg/springframework/binding/expression/Expression;Lorg/springframework/webflow/mvc/view/FlowViewResolver;Lorg/springframework/binding/expression/ExpressionParser;Lorg/springframework/binding/convert/ConversionService;Lorg/springframework/webflow/engine/builder/BinderConfiguration;)V

Do you know a way to solve this problem or do you have an updated version of this example?

best regards! M

w-cker
2009-08-23

Same problem here, i get the NoSuchMethodError with spring webflow > 2.0.5.

However, using spring webflow <= 2.0.5 along with the current svn zkspring, the <zksp:zk-config/> tag breaks the parameter passing via "self.attributes" in flow definitions.

main.xml,38: <set name="flowScope.hotel" value="self.attributes.hotel"/>

⇒ hotel == null, so hotels cannot be reviewed.

Celso
2009-09-23

I have the same problem as Amit:

Configuration problem: Unable to locate Spring NamespaceHandler for XML schema namespace [http://www.zkoss.org/2008/zkspring]

Please, help!

Marius
2009-09-25

Hi Henri,

is there a way to display all validation errors created by the spring validator at the same time? If noticted that if you have lets say two textboxes and both fail validation, only the error message for the first textbox is displayed.

best regards! Marius

henrichen
2009-10-12

@M,

I have posted a bug here. Please follow it.

https://sourceforge.net/tracker/?func=detail&aid=2877018&group_id=152762&atid=785194

Giuseppe
2010-04-01

Hi Henri, first thanks for this very interesting article!

I choose this way to build my application, I need Spring Security, I like Spring Web Flow and I like ZK, so it
seems to me the right choice.

Substantially my application have to manipulate a good number of tables but with a simple layout, using a listbox
to retrieve the data; selecting a row in the listbox and pressing some special buttons, for instance a delete
button, will be deleted the selected record in the database and then will be refreshed the listbox reading again
the data from the database.

The listbox needs to retrieve the data using database (query) pagination (some table may have a lot of records).

Some page can have two listbox, selecting one row for each listbox and pressing a special button will be create a
record in the session associating the selected records, after some associations pressing a special button the
records will be inserted in the database and so on (I will use other ZK objects like Auto-complete Combobox that
read the data on the database etc, but that will be the next step).

Basically I have two problems:

1) I tried to use the approach described in the very useful article "Handling huge data using ZK", but I was not
able to integrate the things (probably for my not so good knowledge of the framework), but is it really
possible using such approach here?

2) I was not able to refresh the listbox after the action, the Web Flow event (returning to the same page) fires
and the select query runs, but I don't know how to force the listbox to reload using the new list in the
session/flowScope (this point could be similar to the previous because paginating needs refresh).

If I try to use the apply="MyController", MyController that extends the GenericForwardComposer class, and I try to
inject my dao in MyController using property, it seems that injection doesn't work.

I missed something?

Is it possible resolve those problems using Spring Web Flow and ZK?

If no, using ZK Web flow (with Spring Security) could solve the problems?

There is another way to do this without renounce to Spring Security, a codified flow approach and of course to ZK?

Thanks a lot in advance for your help and/or suggestions!

Giuseppe

Giuseppe
2010-04-02

Hi, I solved the 2nd problem, I could refresh my listbox specifying
self="@{define(content) fragment(myFragment)}" in the view and
<render fragments="myFragment" /> in the xml flow definition (obviously it was in the demo, my fault :-) )

Now I have to solve the database pagination problem, any help or suggestion will be greatly appreciated!

Thanks

Best regards

Giuseppe

blk
2010-05-21

Hi!!

Thanks for this article...

But... I need built a project with ZK, SpringWF and Hibernate, and manager with Maven, is possible this??

Thanks in advance...

dp
2010-06-30

@A Developer

SWF is primarily Spring's attempt to compete with Seam (and now CDI) and their stateful component models; the major difference being SWF is geared for web apps and Seam/EJB should be able to handle a variety of clients.

dp

Pavlin
2010-08-23

Hello,

I get an error in Eclipse, saying that:
schema_reference.4: Failed to read schema document 'http://www.zkoss.org/2008/
zkspring/zkspring.xsd', because 1) could not find the document; 2) the document could not be
read; 3) the root element of the document is not <xsd:schema>.

Simple look at the schema shows that the root element indeed is <xs:schema> instead of <xsd:schema> as expected.

Is it a mistake or intention?

Thanks,

Pavlin

 
 
Leave a Reply
 
Name (required)
Mail (will not be published) (required)
Website
(Case Insensitive)
Bold textItalic textUnderLine textSource CodeHorizontal rulerExternal Link
Post
Preview