wood burning stoves 2.0*
The moose likes Struts and the fly likes dynamic beans Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Android Security Essentials Live Lessons this week in the Android forum!
JavaRanch » Java Forums » Frameworks » Struts
Bookmark "dynamic beans" Watch "dynamic beans" New topic
Author

dynamic beans

D. Clarke
Greenhorn

Joined: May 09, 2006
Posts: 25
Good day -

I have a JSP that has a block data that can be duplicated up to 4 times, as well as some that will only be there once. I have an ActionForm :


form
String fieldA
String fieldB
ArrayList beans;


The beans array is a list of objects to hold the data that can be duplicated:

Bean
String One;
String Two;
String Three;

I tried using a DynamicForm, but the problem is that I can't figure out how to create that bean, which is then populated on the form. Here is what I currently have, that doesn't work:

<c:forEach var="request" items="${requestForm.map}">
<html:text indexed="true" name="request" property="fieldA"/>
<html:text indexed="true" name="request" property="fieldB"/>
<html:text indexed="true" name="request" property="fieldC"/>
</c:forEach>

Can somebody please suggest the best way to dynamically create the bean (when the user clicks a button that piece of code is duplicated) and associate it with the form ArrayList?
Merrill Higginson
Ranch Hand

Joined: Feb 15, 2005
Posts: 4864
Here's one possible solution:

1.Put the ActionForm in session scope

2. Before the JSP is displayed, instantiate one of your beans that is used for copying and put in the ArrayList as the first element. Then forward to the JSP. The code to display your list of beans will look like this:

<c:forEach var="bean" list="${requestForm.map.beans}" status="status" />
<html-el:text property="beans[${status.index}].one />
<html-el:text property="beans[${status.index}].two/>
<html-el:text property="beans[${status.index}].three/>
</c:forEach>

3.Create an Action class and path named "duplicateForm" or something similar. The sole purpose of this action is to duplicate the data.

4.When the "duplicate" button is pressed on the JSP, use JavaScript to change the action to "duplicateForm" and submit the form. Something like this:

<html:button property="duplicate" value="duplicate" onklick="this.form.action = 'duplicateForm.do';this.form.submit()" />

5.In the duplicateForm action, instantiate a second bean, copy the data from the first bean to the second and place the second bean in the List. you can then forward to the original JSP, and it will now show two copies of the data


Merrill
Consultant, Sima Solutions
D. Clarke
Greenhorn

Joined: May 09, 2006
Posts: 25
Thank you for the advice, but I was hoping Struts had a graceful way of adding bean data to form arrays, but it seems like I have to jump thru hoops to do this.

I wonder if the problem is that Struts can't handle it, or the JSP libs can't handle it?

The search continues...
Merrill Higginson
Ranch Hand

Joined: Feb 15, 2005
Posts: 4864
I don't know what you'd consider "graceful", but dynamically copying data on an HTML form is a fairly complex process. It shouldn't surprise you that it takes a bit of coding to do it.

It will seem less cumbersome as you get more familiar with the Actionform, its relationship to the HTML page, and how indexed properties work.
D. Clarke
Greenhorn

Joined: May 09, 2006
Posts: 25
Thank you for the tip, and I am sorry if I came across as ungrateful earlier. I think what I can do is just have my beans in the JSP already, but hidden. So if I have something like:

<html:text name="${myForm.map.arrayListName[0]}" property="fieldA"/> and
<html:text name="${myForm.map.arrayListName12]}" property="fieldA"/>

then I should be able to set the bean value in the array of the form right?

Thanks again for your help, this has been a learning experience!
Merrill Higginson
Ranch Hand

Joined: Feb 15, 2005
Posts: 4864
Perhaps it would help if I understood your problem domain better. It occurs to me that the suggestions I gave you earlier may not fit what you're really trying to do.

Here's what I'd like from you:

1. Tell me exactly what is in the ActionForm and in the bean that is contained by the array of beans. If you can use real property names instead of field1, field2, etc, that will help.

2. Tell me what the screen should look like before the button is pressed and what it should look like after the button is pressed. Tell me which data should be on the ActionForm bean, and which should be in the Bean that is inside the list of beans.
Jason Menard
Sheriff

Joined: Nov 09, 2000
Posts: 6450
"Johnny Rotten",

Welcome to JavaRanch. We don't have many rules here but we do have a naming policy that we strictly adhere to. Please re-read this naming convention and change your display name in order to comply. Thanks in advance.
D. Clarke
Greenhorn

Joined: May 09, 2006
Posts: 25
Ok, I am back after a name change....

What I am trying to do is have a screen with repeating blocks of data. So it might look like this:

User Name:
User City:

Product A description:
Product A price:
Product A quantity:

Product B description:
Product B price:
Product B quantity:

Product C description:
Product C price:
Product C quantity:

Product D description:
Product D price:
Product D quantity:

So, I want to put the Product values in a ProductBean that is stored in an ArrayList of the Form. The User information will be String attributes on the form as well. As of now, there are only going to be 4 products available, but of course that can change later.

Originally I thought the bean creation had to be dynamic, but it looks like I can just hide it with DHTML, so I will have the <bean:write...> tags to populate each bean. I still have to figure that part out (UI is not my strength) and if I can even do that with JSTL.

Thanks again for all your patience,
Merrill Higginson
Ranch Hand

Joined: Feb 15, 2005
Posts: 4864
Is this page being used just to display products that are already in the database? Or can the user add new products from the page? If so, how will this process work? Do you want the user to be able to change the product information? if so, how?
D. Clarke
Greenhorn

