OGNL Array and List Indexing

馋奶兔 提交于 2019-12-07 05:35:30

问题


I'm sending this parameter to my struts action

cdata[1]=bar

In my action I'm interested in the index and the value. I defined a getter/setter pair for CDATA as the OGNL documentation suggests:

public void setCdata(int index, String value){
    LOG.info("setData; key="+ key +"; value="+ value);
    // store index and value;
}

public String getCdata(int index){
    return null; // don't really need a setter
}

This is the Exception I get:

2013-04-29 15:38:49,792 [http-apr-8080-exec-3] WARN  com.opensymphony.xwork2.util.logging.commons.CommonsLogger.warn(CommonsLogger.java:60) - Error setting expression 'cdata[1]' with value '[Ljava.
lang.String;@4223d2a4'
ognl.OgnlException: target is null for setProperty(null, "1", [Ljava.lang.String;@4223d2a4)
        at ognl.OgnlRuntime.setProperty(OgnlRuntime.java:2309)
        at ognl.ASTProperty.setValueBody(ASTProperty.java:127)
        at ognl.SimpleNode.evaluateSetValueBody(SimpleNode.java:220)
        at ognl.SimpleNode.setValue(SimpleNode.java:301)
        at ognl.ASTChain.setValueBody(ASTChain.java:227)
        at ognl.SimpleNode.evaluateSetValueBody(SimpleNode.java:220)
        at ognl.SimpleNode.setValue(SimpleNode.java:301)
        at ognl.Ognl.setValue(Ognl.java:737)
        ...

If I define a public member variable String[] cdata = new String[1000] I don't see any exception in my log but my setter is not called either. If the member variable is private I get another exception again.


回答1:


Use the following setup

List<String> cdata = new ArrayList<String>();

public List<String> getCdata() {
   return cdata;
}

public void setCdata(final List<String> cdata) {
    if (cdata == null) {
        this.cdata = new ArrayList<String>();
    } else {
        this.cdata = cdata;
    }
}

submit the values from JSP like cdata[1]=value etc

only requirement is to have the getters/setters. I've tested this Tomcat7 running on java 1.6. You can submit values like cdata[0], cdata[1] likewise

or else you could use a map

private Map<String, String> data = new HashMap<String, String>();

public Map<String, String> getData() {
    return data;
}

public void setData(Map<String, String> data) {
    this.data = data;
}

JSP can have

<s:form action="indexProperty">

    <h3>Test The Map</h3>
    <input type="text" name="data['0']"/>
    <input type="text" name="data['1']"/>

    <s:iterator value="data.entrySet()" var="aData">
        <s:property value="#aData.key" />-<s:property value="#aData.value" />
    </s:iterator>

    <input type="submit" name="submit" value="submit"/>
</s:form>

Gets populated without a issue




回答2:


My solution (rather an ugly hack):

I made my action class implement ServletRequestAware and in the action iterate over the parameter map from HttpServletRequest, fetch cdata from it and parse it for index and value

I had to change the sent parameter and encode eg cdata[999]=foobar like cdata_999_=foobar because if it looks like an array field struts requires there's a setter/getter for it in the action class.




回答3:


You should better read the docs. The docs says

JavaBeans supports the concept of Indexed properties. Specifically this means that an object has a set of methods that follow the following pattern:

public PropertyType[] getPropertyName();
public void setPropertyName(PropertyType[] anArray);
public PropertyType getPropertyName(int index);
public void setPropertyName(int index, PropertyType value);

You didn't implement all of these methods.



来源:https://stackoverflow.com/questions/16280300/ognl-array-and-list-indexing

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