Hello, folks, I’d appreciate some direction / input / feedback with a Struts
2 issue involving ParametersInterceptor to set properties directly on my
mode where the model contains a multi-level (collections-within-collections)
structure.

It may very well be that (novice that I am) I’m going about something in
entirely the wrong way.  Perhaps there’s a “better practice”.  On the other
hand, it also seems clear that I’ve stumbled over something questionable in
the framework.  Many thanks to anyone with the patience to read through this
and help!

I’m striving to arrange things so my forms can set properties directly on my
model, but I’m encountering difficulties using ParametersInterceptor to set
a property of an element of an “indexed” collection where that collection is
in turn an element of an outer “indexed” collection (in effect, a two-level
tree structure).

The situation where I’m trying to do this is a form that displays the
innermost elements in a table, with a textfield in each row where the user
can update a property of that row’s element.

The problem arises when there is more than one element in the outer
collection.  

The framework handles an “indexed” collection by constructing a “setmap” for
that collection,  which it caches in a “mapofSetMaps” of such “setmaps”. 
The key in the “mapOfSetMaps” is the “path” to the collection; the value is
the “setmap” for that collection, which is in turn a HashMap that correlates
the indexing property to the corresponding element in the collection.  

In my situation, it constructs two such “setmaps”: the first maps the
indexing property for the outer collection to the elements it contains, the
second maps the indexing property for a particular instance of the inner
collection to its own elements.  However, the “path” that serves as the key
to the “setmap” for a particular instance of the inner collection contains
nothing to distinguish the particular instance it maps, and in fact the map
is created and cached upon the first such indexed reference to any instance
of the inner collection, and is later retrieved and used for all subsequent
references to (again) any instance of the inner collection -- even if not
the same instance.  

As a consequence, the framework either fails to find, or finds the wrong
element, on which to set the property designated by the parameter.

I have a workaround.  It’s simple, but it’s also ugly:  I reach into the
innards and reset the “mapOfSetMaps” prior to processing each parameter.

Am I working “outside the mainstream”?  Should I rethink my approach and not
try to stretch this mechanism so far?  Or should I pursue this as an issue?

In case it helps to make the problem statement clearer, here’s a simplified
version of the code (I hope I didn’t mess it up trying to simplify it):

class Model {
        private List<OuterElement> outerIndexedCollection;
        public List<OuterElement> getOuterIndexedCollection() …
        public void setOuterIndexedCollection …
… }

class OuterElement {
        private String outerIndexProperty;
        public String getOuterIndexProperty() …
        public void setOuterIndexProperty…

        private List<InnerElement> innerIndexedCollection;
        public List<InnerElement> getInnerIndexedCollection() … 
        public void setInnerIndexedCollection …
… }

Class InnerElement {
        private String innerIndexProperty;
        public String getInnerIndexProperty() …
        public String setInnerIndexProperty …

        private String otherProperty;
        public String getOtherProperty() …
        public void setOtherProperty …
… }
        
In Model-conversion.properties:

        KeyProperty_outerIndexedCollection=outerIndexProperty
        Element_outerIndexedCollection=struts2problem.OuterElement


And in OuterCollection-conversion.properties:

        KeyProperty_innerIndexedCollection=innerIndexProperty
        Element_innerIndexedCollection=struts2problem.InnerElement


And in the JSP code:

<s:form  . . . >
<table>
<s:iterator value="%{model.outerIndexedCollection}" >
<s:iterator value="%{innerIndexedCollection}" >
  <tr>
  <td><s:property value='outerIndexProperty' /></td>
  <td><s:property value='innerIndexProperty' /></td>
  <td><s:textfield 
     
name="model.outerIndexedCollection('%{outerIndexProperty}').innerIndexedCollection('%{innerIndexProperty}').otherProperty"
value="%{otherProperty}" />
  </td>
  </tr>
</s:iterator>
</s:iterator>
</table>
<s:submit . . . />
</s:form>



I work around the problem by making my action implement ParameterNameAware
and then for each such parameter that’s going to be processed, I violate the
encapsulation of the framework details by retrieving the “mapOfSetMaps,” if
any, and clearing it:

Map mapOfSetMaps = 
(Map) ActionContext.getContext().getContextMap()
.get("set.map.key");
if (mapOfSetMaps != null) mapOfSetMaps.clear();


Again, thank you mucho to anyone who stuck with me this far.

Mark

-- 
View this message in context: 
http://www.nabble.com/-S2--ParametersInterceptor---nested-indexed-collections-tf4362313.html#a12433545
Sent from the Struts - User mailing list archive at Nabble.com.


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to