Spring4 Webflow Thymeleaf2 Tiles Ajax: Everything works except

巧了我就是萌 提交于 2020-01-07 05:39:25

问题


My Spring4 Thymeleaf2 Tiles and Ajax configuration is working except the very last step. My html page does not refresh. I know the method is called and the result is returned from my service method. I think my error is the way I treat the "id" in the helloworld tile.

I will show my entire configuration as there are few xml configuration examples on the web, and one of them is wrong.

Help on the last step would be deeply appreciated.

Key parts of configuration:

WebFlow Config

<!-- Webflow Config-->

<webflow:flow-registry id="flowRegistry"
		base-path="/WEB-INF/flows/admin" flow-builder-services="flowBuilderServices">
		<webflow:flow-location id="testflow" path="testflow.xml" />
		<webflow:flow-location id="xzcreatetesttype" path="xzcreatetesttype.xml" />
	</webflow:flow-registry>


	<webflow:flow-executor id="flowExecutor"
		flow-registry="flowRegistry" />

	<webflow:flow-builder-services id="flowBuilderServices"
		view-factory-creator="mvcViewFactoryCreator" validator="validator" development="true" />
	
   
	<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter">
		<property name="flowExecutor" ref="flowExecutor" />
		<property name="saveOutputToFlashScopeOnRedirect" value="true" />
	</bean>
		

	<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping">
		<property name="flowRegistry" ref="flowRegistry" />
		<property name="order" value="-1" />
	</bean>

Views Config

<!-- views config-->

	<bean id="templateResolver"
		class="org.thymeleaf.templateresolver.ServletContextTemplateResolver">
		<property name="prefix" value="/WEB-INF/html/" />
		<property name="suffix" value=".html" />
		<property name="templateMode" value="HTML5" />
		<property name="cacheable" value="false" />
		<property name="order" value="0"></property>
	</bean>


	<!-- Thymeleaf Template Engine -->
	<bean id="templateEngine" class="org.thymeleaf.spring4.SpringTemplateEngine">
		<property name="templateResolver" ref="templateResolver" />
		<property name="additionalDialects">
			<set>
				<bean class="org.thymeleaf.extras.tiles2.dialect.TilesDialect" />
			</set>
		</property>
	</bean>

	<!-- Resolves logical view names returned by Controllers to Tiles; a view 
		name to resolve is treated as the name of a tiles definition -->


	<bean id="tilesViewResolver" class="org.thymeleaf.spring4.view.AjaxThymeleafViewResolver">
		<property name="viewClass"
			value="org.thymeleaf.extras.tiles2.spring4.web.view.FlowAjaxThymeleafTilesView" />
		<property name="templateEngine" ref="templateEngine" />
		<property name="order" value="1" />
		<property name="characterEncoding" value="UTF-8" />
	</bean>
	
	<bean id="tilesConfigurer"
		class="org.thymeleaf.extras.tiles2.spring4.web.configurer.ThymeleafTilesConfigurer">
		<property name="definitions">
			<list>
				<value>/WEB-INF/**/views.xml</value>
			</list>
		</property>
	</bean>

Service Config

<!--the businesservice and auservice are not relevant to the current problem. Not used-->

    <bean id="adminUserViewService" class="jake.prototype2.service.user.AdminUserViewServiceImpl">
		<property name="businessService" ref="businessService" />
		<property name="auService" ref="auService" />
	</bean>

Javascript Config

<!--general config-->
<!-- The  following is required to  access the javascript libraries required for ajax calls-->
	<mvc:resources mapping="/resources/**" location="/, classpath:/META-INF/web-resources/" />
	<mvc:annotation-driven />
	<mvc:default-servlet-handler />

<!---WebFlow Flow config-->


<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.4.xsd">

<!-- Here I instantiate a bean that just has  get and set date methods and a java.util.date field-->
<var name="mydate"
		class="jake.prototype2.controller.viewwrapper.ViewWrapperHelloWorld" />

	<!-- called the first view through a controller but I could set up in xml config  -->
	<view-state id="hellotlv1">
		
		<transition on="next" to="standard" />
	</view-state>

     <!-- This confirms that tiles are working. Two tiles are integrated onto a template  -->
	<view-state id="standard">	
		<transition on="next" to="standardext" />
	</view-state>
	
	<!--  This is where we call an ajax method. First we update the mydate bean, then we render as an ajax fragment -->
	<view-state id="standardext">
		
		<transition on="next" to="xzlogin" />
		<transition on="doHelloWorld">
		<!--  I update the date. I have used this design before and it works, i.e., passing variable in as an argument, 
		updating value and returning to view via webflow -->
		<evaluate expression="adminUserViewService.doHelloWorld(mydate,flowRequestContext)"
				result="mydate" />
			<render fragments="helloworld" />
		</transition>

	</view-state>

