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: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to