Howdy, Struts newbie here. I'm in the process of evaluating Struts for use in a project and one of the criteria I'm checking out is how to deal with non-text data to and from a form. For my test case I coded a fairly simple Money class that represents a currency value (stored internally as an integer value of pennies). This class has a factory method that can construct a Money instance from a parsed text field, and has a toString() method that returns the value formatted as its textual equivalent. So in my AmountForm (extending ActionForm) I have the following instance variable, setter, and getter for a field with the key "amount":
So far, so good. But of course, my actions aren't really interested in the text format of the field, but in the Money instance itself. So I changed the getter to:
Figuring that because Money has a toString() method, that all would be well: my actions could obtain the Money instance, and Struts could obtain the text format for displaying on the pages. Well, that broke things. Strangely enough, the symptom of the above change seems to cause the setter to not be called upon form submission (all seems to go well with he getter itself). I'm not sure why the symptoms of the failure are as such, but my question hoils down to this: What patterns do you use to handle this type of non-textual data in your Struts forms? Do you create 2 getters: the bean-patterned setter to return the text value, AND a getter to get the Money (or other non-text) class instance? As in:
This seems rather messy to me, and since this is probably a common requirement (use of non-text data), I figured someone must have come up with a better pattern. Thanks for any input you all might have! bear
As the ActionForm is part of the view component, I leave all attributes as either Strings, ArrayLists (of ActionForms or Strings), or ActionForms. I make sure to keep it decoupled from my control (including Actions) and models. If there is any data conversion that needs to be done between a form and a model, I handle this in the Action. I usually build a general Action for my application that contains common methods, and extend the other Actions for my application from this one. Let's say I am modelling a purchase request system. I have a model PurchaseRequest that contains 1..N PurchaseItems.
I have a jsp view (using nested tags to properly handle the 1..n PurchaseItemForms) that displays the entire purchase request. I use the following ActionForms.
Since I will be doing this conversion between the forms and my model fairly often in various actions, I want to make an Action that I will extend others off of, containing my conversion methods.
Now that we have a base class we can extend our other actions off of that.
Okay, I know that was kind of lengthy and maybe a bit more detail than you asked for, but I was taking your question more in the broader sense of converting information between forms and the model. This was just an example off the tope of my head, so don't get hung up in the whole correctness of the thing as a way to model a PR system. Hope this helps. [ August 13, 2002: Message edited by: Jason Menard ]
Thanks Jason, that was really useful input. My thinking was that since the form is "holder of the data", that it was the natural place to convert to the types that the Action (or Model) will expect. However, your view that the form is merely a broker for the data on behalf of the page and action also has serious merit. So (to clarify),if you had multiple actions that operate upon the same form, you'd create a base class to handle the data on behalf of the actions that would extend it, in order to avoid having to repeat conversion code in multiple actions. Correct? bear
I, too, code my Struts forms with all Strings for the fields. The reason is that it makes returning to the form when a validation error occur work much nicer as the original data the user entered is captured and re-displayed back. As for field conversion - I wrote my own BeanConverter framework in my last project to convert one bean (an ActionForm) to another (a Value Object) and vice versa. It worked very nicely and is quite extensible. But this time around I'm going to investigate the new conversion utilities in Commons to see if anything comparable exists.
Originally posted by Bear Bibeault: So (to clarify),if you had multiple actions that operate upon the same form, you'd create a base class to handle the data on behalf of the actions that would extend it, in order to avoid having to repeat conversion code in multiple actions. Correct?
That's how I do it. I'm sure there are several dozen other ways to accomplish the same thing, but this way seems as good as any to me.