my dog learned polymorphism*
The moose likes Struts and the fly likes Pre-select collection of options (drop-downs) 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 "Pre-select collection of options (drop-downs)" Watch "Pre-select collection of options (drop-downs)" New topic
Author

Pre-select collection of options (drop-downs)

Peter Bliznak
Greenhorn

Joined: Mar 14, 2006
Posts: 12
Hi there,
I am familiar with how to use both options and optionsCollection tags and have not trouble to pre-select values in them - to start with.

My problem is following:
I have dynamic table. Each row is represented by bean and all these bean are part of the collection. Each property of the bean represents a column of the table - most are ordinary text field - one is list of options representing sites. To accomodate for that row bean has collection of site and inner clas representing 1 row in the list (simple option bean with value and id).
Now I can populate the whole table including those drop-down list - after selection had taken place I can retrieve all values inside actionForm class...but I cannot pre-select those drop-downs lists regardless what I tried.
Anybody has done anything like this?
Thankx
P.
Merrill Higginson
Ranch Hand

Joined: Feb 15, 2005
Posts: 4864
It should certainly be possible to do this. It is entirely dependent on what you specify in the property attribute of your <html:select/> tag. Can you show us what you put in this tag? Also show us the <html ptions> or <html ptionsCollection> tags as well as the relevant portions of the ActionForm and any classes included in collections of this bean.
[ March 14, 2006: Message edited by: Merrill Higginson ]

Merrill
Consultant, Sima Solutions
Peter Bliznak
Greenhorn

Joined: Mar 14, 2006
Posts: 12
ok here are sniptes:

jsp:

<bean efine id="compOffersDyna" name="savedcompOffers" scope="request" />
<bean:size id="compOffersSizeDyna" name="compOffersDyna"/>

<logic:greaterThan name="compOffersSizeDyna" value="0">
<logic:iterate id="offersDyna" name="compOffersDyna"
type="com.web.databean.OverrideDataBean">
<tr class="odd">
<td>
<html:select property="siteNamesD" size="1" disabled="false">
html ptionsCollection name="offersDyna" property="listSites" label="name" value="id" />
</html:select></td>
/tr>
</logic:iterate>
</logic:greaterThan>

Main collection contains OverrideDataBeans

each of these represents 1 row in the html table, and 1st column has Select-option box:

