问题
I'm working on a webflow (SWF2). The entities are generated using Roo. One of the webflow views, multi-instance.jspx, may be called multiple times to allow for multiple, persisted instances of the same entity (MyClass).
I'd like to keep a list of those persisted entities so that I can reference them on a later point in the flow. So far, I've tried the following.
A simplified version of my flow.xml
looks like this:
<on-start>
<evaluate expression="new java.util.ArrayList()" result="flowScope.myList" result-type="java.io.Serializable"/>
</on-start>
<view-state id="multi-instance" view="multi-instance" model="myClass">
<binder>
<binding property="field1"/>
<binding property="field2"/>
</binder>
<on-entry>
<evaluate expression="new com.test.MyClass()" result="flowScope.myClass" />
</on-entry>
<transition on="another_instance" to="multi-instance"/>
<transition on="success" to="confirm"/>
<transition on="cancel" to="abort"/>
<on-exit>
<evaluate expression="myClass.persist()"/>
<evaluate expression="flowScope.myList.add(myClass)"/>
</on-exit>
</view-state>
The confirm
and abort
view-states are defined in flow.xml
as well. The confirm.jspx
looks like this:
<div xmlns:spring="http://www.springframework.org/tags" xmlns:c="http://java.sun.com/jsp/jstl/core" xmlns:fn="http://java.sun.com/jsp/jstl/functions" xmlns:form="http://www.springframework.org/tags/form" xmlns:util="urn:jsptagdir:/WEB-INF/tags/util" xmlns:jsp="http://java.sun.com/JSP/Page" version="2.0">
<jsp:directive.page contentType="text/html;charset=UTF-8" />
<jsp:output omit-xml-declaration="yes" />
<form:form>
<c:forEach items="${myList}" var="instance">
<li>${instance.getField1()} ${instance.getField2()}</li>
</c:forEach>
<div class="submit">
<input type="submit" id="success" name="_eventId_success" value="success"/>
<input type="submit" id="cancel" name="_eventId_cancel" value="cancel" />
</div>
</form:form>
</div>
So to the question:
Whenever I hit confirm.jspx
, the web return says that there's an exception thrown at org.springframework.webflow.engine.impl.FlowExecutionImpl.wrap(FlowExecutionImpl.java:569).
EDIT: The Apache log is a little more enlightening. The following is a snippet of the top of the call stack:
SEVERE: Servlet.service() for servlet jsp threw exception org.apache.jasper.JasperException:
/WEB-INF/views/myflow/confirmation.jspx(6,7)
The function getField1 must be used with a prefix when a default namespace is not specified
at org.apache.jasper.compiler.DefaultErrorHandler.jspError(DefaultErrorHandler.java:40)
I'm not sure if the ArrayList-approach is possible; I believe I've read somewhere that the flowScope.myClass instance, as it is defined in the multi-instance
-state, is picked up by the GC or at least falls out of scope. I'm not sure. If anyone can shed some light on that particular topic, I'd be thrilled.
(And if you happen to know a better way to keep a list of these persisted entities, please feel free to let me know!) Thanks in advance! :)
Update: I'm able to count the number of elements in my list like so:
<c:choose>
<c:when test="${myList != null}">myList exists, it contains <c:out value="${fn:length(myList)}" /> items!</c:when>
<c:otherwise>myList doesn't exist.</c:otherwise>
</c:choose>
It shows the same number of elements as I've inserted. However, when I do this:
<c:forEach items="${myList}" var="instance">
<c:if test="${instance != null}">
<li>${instance.field1} ${instance.field2}</li>
</c:if>
</c:forEach>
nothing is displayed. (I can confirm that there is a correct number of <li>-elements when the null-test is omitted. Note also that I'm trying to access the properties directly, as indicated here: jstl/jsp - iterating over a vector of beans) I don't know what to think, regarding the scope here, but it seems clear that I can't access my entities via an ArrayList.
回答1:
First, with regards to your question(s) around variable scoping, I would suggest looking at section 4.4 of the SWF documentation, where it describes all of the different available scopes.
Flow scope variables live through the lifetime of the flow. So your myClass variable will not go away until the flow exits. However keep in mind that your <on-entry>
expression is assigning a new instance every time that view state is entered.
Second, I think you are probably on the right track with your solution. I would note several things:
- You are persisting and adding to your list in the
<on-exit>
element -- this means these two things will always happen when you leave the state, including when you are doing yourcancel
transition. This may not be what you want. Related: - Your
<transition on="another_instance" to="multi-instance"/>
is actually exiting the view-state and re-entering it, triggering the<on-exit>
and<on-entry>
logic. It is possible to remain in the same state, by simply doing<transition on="another_instance">
. Doing this will execute any logic you have inside the transition, and then re-render the view without actually changing states. - You may want to consider using the <var> tag to initialize variables... what you are doing with
<evaluate expression="new ..."/>
works but using<var>
may be cleaner. Also, it is not necessary to sayresult-type="java.io.Serializable"
.result-type
should be used when you need to convert the return type to something elese.
Finally, the error you are getting looks like it is unrelated to webflow. JSTL/EL allow you to access bean properties but not methods, and you are trying to invoke a method. See this question for more info.
来源:https://stackoverflow.com/questions/6180297/spring-webflow-how-to-keep-track-of-persisted-entity-ids