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