• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Struts Issue - Repopulating a Form Bean

 
Ranch Hand
Posts: 3271
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
A coworker of mine came to me with an issue he's havign with Struts and, unfortunately, the solution we came up with isn't particularly elegant. I was wondering if anyone here might have a better solution. Here's the situation:

1. The user goes to a particular page in a web application. From this page, the user can add new calendar events or edit existing ones. If the user wishes to save those changes, they can press a save button. In such a case, Struts creates a new form bean with the new values and that data can be stored. Everything is great.

2. While looking at the events of one day, the user can click on another day - a request is made to the application to retrieve the events for that day. The exact same form is redrawn with a list of events for another day.

This is where the problem comes in.

Each day is using the exact same form and the same form bean. Therefore, when the user goes from one day to the next, Form A requests Form A again, just with different parameters (a new date).

If a user goes to Day 1 and selects a given event, all of the form fields are populated with information about that event (via JavaScript). Now, if the user clicks on a new date while those fields are populated, we run into our problem.

Struts sees this request and creates a new form bean for it. It then tries to populate that form bean, which it does very well because the reuqest came from the same form. This is what we don't want to happen. When the form is redisplayed to the user, the data from the previous day's event is still in the form fields.

Our best solution is to write a reset method for his form bean, but there are a few issues with that solution.

1. We'll have to invoke it explicitly in the Action class because, I believe, the reset method is invoked by Struts prior to the repopulation of the Form Bean. Therefore, if we counted on Struts to invoke it, we'd be no better off.

2. When we invoke it explicitly, we'd have to check to see if the user pressed "Save" or not. If the user did, we don't want to reset the form bean, if the user did not, we do. This just seems rather clumsy.

3. We are planning on writing a reset method that uses reflection to invoke each setter method our form bean has. This is appealing because, as we add features (additional form components), we don't want to have to update our reset method constantly. On the other hand, I don't particularly like using reflection - it always feels like some sort of hack.

So, anyway, that's what we came up with and, while I think it will work, I'm not particularly pleased with the solution. Anyone have any better ideas that might work?

Thanks,
Corey
 
Sheriff
Posts: 6450
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
If I'm understanding things correctly, it looks like part of the problem might be that you are having one Action do too many things. For example, you said that "we'd have to check to see if the user pressed "Save" or not." "Save" should certainly be a discrete Action that you shouldn't have to explicitly check for. In other words, pressing "Save" should call some kind of a Save Action.

It's easy to run into these kind of problems when you start having "Super Actions" that try to do everything. Any separate Action that a client is able to perform should be it's own Action class, or at least a discrete method in some type of DispatchAction.

So if you go ahead and have discrete actions (or methods within a DispatchAction) for every action a user may take, it should be very clear when you need a form reset, saved, or otherwise populated.

As far as "resetting" a form, another thing you can do if you feel it's appropriate is to instantiate a new ActionForm of the appropriate type and set it to the proper scope using the getAttribute() method from ActionMapping. For example, assuming your ActionForm is in request scope:



Of course, whether or not you feel this is appropriate will be dependant on your application, but it's nice to know this option is there.

A note on reset() from the Struts API:

The default implementation does nothing. In practice, the only properties that need to be reset are those which represent checkboxes on a session-scoped form. Otherwise, properties can be given initial values where the field is declared.



So I guess the question is, do you really need reset(), or do you just need the initial values of your properties for a request-scope form? This could be achieved simply by instantiating a new ActionForm as I demonstrated above.

HTH
[ December 28, 2004: Message edited by: Jason Menard ]
 
Sheriff
Posts: 17644
300
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
As Jason hinted, the reset method is not intended to be used the way you plan to use it. You should instead write some kind of init() or clear() method to clear the values of the form. Call this from the appropriate action dispatching method that Jason suggested and you should be able to control the initialization of your form properties without resorting to all the ugliness you have planned to do in the reset() method.

As for using reflection, I would suggest you use org.apache.commons.beanutils.BeanUtils instead of writing your own "utility" from scratch.

 
Corey McGlone
Ranch Hand
Posts: 3271
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Jason Menard:
If I'm understanding things correctly, it looks like part of the problem might be that you are having one Action do too many things. For example, you said that "we'd have to check to see if the user pressed "Save" or not." "Save" should certainly be a discrete Action that you shouldn't have to explicitly check for. In other words, pressing "Save" should call some kind of a Save Action.



What would be the best way to implement this? Whether they click the Save button or a different date to view, the same form is being submitted. As such, the same "Action" is being executed - whatever is defined within the FORM tag.

Would it be best to have a "controller" Action that determines what action was taken and then forwards control to a more specific Action? Or is there some secret way to make a HTML form route conditionally to one action or another. It seems that such a thing could be done via JavaScript, but the thought of doing so makes me cringe.
 
Junilu Lacar
Sheriff
Posts: 17644
300
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
CM: Whether they click the Save button or a different date to view, the same form is being submitted.

Are they clicking on a button to select a different date or are you submitting the form via JavaScript submit()? You'll have different options, depending on the answer. If you are using submit buttons to "select date", then you take advantage of the fact that only one submit button can be clicked per request and the name/value pair that goes in will be the name of the button and it's text.

That is, if you have

<html:submit property="action">Save</html:submit>
<html:submit property="action">Select Date</html:submit>

You can add an "action" property to your form and query that property to see what the user clicked and dispatch the request to the appropriate method in your Action class. Or you could use a DispatchAction to automate this, per Jason's suggestion.

If, on the other hand, you submit the form via JavaScript, then you can always submit to a different action altogether and forward back to the same JSP. See http://www.javascript-coder.com/html-form/html-form-action.phtml
 
Don't get me started about those stupid light bulbs.
reply
    Bookmark Topic Watch Topic
  • New Topic