Webflow returns full page instead of tiles fragment
Hi,
I'm having problems refreshing fragments in webflow. In order to test my understanding, I've build a simple demo app which consists of one page with three parts - a menu, a body and a footer. Each part prints out the current time. The menu also has a refresh link which is meant to refresh the body. If this was working correctly, the time in the body tile would be later than the time in the menu and footer tiles
Of course, this isn't working (otherwise I wouldn't be here typing this post on Sunday morning!). Checkng the result returned to the browser with the use of firebug, the complete page is returned instead of just the body fragment.
As I understand it, a complete page is returned if javascript is disabled, but the refresh request is being made as an ajax call, so this doesn't look to be the problem. If anyone could point out where I'm going wrong, I'd really appreciate it. I'm using Spring 2.5.6, webfow 2.0.9 (have tried 2.0.6 also), tiles 2.1.0 and spring-js 2.0.9 (also tried 2.0.5)
Here's the tiles page definition:
Code:
<tiles-definitions>
<definition name="welcome" template="/WEB-INF/jsp/template.jsp">
<put-attribute name="menu" value="/WEB-INF/jsp/menu.jsp"/>
<put-attribute name="body" value="/WEB-INF/jsp/welcome.jsp"/>
<put-attribute name="footer" value="/WEB-INF/jsp/footer.jsp"/>
</definition>
</tiles-definitions>
Here's the template.jsp
Code:
<table cellpadding="5" cellspacing="5" border="1" width="100%">
<tr>
<td id="left" width="150px"><tiles:insertAttribute name="menu" /></td>
<td id="right"><tiles:insertAttribute name="body" /></td>
</tr>
<tr>
<td colspan="2" id="bottom"><tiles:insertAttribute name="footer" /></td>
</tr>
</table>
Here's the welcome page jsp - this is the section that I'm trying to refresh as a fragment
Code:
<div id="body">
Welcome: <%=new java.util.Date()%>
</div>
Here's the menu.jsp - this contains the javascript that sets up the async call and initialises the callback on that's meant to swap out the body fragment with the result returned from the server:
Code:
<form:form method="GET" id="refreshForm">
<a id="refresh" href="#">Refresh</a>
<script type="text/javascript">
Spring.addDecoration(new Spring.AjaxEventDecoration({
elementId: "refresh", <%-- get the page element with this ID and add an event handler to it that will submit the form on the event --%>
formId: "refreshForm", <%-- when the event occurs, submit the form with this ID --%>
event: "onclick", <%-- The type of event to handle --%>
params: { _eventId: "refreshPage" }
}));
</script>
</form:form>
Here's the webflow - this basically has one view-state containing an internal transition that's meant to return the body fragment:
Code:
<view-state id="start" view="welcome_page" redirect="false">
<transition on="refreshPage">
<render fragments="body" />
</transition>
</view-state>
The only thing left to describe is the webflow and tiles configuration:
Code:
<bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
<property name="definitions">
<list>
<value>/WEB-INF/tiles/pages.xml</value>
</list>
</property>
</bean>
<bean id="tilesViewResolver" class="org.springframework.js.ajax.AjaxUrlBasedViewResolver">
<property name="viewClass" value="org.springframework.webflow.mvc.view.FlowAjaxTilesView"/>
</bean>
<!-- Enables FlowHandler URL mapping -->
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter">
<property name="flowExecutor" ref="flowExecutor" />
</bean>
<!-- Maps request paths to flows in the flowRegistry;
e.g. a path of /hotels/booking looks for a flow with id "hotels/booking" -->
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping">
<property name="flowRegistry" ref="flowRegistry"/>
<property name="order" value="0"/>
</bean>
<webflow:flow-executor id="flowExecutor" flow-registry="flowRegistry"/>
<webflow:flow-registry id="flowRegistry" flow-builder-services="flowBuilderServices">
<webflow:flow-location path="/WEB-INF/classes/flows/results/results.xml" />
</webflow:flow-registry>
<webflow:flow-builder-services id="flowBuilderServices" view-factory-creator="viewFactoryCreator" />
<bean id="viewFactoryCreator" class="org.springframework.webflow.mvc.builder.MvcViewFactoryCreator">
<property name="viewResolvers" ref="viewResolver" />
</bean>
<bean id="viewResolver" class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
<property name="basename" value="views" />
</bean>
This configuration is pretty much standard stuff, with the exception of the view resolver I'm using. This is just so I can define the views in a views.properties file. Inside this file there's the following mapping:
Code:
welcome_page.class=org.springframework.web.servlet.view.tiles2.TilesView
welcome_page.url=welcome
I'd really appreciate it if someone would point out where I'm going wrong.