I’ve been researching this for a while. I’ve read
How to update a the contents of a list displayed on JSP using Struts2?
and it is very close to what I need, but I’m still not quite able to get my problem resolved.
I have a java.util.Set of objects. The class is ‘Event’, and the name of the set is ‘events’. I want to present a form in a JSP that allows the user to modify attributes of the Event objects, but I want to update more than one at a time. Here is my JSP snippet :
<s:form theme="simple">
<table>
<s:iterator value="events" var="ev">
<tr>
<td> <s:textfield name="?????" value="%{#ev.price}" </td>
<td> <s:textfield name="?????" value="%{#ev.amount}" </td>
</tr>
</s:iterator>
<tr><td colspan="2">
<s:submit value="Apply" action="EditEventsAction_save" ></s:submit>
</td></tr>
</table>
</s:form>
My problem is (I think) what needs to go in the name of the texfield in order to update my Set.
How can I specify that the data in the textfield is supposed to update a member of my Set?
Is this possible?
UPDATE
This is my latest (simplified) attempt, based largely on what I read in the type conversion docs.
The form is populated correctly, but changes entered in the textfield are not captured on submit.
Action class:
public class TestAction extends ActionSupport implements Preparable {
private static HashMap<Integer, AssetId> assetMap = new HashMap<Integer, AssetId>();
public String execute () {
return SUCCESS;
}
public void prepare() throws Exception {
AssetId a1 = new AssetId(1, "Asset 1");
AssetId a2 = new AssetId(2, "Asset 2");
AssetId a3 = new AssetId(3, "Asset 3");
assetMap.put(1, a1);
assetMap.put(2, a2);
assetMap.put(3, a3);
}
public String save () {
return SUCCESS;
}
public static HashMap<Integer, AssetId> getAssetMap() {
return assetMap;
}
public static void setAssetMap(HashMap<Integer, AssetId> assetMap) {
TestAction.assetMap = assetMap;
}
}
JSP:
<%@ taglib uri="/struts-tags" prefix="s" %>
<html>
<body>
<s:form theme="simple">
<table>
<s:iterator value="assetMap" var="asset">
<tr>
<td><s:textfield name="assetMap[key].clientId" /></td>
</tr>
</s:iterator>
<tr><td colspan="2"><s:submit value="Apply!" action="TestAction_save" /></td></tr>
</table>
</s:form>
</body>
</html>
AssetId class:
public class AssetId implements java.io.Serializable {
private int assetId;
private String clientId;
// And public getters/setters
}
TestAction-conversion.properties
Key_assetMap=java.lang.Integer
Element_assetMap=AssetId
CreateIfNull_assetMap=false
There are a number of issues; you should have seen stack traces in your log file.
Most important: you didn’t check the rendered HTML. If you had, you’d have seen
keyrendering as-is–unevaluated. My fault (comment was incomplete), although the docs show the OGNL escape.Since you’re trying to evaluate the
keyof the current object of iteration you must wrap it in the OGNL escape sequence–you don’t want to evaluate the rest. This renders:Always check the rendered HTML.
Eventually the static map will be an issue. It should be an instance property (or, I suppose, a
ThreadLocal, but IMO you’d struggle to justify that).You should not need the type conversion file at this point; that’s largely a legacy artifact. You should have seen an exception about not being able to find the
AssetIdclass, too.Once those things are taken care of if I log the asset map in my submit method, I see: