TOC PREV NEXT INDEX






 


 




Spring Framework Integration


The Spring Framework is a full-stack Java/JEE application framework focusing on increased development productivity while improving application testability and quality. For more information on Spring Framework, see http://www.springframework.org.

Spring integration with ICEfaces should be considered preliminary only. The Spring Webflow (http://www.springframework.org/webflow) has recently released milestone versions 2.0 and 2.5, which are a substantial change to the framework and all integration efforts therein. ICEFaces support for version 1 (currently 1.0.5) of Spring Webflow is therefore preliminary, and not subject for improvement.

Getting Started

The easiest way to produce a working ICEfaces/Spring application is to copy the demonstration application available from http://downloads.icefaces.org. This application is based on the original Spring Sellitems demonstration application, and consists of a simple webflow example coupled with ICEfaces components and a demonstration of some pages with enhanced capability using partial submits to access server business logic without full-page transitions. Using the build mechanism in place from the Spring examples allows Ivy to resolve any JAR dependencies. In the demonstration application, a project.properties file contains the directory location of some Springcommon build files. The downloaded demonstration application is intended to go into the following directory:

{Spring base directory}/Spring-webflow-1.0.N/projects/spring-webflow-samples

where N is the version of Spring webflow in use.

Putting the demonstration application in this location allows the build files to work with the existing Spring build resources.

Configuring Spring Applications to Work with ICEfaces

Generally speaking, Spring Webflow applications are about managing state change and managing navigation through the web application. ICEfaces can certainly work in this environment, but ICEfaces brings AJAX technology to web applications simply, without exposure to verbose JavaScript. Using partial submits, you can increase the functionality of a given page and expose more business logic without the need for the same amount of cumbersome full-page navigation states in the application. Any single page can now be enhanced with features, such as autocomplete, with values fetched from the Server, or server-based business rules for calculating intermediate costs.

The good news is that requests to the server made by ICEfaces components don't change or affect the state of the current Webflow State as long as the interaction doesn't return a navigation result that is the same as the result defined for the Spring Webflow. This means that you can add a component to the page and go about increasing functionality without worrying about inadvertently changing the application's behavior.

Primarily, the changes to a Spring application to work with ICEfaces consist of:

Changes to web.xml

The following is the web.xml file from the downloadable example application:

<?xml version="1.0" encoding="ISO-8859-1"?>
 
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
 
    version="2.4">
 
	<context-param>
 
		<param-name>contextConfigLocation</param-name>
 
		<param-value>
 
			classpath:org/springframework/webflow/samples/sellitem/services-config.xml
 
			/WEB-INF/webflow-config.xml
 
		</param-value>
 
	</context-param>
 

 
	<context-param>
 
		<param-name>com.icesoft.faces.standardRequestScope</param-name>
 
		<param-value>true</param-value>
 
	</context-param>
 

 
    <!-- Bootstraps the root Spring Web Application Context, responsible for 
         deploying managed beans defined in the configuration files above.  These 
         beans represent the services used by the JSF application. -->
 
	<listener>
 
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-
class>
 
	</listener>
 

 
    
 

 
    <!--MyFaces listener that starts up the JSF engine by reading 
 
        faces-config.xml -->
 
    <listener>
 
        <listener-class>
 
            org.apache.myfaces.webapp.StartupServletContextListener
 
        </listener-class>
 
    </listener>
 

 
    <listener>
 
        <listener-class>
 
            com.icesoft.faces.util.event.servlet.ContextEventRepeater
 
        </listener-class>
 
    </listener>
 

 
    <!-- Listener for initializing contexts in 3rd party servlet environment --> 
 
    <listener>
 
        <listener-class>
 
            org.springframework.web.context.request.RequestContextListener
 
        </listener-class>
 
    </listener>
 

 
    <context-param>
 
        <param-name>
 
            com.icesoft.faces.synchronousUpdate
 
        </param-name>
 
        <param-value>true</param-value>
 
    </context-param>
 

 
    <context-param>
 
        <param-name>
 
            com.icesoft.faces.concurrentDOMViews
 
        </param-name>
 
        <param-value>false</param-value>
 
    </context-param>
 

 

 
    <context-param>
 
        <param-name>
 
            com.icesoft.faces.actionURLSuffix
 
        </param-name>
 
        <param-value>.iface</param-value>
 
    </context-param>
 

 
    <!-- The front controller for the JSF application, responsible for handling all 
         application requests -->
 
    <servlet>
 
        <servlet-name>Faces Servlet</servlet-name>
 
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
 
        <load-on-startup>1</load-on-startup>
 
    </servlet>
 

 
    <servlet>
 
        <servlet-name>Persistent Faces Servlet</servlet-name>
 
        <servlet-class>
 
               com.icesoft.faces.webapp.xmlhttp.PersistentFacesServlet
 
        </servlet-class>
 
        <load-on-startup> 1 </load-on-startup>
 
    </servlet>
 
    <servlet>
 
        <servlet-name>Blocking Servlet</servlet-name>
 
        <servlet-class>
 
              com.icesoft.faces.webapp.xmlhttp.BlockingServlet
 
        </servlet-class>
 
        <load-on-startup> 1 </load-on-startup>
 
    </servlet>
 

 
    <servlet-mapping>
 
        <servlet-name>Persistent Faces Servlet</servlet-name>
 
        <url-pattern>*.iface</url-pattern>
 
    </servlet-mapping>
 

 
    <servlet-mapping>
 
        <servlet-name>Persistent Faces Servlet</servlet-name>
 
        <url-pattern>*.faces</url-pattern>
 
    </servlet-mapping>
 

 
    <servlet-mapping>
 
        <servlet-name>Persistent Faces Servlet</servlet-name>
 
        <url-pattern>/xmlhttp/*</url-pattern>
 
    </servlet-mapping>
 

 
    <servlet-mapping>
 
        <servlet-name>Blocking Servlet</servlet-name>
 
        <url-pattern>/block/*</url-pattern>
 
    </servlet-mapping>
 

 
    <servlet-mapping>
 
        <servlet-name>Persistent Faces Servlet</servlet-name>
 
        <url-pattern>*.jsp</url-pattern>
 
    </servlet-mapping>
 

 
    <welcome-file-list>
 
      <welcome-file>index.html</welcome-file>
 
    </welcome-file-list>
 

 
</web-app>
 

 
Notes on web.xml
Changes to faces-config.xml
<faces-config>
 
    <application>
 
	  <navigation-handler>
 
					org.springframework.webflow.executor.jsf.FlowNavigationHandler
 
	  </navigation-handler>
 
		<variable-resolver>
 
					org.springframework.web.jsf.DelegatingVariableResolver
 
	  </variable-resolver>
 
          
 
          <!--<variable-resolver>
 
		org.springframework.webflow.executor.jsf.DelegatingFlowVariableResolver
 
	    </variable-resolver>-->
 
    </application>
 
	
 
    <lifecycle>
 
        <phase-listener>
 
            org.springframework.webflow.executor.jsf.FlowPhaseListener
 
        </phase-listener>
 
    </lifecycle>
 
</faces-config>
 

In this file, be sure to have the appropriate JSF variable resolver specified. See the Spring Framework 2.1 reference Section 15.3, Integrating with JavaServer Faces.

Known Issues

Using server-initiated rendering can cause problems with regard to Webflow states. When a server-initiated render operation starts, the Webflow executor key is retrieved from the UIViewRoot, and the Webflow state is resumed. This is okay, and works properly, but it does cause problems if the Webflow has reached a terminal state. In this case, the Webflow cannot be resumed.

There might be several server-initiated rendering scenarios for your application. Currently, it is difficult to know when a page transition occurs as part of a partial submit; hence, it is difficult to know precisely when to stop the server-initiated rendering if the page transitions to a Webflow terminal state.

Consider an example of an application with an outputText component displaying the time on the bottom of the page every 5 seconds. This type of component would be easy to add to a footer, so it is included on every page of the application. This would cause problems in the Webflow sellitems demonstration application because when the application winds up in the shipping cost summary page, the Webflow has reached a terminal state. If the ticking clock is still updating at this time, this will cause exceptions when it tries to restore the Webflow as part of the server-initiated rendering pass.

The DisposableBean interface (and the deprecated ViewListener interface) allow the server-initiated rendering code to know when the user leaves a particular view. For more information on the DisposableBean interface, refer to The DisposableBean Interface.

It is best to avoid server-initiated rendering within Spring Webflow applications for now. Once we understand the ramifications of Webflow 2.0, we'll be able to make using server-initiated rendering easier. In the meantime, using ICEfaces components with simple AJAX functionality should offer plenty of design flexibility.



Copyright 2005-2008. ICEsoft Technologies, Inc.
http://www.icesoft.com

TOC PREV NEXT INDEX