public class OverrideSavedDataBean {

private Collection listSites = new ArrayList();

private String siteD;


// this class is used for a site list name and id.
public static class ListValue implements Serializable {

private String name;
private int id;

public ListValue() {}

public ListValue(int id, String name) {
this.id = id;
this.name = name;
}
public String getName() {
return name;
}
public void setName(String string) {
name = string;
}
public int getId() {
return id;
}
public void setId(int i) {
id = i;
}
}

public void setSiteList(List siteList) {
for (Iterator iter = siteList.iterator(); iter.hasNext() {
Site site = (Site) iter.next();
listSites.add(new ListValue(site.getSiteId().intValue(), site.getSiteName()));
}
..........
.........the rest are just getters and setters

and action form has following properties:

public class AdminOverrideForm extends ActionForm {

String siteNamesDyna;

private String[] selectedSitesList = null;

/**
* this is main colection holdind beans representing table raws
*/

/*
this is list of selected Sites id
*/
private String[] siteNamesD = null;



when I supply array of sites to the action form ALL the sites which are present in that array are selected in the option lists.
Merrill Higginson
Ranch Hand

Joined: Feb 15, 2005
Posts: 4864
Please read this link on using indexed properties in Struts. Pay particular attention to the section entitled "Dynamic indexes for Indexed Properties".

Once you read this, you will probably see the solution.

If you still can't get it to work, please let us know, and we'll help you work the bugs out.
Peter Bliznak
Greenhorn

Joined: Mar 14, 2006
Posts: 12
Thanks for link, I've gone through it and tried couple of different ways and sure they all work but I was only able to achieve what I have already had before. That is to populate and display data but not to pre-select select boxes. Could please tell me how can a form know of option list which is wrapped in collection of bean and how should then action form getter should look like? That is my only problem right know.
Peter Bliznak
Greenhorn

Joined: Mar 14, 2006
Posts: 12
Here is example from Struts site ... simple enough.





In my case I need to exchange strAry[] for a collection of beans so I have



Those beans without any irrelevant properties look like this:



Now I should prepare my actionform setter...



and this setter is called from action class

something like this :


It looks pretty logical but it doesn't pre-select a thing.

I was trying to make this as simple as possible....is there anything you can spot wrong?
Merrill Higginson
Ranch Hand

Joined: Feb 15, 2005
Posts: 4864
You need to create both indexed setters and getters on your form bean. Therefore, there needs to be a getDefaultCompOffersIndexed(int index) method in your main form bean. Since you've specified value="id" in your <htmlptionsCollection> tag, the property you put in the <html:select> tag must match the Id, not the name, so you need getListSiteId() and setListSiteId() methods on your OverrideDataBean

Then, in your JSP, you need to tell Struts how to call those indexed getters and setters. This is done by specifying a property attribute of the struts tag that will tell struts how to navigate to the correct property on your form bean.

In your example, it would be something like this:

<logic:iterate id="offersDyna" name="compOffersDyna"
type="com.web.databean.OverrideDataBean" indexId="index">
<tr class="odd">
<td>
<html:select property='<%="defaultCompOfferIndexed["+index+"].listSiteId"%>' size="1" disabled="false">
htmlptionsCollection name="offersDyna" property="listSites" label="name" value="id" />
</html:select></td>
</tr>
</logic:iterate>

So, if this is the first time through the <logic:iterate> loop, the property will evaluate to defaultCompOfferIndexed[0].listSiteId. This will tell Struts to call myForm.getDefaultCompOfferIndexed(0).getListSiteId(). Whatever is in the value returned by this call will be used to pre-select the option value in the options list.
[ March 15, 2006: Message edited by: Merrill Higginson ]
Peter Bliznak
Greenhorn

Joined: Mar 14, 2006
Posts: 12
Thanks a lot , that moved me definitively in the right direction.
However not there yet.
Now I am getting error:

No getter method available for property defaultCompOfferIndexed[0].listSiteId for bean under name org.apache.struts.taglib.html.BEAN

but I do have "defaultCompOfferIndexed" defined in actionForm and "listSiteId"
in the bean and there are both getters and setters for both properies.
Peter Bliznak
Greenhorn

Joined: Mar 14, 2006
Posts: 12
Ignore last post - it was my typo in jsp. Everything works now.

I really wanna thank you for you help and patience. I would not believe that some was going to spend so much time with me as you have !!!

Have a nice day.
Merrill Higginson
Ranch Hand

Joined: Feb 15, 2005
Posts: 4864
You're very welcome. Glad you wer able to get it working.
Peter Bliznak
Greenhorn

Joined: Mar 14, 2006
Posts: 12
Ok, that was premature celebration :-)
I was able to polulate and presect all data but if I try to submit form I am getting following exception

[3/15/06 15:33:30:106 EST] 104b104b PropertyMessa I org.apache.struts.util.PropertyMessageResources Initializing, config='org.apache.struts.taglib.bean.LocalStrings', returnNull=true
[3/15/06 15:33:30:106 EST] 104b104b PropertyMessa I org.apache.struts.util.PropertyMessageResources Initializing, config='org.apache.struts.taglib.logic.LocalStrings', returnNull=true
[3/15/06 15:33:30:106 EST] 104b104b PropertyMessa I org.apache.struts.util.PropertyMessageResources Initializing, config='org.apache.struts.taglib.logic.LocalStrings', returnNull=true
[3/15/06 15:33:30:137 EST] 104b104b PropertyMessa I org.apache.struts.util.PropertyMessageResources Initializing, config='org.apache.struts.taglib.html.LocalStrings', returnNull=true
[3/15/06 15:36:11:931 EST] 384a384a WebGroup E SRVE0026E: [Servlet Error]-[BeanUtils.populate]: java.lang.reflect.InvocationTargetException: java.lang.IndexOutOfBoundsException: Index: 16, Size: 0
at java.lang.Throwable.<init>(Throwable.java:54)
at java.lang.Throwable.<init>(Throwable.java:68)
at java.util.ArrayList.RangeCheck(ArrayList.java)
at java.util.ArrayList.get(ArrayList.java)

This one is not even coming from my code.
Merrill Higginson
Ranch Hand

Joined: Feb 15, 2005
Posts: 4864
I suspect the problem may be in the scope of the form bean. If you do this type of thing with indexed properties, it won't work if the Actionform is in request scope. You either need to put the ActionForm in session scope where it persists between requests, or you need to implement some mechanism to rebuild the ArrayList of objects each time the form is submitted.

I'd suggest just changing the scope to session for now to get it working. If you later decide you want to change it for performance reasons, you can then implement some sort of process to rebuild the structure with each request.
[ March 15, 2006: Message edited by: Merrill Higginson ]
Peter Bliznak
Greenhorn

Joined: Mar 14, 2006
Posts: 12
Ok I was able to fingure out with arrayOutOfBound Exc is happening

Here are my getter and setter from actionFrom


Once you try to submit this form and this getDefaultCompOffersIndexed method is call previously initialized collection is null. I thought there was supposed to be 1 form per 1 action, but it looks like this is new instance of action form.
Merrill Higginson
Ranch Hand

Joined: Feb 15, 2005
Posts: 4864
See my last post. Putting the ActionForm in session scope should solve the problem.
Peter Bliznak
Greenhorn

Joined: Mar 14, 2006
Posts: 12
I did as you suggested and got step futher. Now I cat see my indexed getter is being called as many times as I have bean in the collection - that is good, but after last call I am being taken into PropertyUtils class (one from commons)and then everything quietly without any exception dies. It would be beneficial to know what is supposed to happen after indexed getter method returns. Weir thing is I can display (populate) all data when I get to the page first time, so how come I cannot retrieve it when I attempt to submit form. Any insigh would be appreciated since I am hitting wall on this one.

{shadow of optimism - almost there}
Merrill Higginson
Ranch Hand

Joined: Feb 15, 2005
Posts: 4864
Since it fails after the last call to your indexed getters and setters, my guess is that there's some other <html:xxx> tag that is causing it to fail. Review all of the inputs on this form to verify that the property attribute corresponds to a property on the form bean.

I'd also check to make sure that your setSiteId() method is getting called.

Also, what exactly do you mean when you say that everything quietly dies? Is the execute() method of your Action class being called?
[ March 15, 2006: Message edited by: Merrill Higginson ]
Peter Bliznak
Greenhorn

Joined: Mar 14, 2006
Posts: 12
I have removed all other html:text tags, the only remaining is select and I still cannot make it move any futher. I have serious doubt this stuff any worked especially after reading this http://www.laliluna.de/dynamic.html that is year and half old article and he is describing exactly same problem I had yesterday. I guess nobody bother fixing that stuff ever since. Plus I found close to 600 posts in Struts mail archive with similar problems but no solutions or suggestion how to fix them.

Unfortunately I have nothing to go on. I will have to abort and come up with different strategy and product - Struts is nice for easy stuff if one doesn't mind writing zillion files for screen but ultimetly is it what it is an open source initialive.

Thanks again for you time but I suppose I have nothing I can give you go on helping me to make it work. Last thing I can say indexed getter is call as many times as it should and then the execution stops. Period.

"Is the execute() method of your Action class being called?" forgot to answer this one : nope execute() is never being called

[ March 16, 2006: Message edited by: Peter Bliznak ]
[ March 16, 2006: Message edited by: Peter Bliznak ]
Merrill Higginson
Ranch Hand

Joined: Feb 15, 2005
Posts: 4864
Sorry to see you give up. I and many other struts developers have been using these techniques for years, and it works fine for us. Let us know if you decide to give it another go.
Peter Bliznak
Greenhorn

Joined: Mar 14, 2006
Posts: 12
To give it a go and how do suggest I should do that? I said all I know and described all I could. There is nothing I can provide you with, no new clues, so how can I decide to give it another go?

Also if it is true that this stuff works how come me getter must look like this


Without checking for a valid index it throws arrayOutBoundsException - unless I am mistaken there is something wrong there?
[ March 16, 2006: Message edited by: Peter Bliznak ]
Merrill Higginson
Ranch Hand

Joined: Feb 15, 2005
Posts: 4864
One thing I noticed about your code is your setter methods. A setter method on a Struts action form should do nothing more than set the property. Your setter methods appear to be more complex than that.

Here's an example from your code above:


If you still have a method like this, it will cause problems.

Try changing all your setter methods so that they simply accept a parameter and place it in the property value, as in:


Here's an indexed setter:


Any processes that pulls the data from a database or any other source should be done outside of the ActionForm bean and the results placed in the bean via one of the setters.

Show me the latest draft of your form bean and it's included beans as well as the relevant portion of your JSP.
[ March 16, 2006: Message edited by: Merrill Higginson ]
Peter Bliznak
Greenhorn

Joined: Mar 14, 2006
Posts: 12
If you can't figure stuff out - simplify ....so I have.

I really wanted to have clean approach and that is why I wanted to have Bean representing 1` row in the table. Good idea but I could not made it work. So
instead of that I have an array per column and all selected site's id are stored in one of them. I am actually using indexed property but in somehow primitive way compared to what I wanted to achieve before with your majestic help.

In action form I have now this :


and in my jsp I use :



this truly works.

I would love to figure out and use the by you mentioned approach of iterating over collection of beans, that would be hellova cleaner and would eliminate all unnecessary set-get-ers in action form and imagine I have 17 columns in that table, but this will do for now.

Thanks and go onto helping another poor soul outthere

PS:

Brent Sterling
Ranch Hand

Joined: Feb 08, 2006
Posts: 948
I see that you posted while I was typing...I will post this anyway...

I looked at the link that you provided. I generally declare my actions to use request scope and use the technique described in "Workaround 2 (better)". I don't know that I would call it a "workaround", but just some simple code that needs to be in place. This technique has worked for me. The "Workaround 3 (best)" listed is interesting and not something that I have thought about, but I don't have any real complaints about "Workaround 2".

I admit that indexed properties can be confusing. I don't fully understand the structure of your data, but it looks like you have nested collections. Also, Struts (probably more correct to say BeanUtils) sometimes does a lot of things behind the scenes and it can be hard to follow.

One thing that I will point out is that the framework is not going to call an indexed "set" method that takes anything other than a simple object. This would require that it knows how to instantiate and populate your object. You have shown this method which will not be used:


To populate this object, the framework will call a method like this (I am not sure if you have something like this, and again I cannot quite follow your classes):


At this point I am getting lost piecing things together from the various snippets of code you have provided. Sometimes if you don't provide the needed indexed get method, but you do provide a method of the same name that returns a List or array, the framework will call that method and try to populate the objects. This might be what is causing your current issue.

- Brent
Merrill Higginson
Ranch Hand

Joined: Feb 15, 2005
Posts: 4864
I could not disagree more with the link's assertion that putting a form bean in the session is very bad. For a novice Struts programmer, it solves the problem easily, and I've never experienced any of the problems the author claims.

For a one level object graph of simple objects, Workaround 2 is probably the best approach. However, I frequently create pages that involve complex object graphs that go many levels deep. It doesn't make sense to re-create that object graph every time the user submits a form. Saving it in the session is a tried-and-true approach that works very well.

The only issue as I see it is with the fact that putting too much data in the session can negatively affect performance. However, if the developer is careful to clean up after himself, using the session.removeAttribute("myBean") When the process is complete, performance isn't an issue either.
 
 
subject: Pre-select collection of options (drop-downs)
 
Similar Threads
JSF page loading very slow
ValueChangeListeners in DataTable
Search Appllication
Dynamic values for JSF selectOneMenu using javascrpt. JSF validation error.
Page loading is very very slow