Struts & Java Tips: Issue #1

The “Issue” thing is a joke. I don’t know what else to call this. I’ve been thoroughly enjoying the last couple weeks I’ve been spending with Struts, I learn something new everyday. One of the things that I happened upon today was a tip from Ted Husted buried deep in his overview of Struts design patterns and strategies page (a great resource btw) which suggests using the LabelValueBean as a core value object class:

When a good number of drop-down controls are being used, standardize on the LabelValueBean object provided in the Struts example. This is an easy way to create both the Label and Value collections the Struts options tag expects.

One of the things that I really like about Struts is the strict separation between presentation, business logic and model. I’ll spend a couple hours writing Action classes, some ActionForms, maybe a utility class or two and then switch over to implementing the JSP using JSTL (and very little time working with the model since I’m using Hibernate, but that’s anothe post). I’m never writing directly to the response with the Action classes, the ActionForms, etc… all of the presentation is done using JSP. The JSP’s become so much more simple. The first couple sites I wrote using servlets & JSP were (and for the most part still are) a complete mishmash of JSP’s with embedded SQL, buggy tags, and scriplets. With Struts, for the most part you don’t have to use scriptlets, you’re left with clean template-like code that the Actions provide data for.

So now I’ve come full circle. The LabelValueBean is an example of the data that the Actions provide to the JSP’s and they become a very useful tool when you’ve got to populate month select boxes, year select boxes, state select boxes, etc., etc. This morning I started out by creating a Month bean (which had only label and value properties), a Year bean (with only label and properties) , and so on… a definite trend. I created a factory class that handled the creation of those beans and returned a collection to the Action instance, which then put the collection into a request attribute for retrieval by the JSP. The code looked something like this:

// code in the factory class
public static Collection getYears() {
 Calendar c = Calendar.getInstance();
 Collection years = new ArrayList();
 int year = c.get(Calendar.YEAR);
 int endyear = year + 10;
 for (int i=year; i<endyear; i++) {
  years.add(new Year(String.valueOf(i), String.valueOf(i)));
 }
 return years;
}

// code in the Action class
Collection years = YearFactory.getYears();
request.setAttribute("years", years);

// code in the JSP
<html:select property="payment_year">
<html:options collection="years" property="value" labelProperty="label" />
</html:select>

There are a couple things in the above code that can be improved. First, like I mentioned before, I should have used the LabelValueBean instead of creating my own Year bean. Because the presentation is completely independent of the business logic, I need only change a single line of code (and an import for you sticklers out there). This:

  years.add(new Year(String.valueOf(i), String.valueOf(i)));

becomes this:

  years.add(new LabelValueBean(String.valueOf(i), String.valueOf(i)));

Next (at this point I should probably mention that I’ve been poring over Effective Java while exercising at night), performance savvy programmers probably winced at the number of unnecessary objects (Item #4) I’ll end up creating with the getYears() method. What I should have done instead was create the years collection and collection elements in a static constructor and store the result as a private static, returning the result when the getYears() method is called. So the above example is refactored to this:

private static Collection years = new ArrayList();
 static {
  Calendar c = Calendar.getInstance();
  int year = c.get(Calendar.YEAR);
  int endyear = year + 10;
  for (int i=year; i<endyear; i++) {
   years.add(new LabelValueBean(String.valueOf(i), String.valueOf(i)));
  }
 }
public static Collection getYears() {
 return years;
}

Finally, a small touch that I learned (and am attempting to use faithfully) from Item #34, “Refer to objects by their interfaces.” In the code examples above I could have declared the return type and the private static to be an ArrayList:

// private static declaration
private static ArrayList years = new ArrayList();
// factory method
public static ArrayList getYears() {

Changing the implementation from an ArrayList to a Vector would have required changes to any of the classes that use this factory, which makes my program less flexible. Instead, using the Collection interface, my program becomes easier to use and to modify:

private static Collection years = new ArrayList();
// could also be this with no changes to the public API
private static Collection years = new Vector();

I’m always interested in your feedback! Thanks for listening.

9 thoughts on “Struts & Java Tips: Issue #1”

  1. I generally create these lists on startup using a
    servlet, and then put them in the servlet
    context. This way you create the list once.

    An action shouldn’t have to know anything about
    picklists unless it is generating a custom list
    based on something in the request. Like a
    type/subtype relationship.

  2. I used to believe the Struts propaganda about separation of the MVC layers. However, its hard for me to think of the separation as ‘strict’ since I am free to put as much crap as I want to in the form’s validate method. What really drove it home was my exposure to http://www.springframework.org. Now, that is what I would call a strict separation. You should check it out. The separation is far better than that suggested by Struts. Furthermore, you don’t have to play games with forward actions to pre-populate a form with data from persistent store.

  3. I’d like to know if you can help me to resolve a problem that i have, your example of collections with struts its easy but how you can mark an item of the combo??? example: Your combo options is about years….but how you especify that if an item of collection is 2000 ..so checked it as default????

    thanks

  4. hi Miguel,

    Generally if you have a drop down select box it’s associated with an , which is then associated with a . The form bean should have a publicly accesible getter() whose name is the same as the name of the element in your form. Upon form load, if you wanted the year to default to 2000, you’d update the form-bean to have a value of 2000 and then the drop down would automatically see that value and show 2000 as the default.

    That help?

    AJ

  5. I have a question with the selectbox. Is it possible to pass on the labelproperty also to the server ? Scenario is something like this: There is a select box in page 1 with property=departmentID and labelproperty=departmentName. After submitting page1, the control goes to a confirmation page – page2(thru’ some action class etc…) where I want to show the departmentName, the user selected in the previous page. I don’t want to search for the department name using the departmentID, instead I want to pass it as a hidden variable from page1. Any thoughts ??

    Thanks
    sathish

  6. hi Sathish,

    You could use some fancy JavaScript to capture the value of the selected item upon form submit and then pass that into a hidden field, whereupon it would be passed to your next page. Other than that, the only other way would be to search for the department name by ID in the action and then put the resulting department into the request scope for page b.

    hope that helps,

    AJ

  7. i am new to J2EE technologies, i am not able to understand the flow of it. it seems to be too hard. any how i am going to write sun certifications. please give me suggestions that how to start, and how to understand the flow of it. and XML integration. suggest books , free online training urls

  8. I have facing problem when i am using

    I want to populate the all values to form bean

    How can i do this ?

    question2

    I have a

    Operator
    Common User
    Admin User

    I want to get all the above values into next JSP pages

    How can get this
    Actually when i try this with

    My output is coming like this

    Operator
    Common
    Admin

    User has get removed
    Why is this happening

    String roles [] = request.getParameter(“rolelist”);

Leave a Reply

Your email address will not be published. Required fields are marked *