I really get **** crazy **** with Struts indexed properties.
I just posted a message about big difficulties resend an indexed
property of a form as part of a request. I made some progress in
debugging and the result is quite SURPRISING !
I build a super-simple code sample to share with you so you can help me
"find the trick".
I have a form named TestForm; It has one property named 'beans' that is
an array of TestBean. TestBean is a bean that as two strings properties
: 'b' and 'c'. I put the class code below.
I have two struts actions : '/Test' and '/Validate'.
- '/Test' populates the form (especially the 'beans' property) and
forwards to the JSP 'test.jsp'.
- 'test.jsp' displays basic a form property as well as a list (indexed
property).
- 'Validate' is the action called by the form included in 'test.jsp. It
does nothing but forward back to the JSP 'test.jsp'.
I included the code of those two actions as well as the declarations in
struts-config.xml.
HERE IS MY PROBLEM :
If I use the 'test.jsp' file below, I get an exception
InvokationTargetException when I hit the validate button (submit button
of the form). I added the JSP an the exception from BeanUtils.populate()
below.
<html>
<head>
<title>Test Indexed property</title>
</head>
<body>
<html:form action="/Validate.do">
<html:text property="a" />
<table width="650" border="0" cellspacing="0" cellpadding="0">
<tr align="left">
<th>B</th>
<th>C</th>
</tr>
<logic:iterate name="testForm"
property="beans"
id="bean"
indexId="i"
type="com.rubis.web.system.TestBean">
<tr align="left">
<td>
<html:text name="bean" property="b" indexed="true"/>
</td>
<td>
<html:text name="bean" property="c" indexed="true"/>
</td>
</tr>
</logic:iterate>
<html:submit>Validate</html:submit>
</table>
</html:form>
</body>
</html>
Here is the exception :
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
.../...
at
org.apache.commons.beanutils.BeanUtils.populate(BeanUtils.java:808)
I think I did everything OK:
- Class TestForm has the following methods
public TestBean[] getBeans();
public void setBeans(TestBean[] beans);
public TestBean getBean(int index)
public void setBean(int index, TestBean bean)
- The <logic:iterate> tag of 'test.jsp' file has an 'id' attribute equal
to the attributes 'name' of the nested <html:text> tags (as required)
Here is what are my debugging findings. I traced the populate() method
of Struts class BeanUtils. It invokes the "public TestBean getBean(int
index)" method with an Integer argument and not an "int" one !!!!!!!!!!
The exception happens in method "public static Object
getIndexedProperty(Object bean,String name, int index)" of class
org.apache.commons.beanutils.PropertyUtils with the following arguments:
- 'bean' : the TestForm instance
- 'name' : "bean" (String)
- 'index' : 1 (int)
In this routine, it finds "public TestBean getBean(int index)" in the
form's class puts it in a 'readMethod' local variable and executes :
Object subscript[] = new Object[1];
subscript[0] = new Integer(index);
try {
return (readMethod.invoke(bean, subscript));
} catch (InvocationTargetException e) {
.../...
}
=> STRUTS CALLS the "public TestBean getBean(int index)" method with an
Integer argument, and not an int.
Does anybody have an idea about this problem ?
Thanks in advance for your help.
Fred
************************ TestForm.java ******************************
package com.rubis.web.system;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionForm;
import com.rubis.web.system.TestBean;
public class TestForm extends ActionForm implements java.io.Serializable
{
public String getA() {
return a;
}
public void setA(String a) {
this.a = a;
}
public TestBean[] getBeans() {
return beans;
}
public void setBeans(TestBean[] beans) {
this.beans = beans;
}
public TestBean getBean(int index) {
return beans[index];
}
public void setBean(int index, TestBean bean) {
beans[index] = bean;
}
public void reset(ActionMapping mapping, HttpServletRequest request) {
a = null;
beans = null;
}
private String a;
private TestBean[] beans;
}
******************** TestBean.java ***********************
package com.rubis.web.system;
public class TestBean {
public String getB() {
return b;
}
public void setB(String b) {
this.b = b;
}
public String getC() {
return c;
}
public void setC(String c) {
this.c = c;
}
private String b;
private String c;
}
*************** struts-config.xml ********************
>action path="/Test"
type="com.rubis.web.system.TestAction"
scope="request"
name="testForm"
validate="false"
attribute="testForm">
<forward name="success" path="/test.jsp" />
</action>
<action path="/Validate"
type="com.rubis.web.system.ValidateAction"
scope="request"
name="testForm"
validate="false"
attribute="testForm">
<forward name="success" path="/test.jsp" />
</action>
************** TestAction.java *************************
package com.rubis.web.system;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionForward;
import org.apache.log4j.Logger;
import com.rubis.web.system.TestForm;
public class TestAction extends Action {
public ActionForward execute( ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
logger.info("execute() : Starting with form : " + form);
TestForm testForm = (TestForm) form;
testForm.setA("a");
TestBean bean1 = new TestBean();
bean1.setB("b1");
bean1.setC("c1");
TestBean bean2 = new TestBean();
bean2.setB("b2");
bean2.setC("c2");
TestBean[] beans = new TestBean[2];
beans[0] = bean1;
beans[1] = bean2;
testForm.setBeans(beans);
logger.info("execute() : Ending with form : " + form);
return (mapping.findForward("success"));
}
static private Logger logger = Logger.getLogger(TestAction.class);
}
************** ValidateAction.java *************************
package com.rubis.web.system;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionForward;
import org.apache.log4j.Logger;
public class ValidateAction extends Action {
public ActionForward execute( ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
logger.info("execute() : form = " + form);
return (mapping.findForward("success"));
}
static private Logger logger = Logger.getLogger(ValidateAction.class);
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]