..........
Tiles Config

<!--Tiles Config-->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE tiles-definitions PUBLIC
	"-//Apache Software Foundation//DTD Tiles Configuration 2.1//EN"
	"http://tiles.apache.org/dtds/tiles-config_3_0.dtd">
	
<tiles-definitions>
	
	
		<!-- If just using tiles view resolver all pages must be defined in view regardless of whether or not they use tiles
		The path to the tiles is the path over and ablve the path specified in templateResolver configuration. Hence since template configuration
		specifies WEB-INF/html and since there is a single view.xml and all html files (templates and fragments) in the html folder, no further 
		path specification is required in this case. Webflow will be looking for the definition name as the "to" value of a transition -->
		<definition name="hellotl" template="hellotl" templateType="thymeleaf"/>
		<definition name="hellotlv1" template="hellotlv1" templateType="thymeleaf"/>
		
		
	     <!-- standard.html is a template. hw and hw2 are tiles inserted into the template. Note there is no need to specify a suffix .html here -->
		<definition name="standard" template="standard" templateType="thymeleaf">
		<put-attribute name="testa" value="hw :: content" type="thymeleaf"/>	
		<put-attribute name="testb" value="hw2 :: test"  type="thymeleaf"/>
		<put-attribute name="helloworld" value="hw :: helloworld"  type="thymeleaf"/>
		</definition>
	
	<!--  standardext is where we attempt an ajax call.  -->
	<definition name="standardext" extends="standard" templateType="thymeleaf">
		<put-attribute name="testa" value="hw3 :: content" type="thymeleaf"/>		
		<put-attribute name="testb" value="hw2 :: blank"/>	
		<put-attribute name="helloworld" value="hw3 :: helloworld"/>		
	</definition>

	
</tiles-definitions>

**HTML Template **

<!--this is the template for tiles-->
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" 
      xmlns:th="http://www.thymeleaf.org"
      xmlns:tiles="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org"
      lang="en">
     
      
<head>

<title>test layout</title>


</head>

<body >

<div tiles:include="testa">dodododo</div>

		This text appears everywhere
<div tiles:include="testb">kkkkkkk</div>

<div tiles:include="helloworld">hello world</div>



</body>


</html>

**HTML Tiles for Ajax **

  <!-these are the two tiles used for the Ajax call>
    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:th="http://www.thymeleaf.org"
	xmlns:tiles="http://www.thymeleaf.org"
	xmlns:sec="http://www.thymeleaf.org" lang="en">
    <head>
    </head>
    <body>
	<div tiles:fragment="content">

		<script type="text/javascript" th:src="@{/resources/dojo/dojo.js}"></script>
		<script type="text/javascript" th:src="@{/resources/spring/Spring.js}"></script>
		<script type="text/javascript"
			th:src="@{/resources/spring/Spring-Dojo.js}"></script>

		<form id="triggerform" method="post" action="">
			<input type="submit" id="helloWorld" name="_eventId_doHelloWorld"
				value="Update now!" />
		</form>

		<script type="text/javascript">
			Spring.addDecoration(new Spring.AjaxEventDecoration({
				formId : 'triggerform',
				elementId : 'helloWorld',
				event : 'onclick'
			}));
		</script>
	</div>
	
	
	<!--If I do not include a tiles:fragment, I get an excetion from apache tiles-->
	<div id="data"  tiles:fragment="helloworld"> <span th:text="${mydate}? ${mydate.date}">
	<!--because the date is initialized with the bean, I always see the date here, but it does not update-->
		the date goes here</span></div>
    </body>
    </html>
**Service Method **
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.webflow.execution.RequestContext;
import jake.prototype2.controller.utilities.SessionAndRequestParameters;
import jake.prototype2.controller.viewwrapper.ViewWrapperHelloWorld;
import jake.prototype2.controller.viewwrapper.ViewWrapperUserAdminLogin;
import jake.prototype2.controller.welcome.*;
import jake.prototype2.model.business.Business;
import jake.prototype2.model.user.UserAdmin;
import jake.prototype2.model.user.UserStructureException;

