Map-based nested bean--No bean specified?

2006-08-14 Thread Scott Van Wart
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 MapString, ChildPerson children;
  
   public TestForm()

   {
 this.firstName = ;
 this.lastName = ;
 this.children = new TreeMapString, ChildPerson();
   }

   public SetString getChildIds()
   {
 return this.children.keySet();
   }
  
   public MapString, ChildPerson getChildren()

   {
 return this.children;
   }

   public void setChildren( MapString, 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

   titleTest/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

[SOLVED?] Re: Map-based nested bean--No bean specified?

2006-08-14 Thread Scott Van Wart

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 MapString, ChildPerson children;
 public TestForm()
   {
 this.firstName = ;
 this.lastName = ;
 this.children = new TreeMapString, ChildPerson();
   }

   public SetString getChildIds()
   {
 return this.children.keySet();
   }
 public MapString, ChildPerson getChildren()
   {
 return this.children;
   }

   public void setChildren( MapString, 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

   titleTest/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

Map-based nested bean

2006-08-09 Thread Scott Van Wart

(Struts 1.2.9, Tomcat 5.5.17)

I have something similar to the following in my ActionForm:

   public class MyForm extends ActionForm {

   public static class NestedBean {
   private String name;
   private String value;
   // String getName(), String getValue(), void setName( String 
), void setValue( String )

   }

   private MapString, NestedBean children = new TreeMapString, 
NestedBean();


   // Map getChildren(), void setChildren( Map )

   public NestedBean getChild( String key ) {
   return this.children.get( key );
   }

   public void setChild( String key, NestedBean child ) {
   this.children.put( key, child );
   }

   }

I use it like so in the JSP:

   html:form action=/myAction
   html:text property=myForm.child(whatever).name /
   html:text property=myForm.child(whatever).value /
   /html:form

Everything works fine until form submission.  Then I get errors like No 
bean specified in the populate methods of BeanUtils.  Looking at the 
property descriptors I see that it's not picking up the getChild and 
setChild accessors.  Is this the right way to implement this?  Am I 
still missing something?


Thanks,
 Scott

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