Joined: May 09, 2006
Posts: 25
These are going to be products that the user defines and adds to the database once they click the submit button. Of course, I will have to validate that as well, but I'll cross that bridge when I get there.

Grateful,
D.
D. Clarke
Greenhorn

Joined: May 09, 2006
Posts: 25
Here is what I have thus far:

Form
private ArrayList productList = new ArrayList(4);

public getProductList(int index) {
System.out.println("returning request # " + index + " = " + ((ProductBean)productList.get(index)).toString());
return (ProductBean)productList .get(index);
}

The bean has all the attributes initialized to "" or 0.0, so I don't think its a null issue.

In my JSP I am trying to get the first ProductBean and set the property of description field:

<html:text name="${form.productList[0]}" property="description" />

However, I am getting the error:
Unable to find a value for "description" in object of class "com.company.form" using operator "."

So I am not sure if the problem is my JSTL syntax or the bean. I put debug statements in the array and it doesn't appear to ever get called.
D. Clarke
Greenhorn

Joined: May 09, 2006
Posts: 25
Ok, yet another update - but it's encouraging....

I finally got my JSP to stop puking and everything appears to be fine. I added a constructor to my Actionform that created 4 instances of the ProductBean and added to the Form's arraylist. If I don't do this, it doesn't appear in the debugger as ever having ProductBeans in the array.

Then in the JSP I do this:
<input type="text" name='${requestScope.form.productList[0].description}' value="Blah blah blah"/>" id="from">

While this is getting past the errors, it is also not populating the bean. I thought it would be like Java, and update by reference, but apparently this is not correct.

Hopefully this all makes sense - it's been a long day !
Merrill Higginson
Ranch Hand

Joined: Feb 15, 2005
Posts: 4864
First of all, the name attribute of the <html:text> should generally be omitted entirely. It represents the name of the ActionForm bean you're using. If you don't specify a name, it defaults to the one used by the action specified in the <html:form> tag.

The <html:text> tag knows how to get the value from the underlying ActionForm bean. You don't have to do anything to make this happen except specify the correct property name. Here is a link to the documentation on this tag.

I've put together a basic outline that will do what you've said you want your page to do. It will produce the page you specified as a blank form ready to be filled out. It will have spaces to enter up to four products. To display the page, enter the URL www.mycompany.com/myapp/productInit.do


sruts-config.xml file
<form-bean name="productForm" type="com.mycompany.ProductForm" />
<action path="/productInit" name="productForm" scope="session" type="com.mycompany.ProductInit>
<forward name="success" path="/product.jsp">
</action>
<action path="productProcess" name="productForm" scope="session" type="com.mycompany.ProductProcess >
<forward name="success" path="/product.jsp">

</action>

ProductForm

public class ProductForm extends ActionForm {
private String name;
private String city;
private List products;
// getters and setters for the above properties
public Product getProduct(int index) {
return (Product)products.get(i);
}
public void setProduct(int index, Product p) {
products.set(index, Product);
}
}

Product

public class Product {
private String Description = "";
private BigDecimal price = new BigDecimal(".00");
private int quantity = 0;
// getters and setters for the above properties
public String getFormattedPrice() {
return price.toString();
}
public void setFormattedPrice(String str) {
price = new BigDecimal(str);
}
}


ProductInit Action


product.jsp
<%@ taglib uri="http://jakarta.apache.org/struts/tags-html-el"
prefix="html"%>
<html>
<head>
<title>Product Page</title>
</head>
<body>
<html:form action="/productProcess" >
<table>
<tr><td>Name: <html:text property="name" /></td></tr>
<tr><td>City: <html:text property="city" /></td></tr>
<tr><td><bProducts</b></td></tr>
<c:forEach list="${productForm.products}" var="product" status="status">
<tr><td>Description: <html:text property="product[${status.index}].description" /></td></tr>
<tr><td>Price: <html:text property="product[${status.index}].formattedPrice" /></td></tr>

</c:forEach>
<tr><td><html:submit property="save" value="submit" /></td></tr>
</table>
</body>
</html>
[ May 11, 2006: Message edited by: Merrill Higginson ]
D. Clarke
Greenhorn

Joined: May 09, 2006
Posts: 25
Good day Merrill -

Thank you so very much for all your help. You certainly have gone out of your way to help me here, more than most others would have done. It would appear that it is finally working, despite taking a slightly different approach.

I still initialize the array in my constructor because that is working. I might change it to use an action to initialize it as you suggested.

The problem was in my JSP page. Because I didn't want to iterate and build a straight list (which I omitted to say because of brevity concerns), because there is lots of content between bean to populate, I referrenced them directly.

So here is what I did:

Form:
List productList = new ArrayList(4);
constructor()
for (a < 4) {
ProductBean bean = new ProductBean ();
bean.setIndex(a);
productList.add(a, bean);
}


JSP:
<html:text property="productList[${0}].description" value="" />
<html:text property="productList[${0}].price" value="" />
<html:checkbox property="productList[${0}].show"/>

<html:text property="productList[${1}].description" value="" />
<html:text property="productList[${1}].price" value="" />
<html:checkbox property="productList[${1}].show"/>


I put some debug out and it would appear that the beans are being properly being populated. My last concern is that by initializing the array in teh constructor, I am going to be creating this over and over - so I will probably take your suggestion and use the action class to create them.

Thank you again for your patience and advice. I really need to brush up on my JSTL, I am much more comfortable with Java!

Gratefully,
D.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: dynamic beans
 
Similar Threads
Nested Iterator Tags
indexed property
Validation of indexed properties
Indexed properties and logic:iterate problem
logic iterate tag for Float array