Struts, select tag
Hi,
This is really horrible of using select tag in struts. I have below given resources
publicclass SignUpFormBeanextends org.apache.struts.action.ActionForm
{
private Vector countries=new Vector();
private String country=null;
public SignUpFormBean()
{
super();
}
public String getCountry()
{
return this.country;
}
publicvoid setCountry(String temp)
{
this.country=temp;
}
public Vector getCountries()
{
DBDriver db=new DBDriver();
java.sql.ResultSet rst=db.executeQuery("SELECT id,name FROM countries");
try
{
while(rst.next())
{
CountryBean ctBean=new CountryBean();
ctBean.setCountryID(rst.getInt("id"));
ctBean.setCountryName(rst.getString("name"));
countries.add(ctBean);
}
}catch(Exception e){System.out.println(e);}
return this.countries;
}
publicvoid setCountries(Vector temp)
{
this.countries=temp;
}
}
publicclass CountryBean
{
privateint countryID;
private String countryName;
/** Creates a new instance of CountryBean */
public CountryBean()
{
}
publicint getCountryID()
{
return this.countryID;
}
publicvoid setCountryID(int tempID)
{
this.countryID=tempID;
}
public String getCountryName()
{
return this.countryName;
}
publicvoid setCountryName(String tempName)
{
this.countryName=tempName;
}
}
NOW I WANT TO ADD THESE COUNTRIES IN MY APPLICATION USING STRUTS SELECT TAG --
<html:select property="country" tabindex="8">
<html:options ........................./>
</html:select>
Someone please help me.................:(((( this just killing me:((((((
[4109 byte] By [
bdspidera] at [2007-11-26 23:38:43]

# 1
Put the result set in arraylist and set the arraylist in the action class like below:
myform.setCountry(myservice.getCountries()
);
<html:select property="country" tabindex="8">
<html:optionsCollection property="cnty" name="countryName" value="countryID"/>
</html:select>
name and value should match in your bean.
skp71a at 2007-7-11 15:03:18 >

# 2
Hi,It was nice getting some reply. Can you tell me little more about "action class"? I mean what did you mean by action class? and here what is "myform", is that ActionForm? and what is "myservice"?Sorry for not understanding totally and bothering you again.
# 3
Hi,
Thanks for your reply. I did it like this way--
public class SignUpFormBean extends org.apache.struts.action.ActionForm
{
private ArrayList countries=new ArrayList();
public SignUpFormBean()
{
super();
}
public ArrayList getCountries()
{
DBDriver db=new DBDriver();
java.sql.ResultSet rst=db.executeQuery("SELECT id,name FROM countries");
try
{
while(rst.next())
{
CountryBean ctBean=new CountryBean();
ctBean.setCountryID(rst.getInt("id"));
ctBean.setCountryName(rst.getString("name"));
countries.add(ctBean);
}
}catch(Exception e){System.out.println(e);}
return this.countries;
}
public void setCountries(ArrayList temp)
{this.countries=temp;}
}
public class SignUpAction extends Action
{
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception
{
SignUpFormBean signUpBean=(SignUpFormBean)form;
signUpBean.setCountries(signUpBean.getCountries());
if(signUpBean.addUser())
return mapping.findForward("success");
else
return mapping.findForward("failure");
}
}
public class CountryBean
{
private int countryID;
private String countryName;
/** Creates a new instance of CountryBean */
public CountryBean()
{
}
public int getCountryID()
{
return this.countryID;
}
public void setCountryID(int tempID)
{
this.countryID=tempID;
}
public String getCountryName()
{
return this.countryName;
}
public void setCountryName(String tempName)
{
this.countryName=tempName;
}
}
Then in JSP page I did it like this way-
<td><bean:message key="signup.country.label"/></td>
<td>
<html:select property="country" tabindex="8">
<html:optionsCollection property="countries" name="countryName" value="countryID"/>
</html:select>
</td>
But I get this error --
org.apache.jasper.JasperException: Exception in JSP: /SignUp.jsp:63
60: <td><bean:message key="signup.country.label"/></td>
61: <td>
62:<html:select property="country" tabindex="8">
63: <html:optionsCollection property="countries" name="countryName" value="countryID"/>
64:</html:select>
65: </td>
66: </tr>
javax.servlet.ServletException: Cannot find bean: "countryName" in any scope
org.apache.jasper.runtime.PageContextImpl.doHandlePageException(PageContextImpl.java:858)
org.apache.jasper.runtime.PageContextImpl.handlePageException(PageContextImpl.java:791)
org.apache.jsp.SignUp_jsp._jspService(SignUp_jsp.java:105)
org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:97)
javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:332)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:314)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:264)
javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
Please help me, this problem is killing me!
Regards.
Jahid
# 4
Ok, to fix your initial problem, you should be using label="countryName" rather than name="countryName"
And then on your JSP
<html:select property="country" tabindex="8">
<html:optionsCollection property="countries" label="countryName" value="countryID"/>
</html:select>
You shouldn't have any code accessing database in your FormBean.
The Formbean is meant to be the data transfer from your webpage to a struts action, or the struts action to a web page. It shouldn't do any lookup itself.
Your CountryBean looks good.
To get proper separation, you need a seperate 'service' class or "DataAccess class"
SignupFormBean:
It has two attributes
1 - list of countries to display on the form
2 - the id of the country selected.
public class SignUpFormBean extends org.apache.struts.action.ActionForm
{
private List countries=new ArrayList();
private int selectedCountry;
public SignUpFormBean()
{
super();
}
public List getCountries()
{
return this.countries;
}
public void setCountries(List temp)
{this.countries=temp;}
public void setSelectedCountry(int sellectedCountry){
this.selectedCountry = selectedCountry;
}
public int getSelectedCountry(){
return this.selectedCountry;
}
}
DAO / Service
This is a helper class that does the database access to retrieve a list of countries.
public class CountryDAO(){
public static List getCountries() throws MyDataAccessException{
{
List countries = new ArrayList();
DBDriver db=new DBDriver();
java.sql.ResultSet rst=db.executeQuery("SELECT id,name FROM countries");
try
{
while(rst.next())
{
CountryBean ctBean=new CountryBean();
ctBean.setCountryID(rst.getInt("id"));
ctBean.setCountryName(rst.getString("name"));
countries.add(ctBean);
}
}catch(Exception e){
System.out.println(e);
throw new DataAccessException("Error loading countries", e);
}
return this.countries;
}
}
}
A custom exception for the DataAccess layer to throw
public class MyDataAccessException extends Exception{
public MyDataAccessException(String message, Throwable cause){
super(message, cause);
}
}
A new struts action:
This action should be firing when you DISPLAY the sign up page.
It loads the list of countries from the database, and puts it into your form.
public class SignUpActionDisplay extends Action
{
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception
{
SignUpFormBean signUpBean=(SignUpFormBean)form;
signUpBean.setCountries(CountryDAO.getCountries());
return mapping.findForward("success");
}
}
And the JSP something like this
<html:select property="selectedCountry" tabindex="8">
<html:optionsCollection property="countries" label="countryName" value="countryID"/>
</html:select>
Hope this helps some.
# 5
Thanks evnafets. evnafets reply should work dbspider.
skp71a at 2007-7-11 15:03:18 >

# 6
Hi,
Thanks a lot for so nice reply with examples. And I appreciate your way of making people understanding with example and instructions, is the best for any developer.
I did exactly the way you said. Like below --
public class SignUpFormBean extends org.apache.struts.action.ActionForm
{
private String city=null;
private List countries=new ArrayList();
public String getCountry()
{return this.country;}
public void setCountry(String temp)
{this.country=temp;}
public List getCountries()
{return this.countries;}
public void setCountries(List temp)
{this.countries=temp;}
}
public class DBDriver
{
private Connection connection=null;
private Statement statement=null;
public DBDriver()
{
if(connection==null)
this.connect();
}
public void connect()
{
try
{
Class.forName("com.mysql.jdbc.Driver");
connection=DriverManager.getConnection("jdbc:mysql://localhost/strutstest?charSet=UTF8","root","jahid");
statement=connection.createStatement();
}catch(Exception e){System.out.println(e);}
}
public List getCountries()
{
if(connection==null)
this.connect();
List countries=new ArrayList();
ResultSet rst=executeQuery("SELECT id,name FROM countries");
try
{
while(rst.next())
{
CountryBean ctBean=new CountryBean();
ctBean.setCountryID(rst.getInt("id"));
ctBean.setCountryName(rst.getString("name"));
countries.add(ctBean);
}
}catch(Exception e){System.out.println(e);}
return countries;
}
}
public class SignUpAction extends Action
{
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception
{
SignUpFormBean signUpBean=(SignUpFormBean)form;
signUpBean.setCountries(new DBDriver().getCountries());
if(signUpBean.addUser())
return mapping.findForward("success");
else
return mapping.findForward("failure");
}
}
<html:select property="country" tabindex="8">
<html:optionsCollection property="countries" label="countryName" value="countryID"/>
</html:select>
Now the problem is, when the page is loading, its not loading with all countries. I thought it's calling the "getCountries()" method of class "SignUpFormBean". And since on that form bean we didn't do initialization of "List", so when the page is loading we are not getting any country. So I tried it like this way --
public class SignUpFormBean extends org.apache.struts.action.ActionForm
{
................
................
public List getCountries()
{
this.countries=new DBDriver().getCountries();
return this.countries;
}
...............
..............
}
And then the page loaded with all countries, and it looked perfect. But you said its not good idea to put DB access on FormBean class. And I want to follow the convention while developing to get full advantage. So where should I initialize the "countries" of SignupFormBean Class? You said to call it from Action class. But, isn't it Action class will be called after we perform any event on the page?
I mean, the page is loading, and then when we are performing any event, then its calling the Action class. So, doing initialization in Action class will not initialize countries when the application, isn't it? And if we shouldn't put DB access in FormBean, then where should we initialize "countries" from DB to that variable?
Hope to get your reply soon.
Regards.
Jahid
# 7
>So where should I initialize the "countries" of SignupFormBean Class?
>You said to call it from Action class.
>But, isn't it Action class will be called after we perform any event on the page?
What we need here is two seperate "actions"
One action to 'load' the page
Another action to 'save' the page.
So the load action would load the list of countries, put it into the formbean, and then forward to the JSP.
The save action retrieves the selected countryId, and does with it what it will. calls addUser() in this case.
Both of the actions use the same actionForm.
You could do it as two seperate Action classes.
You could use a DispatchAction to implement the two features within the same class.
Another alternative, if (as is likely) the list of countries is the same for every user, you should maybe store it in an application level bean/attribute.
That way you only load it once for all users, and thereafter use the one in memory.
The list of countries doesn't really need to be in the form bean - just the selected country.
Cheers,
evnafets
# 8
Hi,
>One action to 'load' the page
>Another action to 'save' the page.
I know how to use action to save a page, but how to call an action when the page is loading? Can you give me a little example? Or an URL to browse?
>"you should maybe store it in an application level bean/attribute"
Did you mean hard coding in JSP page? If so, then i18N will not work. Can you give me a little example about what you meant?
So, kind of you.
Regards.
Jahid
# 9
Someone, please give me a better way to populate select tag while loading the page first time. please, it will be a great help.regards
# 10
Hi bdspider,
I had the same problem, but found a solution for it?I want to create a dropdown called Unit, (means a dropdown that lists all the units of my company) in a form called Call Register?i have to populate this dropdown from database during page load匢 did the following;
In struts-config.xml
<form-beans>
<form-bean name="callRegisterForm" type="org.apache.struts.validator.DynaValidatorForm">
?<form-property name="unit" type="java.lang.String" initial=""/>
?</form-bean>
</form-beans>
Please note that I dint use any list object to hold the data to populate the dropdown?only a String object called unit is used the form-bean.
When the user clicks the Call Register link is clicked in the menu, I wont call the jsp page of Call Register, instead I call an action called FillActions. I use this action to create objects (that are used to populate the unit dropdown) and add to session scope... in this case say i added a objetc called SES_UNIT in session... on successful completion of this Action, I redirect to the Call Register JSP page?in the call register page I use the following code,
<html:select property="unit">
<html:options collection="SES_UNIT?property="value" labelProperty="label"/>
</html:select>
This solution works fine for me?now you might ask me why I should add these objects in session scope?initially I did it with request scope?I am using validator framework in my project?when I submit an incomplete form, the validator returns error (that抯 what it is supposed to do)?but when refreshing the page the objects in the request scope are lost?so I dint get the page completely?also I do one more thing?all the objects that I add to session is prefixed as 揝ES_?so when calling the FillActions, I will first delete all the objects with prefix 揝ES_?and then I will add new objects to session?
This way I have solved the problem?I am not an english so sorry for my poor english?if you had may thing to ask me please feel free to ask?br>
A * R