public class AdminUserViewServiceImpl implements AdminUserViewService
{   
/**The autowired beans are not required for the hello wrld function**/
@Autowired
private BusinessService businessService;    
@Autowired
private AdminUserService auService; 
/*******service methods************/
/**The method takes a bean declared in test flow as an argument and returns it as the return object. 
 * I cannot guarantee this is the best design as I don't know how webflow deals with objects. 
 * (In theory, it should be returning the same reference)
 * RequestContext is not needed in this example, but it is a helpful tool in many methods if you need access to
 * webflow or servlet environment objects. Note, this is webflows, request context
 * org.springframework.webflow.execution.RequestContext**/
public ViewWrapperHelloWorld doHelloWorld(ViewWrapperHelloWorld mydate, RequestContext ctx)
{       
    SS.getLogger().debug("\n\n\nReturning with new date");
    mydate.setDate(new Date(System.currentTimeMillis()));       
    return mydate;
}

回答1:


Got It!

Thymeleaf sandbox tiles was super helpful as was this post (bottom of thread)

I made a few changes.

  1. I made the ajax fragment a stand alone html file, hw4.html. NOTE: I call the date twice in this test. Once directly through thymeleaf (which confirms the tile refreshes) and once from a bean (which confirms the bean is in scope and refreshing). This way I could confirm that it was not a problem with my bean or scoping.

<div id="data"> <h3 th:text="${#dates.createNow()}"></h3>
	<span  th:text="${mydate}? ${mydate.date}">
		the date goes here</span></div>
	

Also note that there is no th:fragment or tiles:fragment. This is no longer necessary.

The views.xml looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE tiles-definitions PUBLIC
	"-//Apache Software Foundation//DTD Tiles Configuration 2.1//EN"
	"http://tiles.apache.org/dtds/tiles-config_3_0.dtd">
	
<tiles-definitions>
	
	
		<!-- If just using tiles view resolver all pages must be defined in view regardless of whether or not they use tiles
		The path to the tiles is the path over and ablve the path specified in templateResolver configuration. Hence since template configuration
		specifies WEB-INF/html and since there is a single view.xml and all html files (templates and fragments) in the html folder, no further 
		path specification is required in this case. Webflow will be looking for the definition name as the "to" value of a transition -->
		<definition name="hellotl" template="hellotl" templateType="thymeleaf"/>
		<definition name="hellotlv1" template="hellotlv1" templateType="thymeleaf"/>
		
		
	     <!-- standard.html is a template. hw and hw2 are tiles inserted into the template. Note there is no need to specify a suffix .html here -->
		<definition name="standard" template="standard" templateType="thymeleaf">
		<put-attribute name="testa" value="hw :: content" type="thymeleaf"/>	
		<put-attribute name="testb" value="hw2 :: test"  type="thymeleaf"/>
		<put-attribute name="helloworld" value="hw :: helloworld"  type="thymeleaf"/> 
		</definition>
	
	<!--  standardext is where we attempt an ajax call.  -->
	<definition name="standardext" extends="standard" templateType="thymeleaf">
		<put-attribute name="testa" value="hw3 :: content" type="thymeleaf"/>		
		<put-attribute name="testb" value="hw2 :: blank" type="thymeleaf"/>	
	   <put-attribute name="helloworld" value="hw4"  type="thymeleaf"/> 
	</definition>

	
</tiles-definitions>

The tiles template should use tiles:replace

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" 
      xmlns:th="http://www.thymeleaf.org"
      xmlns:tiles="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org"
      lang="en">
     
      
<head>

<title>test layout</title>


</head>

<body >

<div tiles:include="testa">dodododo</div>

		This text appears everywhere
<div tiles:include="testb">kkkkkkk</div>

<div tiles:replace="helloworld">hello world</div>  



</body>


</html>

The form tile is pretty much unchanged:

<div tiles:fragment="content">

		<script type="text/javascript" th:src="@{/resources/dojo/dojo.js}"></script>
		<script type="text/javascript" th:src="@{/resources/spring/Spring.js}"></script>
		<script type="text/javascript"
			th:src="@{/resources/spring/Spring-Dojo.js}"></script>

		<form id="triggerform" method="post" action="">
			<input type="submit" id="helloWorld" name="_eventId_doHelloWorld"
				value="Update now!" />
		</form>

		<script type="text/javascript">
			Spring.addDecoration(new Spring.AjaxEventDecoration({
				formId : 'triggerform',
				elementId : 'helloWorld',
				event : 'onclick'
			}));
		</script>
		
		
	</div>

The rest is pretty much the same as in the question. I didn't make changes to the application context.

So, this works. It took me about a week to work through thymeleaf and ajax. Hopefully this post will make it much easier for others that follow.

I should stress that this is a neophyte effort. Experts are welcome to offer suggested improvements or errors in this post



来源:https://stackoverflow.com/questions/32342569/spring4-webflow-thymeleaf2-tiles-ajax-everything-works-except

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!