You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@struts.apache.org by Scott Van Wart <sc...@indosoft.com> on 2006/08/14 17:51:08 UTC
Map-based nested bean--No bean specified?
I posted on this before, so I thought I'd post a more concrete example
this time.
I'm using a map-based nested bean, and I'm getting the following error:
java.lang.IllegalArgumentException: No bean specified
org.apache.commons.beanutils.PropertyUtilsBean.getPropertyDescriptor(PropertyUtilsBean.java:751)
org.apache.commons.beanutils.BeanUtilsBean.setProperty(BeanUtilsBean.java:937)
org.apache.commons.beanutils.BeanUtilsBean.populate(BeanUtilsBean.java:811)
org.apache.commons.beanutils.BeanUtils.populate(BeanUtils.java:298)
org.apache.struts.util.RequestUtils.populate(RequestUtils.java:493)
(add nausea)
So I whipped up an example. I have a DoTestAction that populates the
form and sticks it in a request. The form is called TestForm and looks
like this:
package test.form;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import org.apache.struts.action.ActionForm;
public class TestForm extends ActionForm
{
public static final long serialVersionUID = 1;
private String firstName;
private String lastName;
private Map<String, ChildPerson> children;
public TestForm()
{
this.firstName = "";
this.lastName = "";
this.children = new TreeMap<String, ChildPerson>();
}
public Set<String> getChildIds()
{
return this.children.keySet();
}
public Map<String, ChildPerson> getChildren()
{
return this.children;
}
public void setChildren( Map<String, ChildPerson> children )
{
this.children = children;
}
public String getFirstName()
{
return this.firstName;
}
public void setFirstName( String firstName )
{
this.firstName = firstName;
}
public String getLastName()
{
return this.lastName;
}
public void setLastName( String lastName )
{
this.lastName = lastName;
}
public void setChild( String id, ChildPerson child )
{
this.children.put( id, child );
}
public ChildPerson getChild( String id )
{
return this.children.get( id );
}
}
The populate action looks like this:
package test.action;
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.ActionForward;
import org.apache.struts.action.ActionMapping;
import test.form.ChildPerson;
import test.form.TestForm;
public class DoTestAction extends Action
{
@Override
public ActionForward execute( ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response )
throws Exception
{
TestForm testForm = new TestForm();
ChildPerson child = new ChildPerson();
child.setFirstName( "First 1" );
child.setLastName( "Last 1" );
testForm.setChild( "1", child );
child = new ChildPerson();
child.setFirstName( "First 2" );
child.setLastName( "Last 2" );
testForm.setChild( "2", child );
request.setAttribute( "testForm", testForm );
return mapping.findForward( "default" );
}
}
While the JSP itself looks like this:
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="/tags/struts-html" prefix="html" %>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;
charset=UTF-8">
<title>Test</title>
</head>
<body>
<html:form action="/test">
First Name: <html:text property="firstName" /><br>
Last Name: <html:text property="lastName" /><br>
<c:forEach var="childId" items="${testForm.childIds}">
Child #${childId} First Name: <html:text
property="child(${childId}).firstName" /><br>
Child #${childId} Last Name: <html:text
property="child(${childId}).lastName" /><br>
</c:forEach>
<html:submit />
</html:form>
</body>
</html>
My struts-config.xml (though I'm not sure this would help) has this for
the forms and actions:
<form-bean name="doTestForm"
type="test.form.DoTestForm" />
<form-bean name="testForm"
type="test.form.TestForm" />
...
<action path="/doTest" type="test.action.DoTestAction"
name="doTestForm" scope="request"
validate="false">
<forward name="default" path="/test.jsp" />
</action>
<action path="/test" type="test.action.TestAction" name="testForm"
scope="request"
validate="false">
<forward name="default" path="/test.jsp" />
</action>
I won't bother to post TestAction (/testAction) as it doesn't even get
to that point. Am I doing this the right way? Is this sort of thing
even possible? It seems such a natural way (against everything else) to
express what I'm trying to do, but doesn't seem to be working.
BeanUtils doesn't even recognize TestForm.setChild() and
TestForm.getChild() as being property accessors!
Any help would be appreciated!
Thanks,
Scott
---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org
[SOLVED?] Re: Map-based nested bean--No bean specified?
Posted by Scott Van Wart <sc...@indosoft.com>.
OK so I replaced the 'getChild( String id )' method with the following:
public ChildPerson getChild( String id )
{
ChildPerson child = this.children.get( id );
if ( child == null )
{
child = new ChildPerson();
this.children.put( id, child );
}
return child;
}
And my problems were all solved. I tried this solution before in my
previous post, but made a typo, which caused it to fail with the same
error, so I thought my previous solution simply didn't work. It wasn't
until I tried this solution with my concrete example below that I
noticed the typo (was creating a new child, putting it into the map, but
then STILL returning null. Note that setChild( String id, ChildPerson
child ) never gets called by the framework.
So my final question: Is all this a good idea? :)
- Scott
Scott Van Wart wrote:
> I posted on this before, so I thought I'd post a more concrete example
> this time.
>
> I'm using a map-based nested bean, and I'm getting the following error:
>
> java.lang.IllegalArgumentException: No bean specified
> org.apache.commons.beanutils.PropertyUtilsBean.getPropertyDescriptor(PropertyUtilsBean.java:751)
>
> org.apache.commons.beanutils.BeanUtilsBean.setProperty(BeanUtilsBean.java:937)
>
> org.apache.commons.beanutils.BeanUtilsBean.populate(BeanUtilsBean.java:811)
>
> org.apache.commons.beanutils.BeanUtils.populate(BeanUtils.java:298)
> org.apache.struts.util.RequestUtils.populate(RequestUtils.java:493)
> (add nausea)
>
> So I whipped up an example. I have a DoTestAction that populates the
> form and sticks it in a request. The form is called TestForm and
> looks like this:
>
> package test.form;
>
> import java.util.Map;
> import java.util.Set;
> import java.util.TreeMap;
>
> import org.apache.struts.action.ActionForm;
>
> public class TestForm extends ActionForm
> {
>
> public static final long serialVersionUID = 1;
>
> private String firstName;
> private String lastName;
> private Map<String, ChildPerson> children;
> public TestForm()
> {
> this.firstName = "";
> this.lastName = "";
> this.children = new TreeMap<String, ChildPerson>();
> }
>
> public Set<String> getChildIds()
> {
> return this.children.keySet();
> }
> public Map<String, ChildPerson> getChildren()
> {
> return this.children;
> }
>
> public void setChildren( Map<String, ChildPerson> children )
> {
> this.children = children;
> }
>
> public String getFirstName()
> {
> return this.firstName;
> }
>
> public void setFirstName( String firstName )
> {
> this.firstName = firstName;
> }
> public String getLastName()
> {
> return this.lastName;
> }
> public void setLastName( String lastName )
> {
> this.lastName = lastName;
> }
>
> public void setChild( String id, ChildPerson child )
> {
> this.children.put( id, child );
> }
> public ChildPerson getChild( String id )
> {
> return this.children.get( id );
> }
> }
>
>
> The populate action looks like this:
>
> package test.action;
>
> 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.ActionForward;
> import org.apache.struts.action.ActionMapping;
>
> import test.form.ChildPerson;
> import test.form.TestForm;
>
> public class DoTestAction extends Action
> {
>
> @Override
> public ActionForward execute( ActionMapping mapping, ActionForm form,
> HttpServletRequest request, HttpServletResponse response )
> throws Exception
> {
>
> TestForm testForm = new TestForm();
>
> ChildPerson child = new ChildPerson();
> child.setFirstName( "First 1" );
> child.setLastName( "Last 1" );
> testForm.setChild( "1", child );
>
> child = new ChildPerson();
> child.setFirstName( "First 2" );
> child.setLastName( "Last 2" );
> testForm.setChild( "2", child );
>
> request.setAttribute( "testForm", testForm );
> return mapping.findForward( "default" );
>
> }
>
> }
>
> While the JSP itself looks like this:
>
> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
> <%@ taglib uri="/tags/struts-html" prefix="html" %>
> <%@ page language="java" contentType="text/html; charset=UTF-8"
> pageEncoding="UTF-8"%>
> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
> <html>
> <head>
> <meta http-equiv="Content-Type" content="text/html;
> charset=UTF-8">
> <title>Test</title>
> </head>
> <body>
> <html:form action="/test">
> First Name: <html:text property="firstName"
> /><br>
> Last Name: <html:text property="lastName"
> /><br>
> <c:forEach var="childId" items="${testForm.childIds}">
> Child #${childId} First Name:
> <html:text property="child(${childId}).firstName" /><br>
> Child #${childId} Last Name:
> <html:text property="child(${childId}).lastName" /><br>
> </c:forEach>
> <html:submit />
> </html:form>
> </body>
> </html>
>
> My struts-config.xml (though I'm not sure this would help) has this
> for the forms and actions:
>
> <form-bean name="doTestForm"
> type="test.form.DoTestForm" />
>
> <form-bean name="testForm"
> type="test.form.TestForm" />
>
> ...
>
> <action path="/doTest" type="test.action.DoTestAction"
> name="doTestForm" scope="request"
> validate="false">
> <forward name="default" path="/test.jsp" />
> </action>
>
> <action path="/test" type="test.action.TestAction" name="testForm"
> scope="request"
> validate="false">
> <forward name="default" path="/test.jsp" />
> </action>
>
> I won't bother to post TestAction (/testAction) as it doesn't even get
> to that point. Am I doing this the right way? Is this sort of thing
> even possible? It seems such a natural way (against everything else)
> to express what I'm trying to do, but doesn't seem to be working.
> BeanUtils doesn't even recognize TestForm.setChild() and
> TestForm.getChild() as being property accessors!
>
> Any help would be appreciated!
>
> Thanks,
> Scott
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
> For additional commands, e-mail: user-help@struts.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org