View / Javabeans


Wither JavaBeans?

Why implement the JavaBeans design pattern in the Actionform? A persistent class in a web setting does not have to be a bean. A ServletContext or a HttpSession is not. Attributes are set and retreived like hashmaps. Although JavaBeans have been one way of getting persistence, I see little reason (yet) why the ActionForm should be modeled as such.

[Ted Husted] I think the keyword here is "yet". Much of the underlying Struts designs are based on trends and patterns that have yet to reach their logical conclusion. 

For example, future Java design tools are sure to fully support JavaBeans. Support for other structures, like hashtables, is likely to be less thorough. Another example is custom tags, which are a good thing now, but will be a truly tremendous thing when the visual HTML editors catch up with the Java 2 spec.

Struts is also designed to work well with J2EE design patterns, which rely on JavaBeans. I construct both my form and model (or value) beans at the same time (using simple search and replace templates), and then extend the value beans to work with native types. Personally, I find it more convenient to be working with beans on both sides, rather than with a hashtable here and a JavaBean there. 

It is also very important to note that the ActionForm beans are just a means to an end. They exist as an adaptor between the HTML forms and the rest of your application. After the data has been captured, it should be handed to another object to handle the business-logic portion of your program. As such, they are usually only persistent for the life of a request, and as you say, should do little beside validating the input and converting the data for use by another object.


Why can't the Struts tags access the properties of my beans?

[Dmitri Plotnikov] Struts uses JavaBeans Introspector to discover properties of beans. Introspector is pretty picky in the way it decides whether something is a property or not. Specifically, it requires that 

  1. Both getter and setter be declared public and non-static 
  2. The return type of the getter be the same as the type of the argument of the setter. 

So, first check if your property breaks one of these rules.


Indexed Properties

Can we access members of an array like <form:select property="array[i]"> in a for loop... It  works if I use constants but not expressions..  property="array[0]" is fine but not array[i] or  array[<%=i>] for the property attribute of  form:select. Any clues???

[Craig McClanahan]  The property accessor syntax in Struts 1.0 supports only constants as array subscripts.

You might consider using some sort of runtime expression instead, to dynamically calculate the property to be retrieved. Assume that "i" is an integer variable, and you are inside a loop:

<form:select property='<%= "array[" + i + "]" %>'/>


Has anyone had luck using radio buttons?

<p>The idea behind a radio button is that you have a String field that has one of a
fixed set of values, and you want to render one radio button for each of them.</p>
<p>Let's assume that your bean property "gender" can have property values "Male" or "Female". You might display them like this:</p>
<pre>
<html:radio property="gender" value="Male">
<bean:message key="gender.male"/>
</html:radio>

<html:radio property="gender" value="Female">
<bean:message key="gender.female"/>
</html:radio>
</pre>
<p>A particular radio button will be selected if the value returned for this property matches the "value" attribute of that button's <html:radio> element.</p>
<p>In the example above, we're also looking up the actual text of the strings displayed on the HTML page in a message resources bundle, so that it is suitably internationalized.</p>
<p>Craig McClanahan</p>


Wrapping a text area

I usually need 'wrap="virtual"' as an attribute for my textareas. It isn't part of the HTML spec, but it's supported in both Netscape and IE, and it's pretty useful. 

[Ted Husted] The Struts Action works through introspection. It doesn't know (or care) whether the value in a form was rendered by a Struts custom tag or not. This means if you use a standard textarea tag in your form, and give it a name that matches a property in your form bean, Struts will use that attribute just as if it had been rendered by a html:textarea tag. After all, this is all the Struts html:textarea tag does.

To seed the textarea from the form bean, you could code something like:

<textarea name="article" rows="15" cols="60" wrap="soft"></textarea> 

And everything else will be automagical again.


Alternating colours with logic:iterate

"I'm using the logic:iterate tag to render a table. Now I need to show alternating colours for odd and even table rows. How do I achieve this effect together with the logic:iterate tag?"

[Greg Reddin]:

String LIGHT_COLOR = "LightColor";
String currentColor = DARK_COLOR;
int i = 0;
%>
<struts:enumerate id="searchRow" 
name="searchForm" property="SearchResults"> 
<%
if ( i % 2 == 0)
{
currentColor = DARK_COLOR;
}
else
{
currentColor = LIGHT_COLOR;
}
i++;
%>
<TR ALIGN="center" class="<%=currentColor %>">

[Scott Sayles] What you could do is create a color alternating bean. I've made one for similar uses. Here's how mine is layed out:

--ColorAlternator--
public String getNext()
public String getCurrent()
public void setColor1(String color1)
public void setColor2(String color2)
public void setColor3(String color3)
public int getNumberOfColors()
public void setNumberOfColors(int numOfColors) // should be either 2 or 3
-------------------

You just implement it so that each call to next sets the current color to the next one and returns it. Actually, this is really just a String alternator but the intent is for color names. I suppose that I could have used some kind of circular list and then enabled
it to handle any number of colors, but my assumption was that you probably never have a use for more than 3 colors. It makes the implementation pretty simple.

Then you can use this bean whenever you want. For example:

----- JSP page -------------

<jsp:useBean id="color" class="ColorAlternator"/>
<jsp:setProperty name="color" property="color1" value="white"/>
<jsp:setProperty name="color" property="color2" value="oldlace"/>

<table>
<logic:iterate ....>
<tr bgcolor='<jsp:getProperty name="color" property="next">'> 
<td>content</td>
</tr>
</logic:iterate>
</table>

[Bob Sullivan] You might want to check out JSPTags.com's Pager tag library. They have about 4 different flavors of displays to allow just sort of a presentation effect. I haven't used it in anything real, so I can't speak to the quality or robustness (but it sure looks pretty :)

[Julia Reynolds ] Here's what I have done:

out.println("<table cellspacing=0 cellpadding=0 width=600>");
int row = 1;
String color = "";
while(rec.next())
{
if((row%2)==0)
{
color = "white";
}
else
color = "DDDDDD";

out.println("<tr bgcolor=" + color + "><td ><a href=" +
rec.getString("URL") + "" + " target=\"_blank\"" + ">" +
rec.getString("Description") + "</a></td><td> Category: "
+ rec.getString("CatName") + "<br></td></tr>");
row++;
}
out.println("</table>");

It's not beautiful, but it works.

[Proetel, Ingo] I'm creating the effect like this:

<% int count=0; %>
<struts:iterate id="row" name="currentReport" property="data" >
<tr BGCOLOR='<%= (count++ % 2==0 ?"#FFFFAA":"#EEEEEE") %>' >
<td> <%= count %> </td>
<struts:iterate id="item" collection="<%= row %>" >
<td nowrap align=MIDDLE > <%=(item).toString() %> </td>
</struts:iterate>
</tr> 
</struts:iterate>

[ Niall Pemberton] I have a RowTag that does this, it generates <tr> elements and you can
specify either oddColor/evenColor attributes to generate bgcolor= attributes or oddStyle/evenStyle parameters to generate class= attributes for CSS.

So the jsp looks like this:

<table>
<logic:iterate id=".." name=".." property="..">
<util:row oddColor="#C0C0C0" evenColor="#FF0000">
<td>.....</td>
<td>.....</td>
</util:row>
</logic:iterate>
</table>

You can either specify both odd and even or just one of them.

It's available on the More About Struts Resources page  if you’re interested.