You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@struts.apache.org by Timmos <ti...@gmail.com> on 2009/03/28 10:26:28 UTC

Struts 2 - Dynamic form: submitting issues

Hi,

I figured out how to generate a form with dynamic length. The submitting
part remains a bit tricky, but before you redirect me to OGNL / Type
Conversion pages, I have to say I already read those articles.

This is a part of my generated .jsp (the generate part - I won't include the
Action code for this):

<s:iterator value="properties" status="stat">
    <s:textfield name="lijst[2]" label="%{name}" />
</s:iterator>

As you can see, for testing purposes I hard-coded the index "2", but I don't
know if this syntax is correct.

This form is to be submitted to DoSearchAction:

public void setLijst(int index, String s) {
     lijst[index] = s;
     System.out.println(">>>> LIJST!!! >> " + index + ":::" + s);
}

When I run this piece of junk, I get: ognl.OgnlException: target is null for
setProperty(null, "2", [Ljava.lang.String;@13dd8).

I would like to know what is wrong with the setter / s:textfield name
parameter. What do I have to do to get it working?


-- 
View this message in context: http://www.nabble.com/Struts-2---Dynamic-form%3A-submitting-issues-tp22755036p22755036.html
Sent from the Struts - User mailing list archive at Nabble.com.


---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: Struts 2 - Dynamic form: submitting issues

Posted by Greg Lindholm <gl...@yahoo.com>.


Timmos wrote:
> 
> Hi,
> 
> I figured out how to generate a form with dynamic length. The submitting
> part remains a bit tricky, but before you redirect me to OGNL / Type
> Conversion pages, I have to say I already read those articles.
> 
> This is a part of my generated .jsp (the generate part - I won't include
> the Action code for this):
> 
> <s:iterator value="properties" status="stat">
>     <s:textfield name="lijst[2]" label="%{name}" />
> </s:iterator>
> 
> As you can see, for testing purposes I hard-coded the index "2", but I
> don't know if this syntax is correct.
> 
> This form is to be submitted to DoSearchAction:
> 
> public void setLijst(int index, String s) {
>      lijst[index] = s;
>      System.out.println(">>>> LIJST!!! >> " + index + ":::" + s);
> }
> 
> When I run this piece of junk, I get: ognl.OgnlException: target is null
> for setProperty(null, "2", [Ljava.lang.String;@13dd8).
> 
> I would like to know what is wrong with the setter / s:textfield name
> parameter. What do I have to do to get it working?
> 
> 
> 

This will work. You just have to provide getter and setter for your list.

<s:iterator value="myList" status="stat">
    <s:textfield name="myList[%{#stat.index}].field1" />
    <s:textfield name="myList[%{#stat.index}].field2" />
</s:iterator>

    public List<MyClass> getMyList()
    {
        return myList;
    }
    public void setMyList(List<MyClass>myList)
    {
        this.myList = myList;
    }

-- 
View this message in context: http://www.nabble.com/Struts-2---Dynamic-form%3A-submitting-issues-tp22755036p22782850.html
Sent from the Struts - User mailing list archive at Nabble.com.


---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: Struts 2 - Dynamic form: submitting issues

Posted by Jeroen De Ridder <vo...@gmail.com>.
According to the OGNL spec, setting indexed JavaBean properties using 
lijst[0], lijst[1] etc should work. And it does; except not through 
struts 2's params interceptor. Try it out:

public class ActionTest extends ActionSupport {
   
    private List<String> someProperty = new ArrayList<String>();
   
    public ActionTest(){
       
        try {
            Ognl.setValue("someProperty[0]", this, "Foo");
        }
        catch(Exception ex){
            ex.printStackTrace();
        }
       
    }
   
    public String execute(){
        return SUCCESS;
    }
   
    public String getSomeProperty(int index){
        return someProperty.get(index);
    }
   
    public void setSomeProperty(int index, String name){
        someProperty.set(index, name);
    }
   
}

Set a breakpoint on setSomeProperty and you will find that it calls the 
indexed setter exactly as it should. I've been debugging this around a 
bit to see why this doesn't work through the Struts 2 params 
interceptor, and I found that apparently this is due to the fact that 
Struts does not pass the action instance itself as the object to 
evaluate the OGNL expression against, but rather a CompoundRoot of the 
action and a DefaultTextProvider.

When the OGNL expression "someProperty[0]" is evaluated, OGNL will parse 
the expression into an ASTChain of 2 ASTProperty's. 
ASTChain.setValueBody is then called to execute the appropriate setter. 
What's preventing the indexed setter from being executed is 
propertyNode.getIndexedPropertyType(context, target) returning the wrong 
index type.

The index type of a property (see ASTProperty.getIndexedPropertyType) 
appears to be ultimately determined in 
OgnlRuntime.getIndexedPropertyType, which fetches a PropertyDescriptor 
for the specified object's class and property (ie. "someProperty" in 
this case). The problem here is that, since the object is a 
CompoundRoot, a property descriptor for CompoundRoot.class is returned, 
which understandably has no property descriptor for "someProperty" since 
it has no indexed setter for "someProperty", causing it to return 
INDEXED_PROPERTY_NONE (ie. not indexed) instead of 
INDEXED_PROPERTY_OBJECT. When the action instance itself is passed as 
the object to evaluate against, a property descriptor is fetched for the 
actual action class (ActionTest.class), and an 
ObjectIndexedPropertyDescriptor is returned for "someProperty" as expected.

So it looks like the root cause is that only the methods of CompoundRoot 
are considered for determining any indexed setters, not those of the 
objects it contains. I'm sure there are a whole slew of a problems 
abound if you would propagate the lookup into the contained objects, and 
even if you did, the property descriptors are only assigned once and 
then reused, so you'd still only get the descriptors for the first 
CompoundRoot object you encounter.

I'm fairly new to the Struts 2 and OGNL codebase and I'm not sure what 
the best way to fix it would be, but I hope this might provide some 
insight or even serve as a rough bug report.
>
> newton.dave wrote:
>   
>> Timmos wrote:
>>     
>>> Hi,
>>>
>>> I figured out how to generate a form with dynamic length. The submitting
>>> part remains a bit tricky, but before you redirect me to OGNL / Type
>>> Conversion pages, I have to say I already read those articles.
>>>
>>> This is a part of my generated .jsp (the generate part - I won't include
>>> the
>>> Action code for this):
>>>
>>> <s:iterator value="properties" status="stat">
>>>     <s:textfield name="lijst[2]" label="%{name}" />
>>> </s:iterator>
>>>
>>> As you can see, for testing purposes I hard-coded the index "2", but I
>>> don't
>>> know if this syntax is correct.
>>>
>>> This form is to be submitted to DoSearchAction:
>>>
>>> public void setLijst(int index, String s) {
>>>      lijst[index] = s;
>>>      System.out.println(">>>> LIJST!!! >> " + index + ":::" + s);
>>> }
>>>
>>> When I run this piece of junk, I get: ognl.OgnlException: target is null
>>> for
>>> setProperty(null, "2", [Ljava.lang.String;@13dd8).
>>>
>>> I would like to know what is wrong with the setter / s:textfield name
>>> parameter. What do I have to do to get it working?
>>>       
>> (1) If there are multiple parameters w/ the same name the framework 
>> appears to put them into a collection: it may not be necessary to do 
>> *anything*.
>>
>> (2) IIRC using indexed setters would use the (n) syntax (not [n]), but I 
>> could be remembering wrong. In any case, you don't need to use an 
>> indexed setter, just have an appropriate collection property with a 
>> setter, say:
>>
>> private List<String> lijst;
>> public void setLijst(List l) { lijst = l; }
>>
>> (Or whatever.)
>>
>> Dave
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
>> For additional commands, e-mail: user-help@struts.apache.org
>>
>>
>>
>>     
> Thx. What should the name attributes of my textfield be then, knowing that
> "lijst" is my List to set?
>
> <s:textfield value="" name"lijst" /> ? And it should work?
>   


Re: Struts 2 - Dynamic form: submitting issues

Posted by Timmos <ti...@gmail.com>.


newton.dave wrote:
> 
> Timmos wrote:
>> Hi,
>> 
>> I figured out how to generate a form with dynamic length. The submitting
>> part remains a bit tricky, but before you redirect me to OGNL / Type
>> Conversion pages, I have to say I already read those articles.
>> 
>> This is a part of my generated .jsp (the generate part - I won't include
>> the
>> Action code for this):
>> 
>> <s:iterator value="properties" status="stat">
>>     <s:textfield name="lijst[2]" label="%{name}" />
>> </s:iterator>
>> 
>> As you can see, for testing purposes I hard-coded the index "2", but I
>> don't
>> know if this syntax is correct.
>> 
>> This form is to be submitted to DoSearchAction:
>> 
>> public void setLijst(int index, String s) {
>>      lijst[index] = s;
>>      System.out.println(">>>> LIJST!!! >> " + index + ":::" + s);
>> }
>> 
>> When I run this piece of junk, I get: ognl.OgnlException: target is null
>> for
>> setProperty(null, "2", [Ljava.lang.String;@13dd8).
>> 
>> I would like to know what is wrong with the setter / s:textfield name
>> parameter. What do I have to do to get it working?
> 
> (1) If there are multiple parameters w/ the same name the framework 
> appears to put them into a collection: it may not be necessary to do 
> *anything*.
> 
> (2) IIRC using indexed setters would use the (n) syntax (not [n]), but I 
> could be remembering wrong. In any case, you don't need to use an 
> indexed setter, just have an appropriate collection property with a 
> setter, say:
> 
> private List<String> lijst;
> public void setLijst(List l) { lijst = l; }
> 
> (Or whatever.)
> 
> Dave
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
> For additional commands, e-mail: user-help@struts.apache.org
> 
> 
> 
Thx. What should the name attributes of my textfield be then, knowing that
"lijst" is my List to set?

<s:textfield value="" name"lijst" /> ? And it should work?
-- 
View this message in context: http://www.nabble.com/Struts-2---Dynamic-form%3A-submitting-issues-tp22755036p22779033.html
Sent from the Struts - User mailing list archive at Nabble.com.


---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: Struts 2 - Dynamic form: submitting issues

Posted by Dave Newton <ne...@yahoo.com>.
Timmos wrote:
> Hi,
> 
> I figured out how to generate a form with dynamic length. The submitting
> part remains a bit tricky, but before you redirect me to OGNL / Type
> Conversion pages, I have to say I already read those articles.
> 
> This is a part of my generated .jsp (the generate part - I won't include the
> Action code for this):
> 
> <s:iterator value="properties" status="stat">
>     <s:textfield name="lijst[2]" label="%{name}" />
> </s:iterator>
> 
> As you can see, for testing purposes I hard-coded the index "2", but I don't
> know if this syntax is correct.
> 
> This form is to be submitted to DoSearchAction:
> 
> public void setLijst(int index, String s) {
>      lijst[index] = s;
>      System.out.println(">>>> LIJST!!! >> " + index + ":::" + s);
> }
> 
> When I run this piece of junk, I get: ognl.OgnlException: target is null for
> setProperty(null, "2", [Ljava.lang.String;@13dd8).
> 
> I would like to know what is wrong with the setter / s:textfield name
> parameter. What do I have to do to get it working?

(1) If there are multiple parameters w/ the same name the framework 
appears to put them into a collection: it may not be necessary to do 
*anything*.

(2) IIRC using indexed setters would use the (n) syntax (not [n]), but I 
could be remembering wrong. In any case, you don't need to use an 
indexed setter, just have an appropriate collection property with a 
setter, say:

private List<String> lijst;
public void setLijst(List l) { lijst = l; }

(Or whatever.)

Dave


---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org