I am about to start with e project that uses Struts 1.2. There is no plan to move to another framework.
I wanted to know what's the convention when handling a date in the form?
Should I create a Date variable and create a setDate(String date)
method where the conversion will occur?
Create a Date variable, a setDate(Date date)
and register a special converter somewhere in the chain? (don't know if it's possible)
Create a String variable, a setDate(String date)
and let the conversion/validation to the validate
method in the ActionForm bean?
Or another approach?
Also, if you have any advice to get up to speed with this framework, I would really appreciate it.
Before I respond to your question, let me start by saying this: People don't understand what ActionForm is or what ActionForm does
The ActionForm represents the data that the user filled in the HTML form. Struts reads in the request parameters and matches them by name with the configured ActionForm for the target Action of the submit. It is data inputted by the user, plain and simple.
Data that comes on the request is always of type java.lang.String. But people might have a form field named "age" which is an int in their Model data. Or maybe instead of "age" they have a "birthDate" which off course is java.util.Date in their Model data. So they think it is a good idea to have the type int and Date placed on the ActionForm and allow Struts to convert the Strings that arrive on request into ints and Dates.
Its a very useful conversion and you as a developer don't have to handle it, Struts does. It's a little bit of framework magic.
But this ain't freaking Harry Potter! Conversion can fail on ints and Dates. Why?
int is a primitive type and as such it must always have a value. Default initialization is with zero. When doing the binding (request parameters to ActionForm object properties) Struts sees an int type on the ActionForm and tries to convert the request String value to int.
If user inserted String "5", the field is set to 5. That's fine!
But what if user inserted "bla"? Will we get an exception thrown in our face? Nope! We get back a value of zero because conversion (silently) failed. Ups!
Dates again are an issue. Why? Because their value arrives on request as String. Their format might be something simple like "12/01/2011" which is completely useless as information. Why? Because Dates represented as Strings must go hand in hand with a Locale in order to be transformed to the correct Date instance it represents.
"12/01/2011" + Locale.US = 01 December 2011
"12/01/2011" + Locale.FRENCH = 12 January 2011
Ups!
Ok, so this was the intro! Now let's go to your question.
- Should I create a Date variable and create a setDate(String date) method where the conversion will occur.
At some point you will have to send the Date back to the view and the Struts html tags will normally have to go for a getDate()
which returns String. The "12/01/2011" you get on user input might be displayed as "Jan. 12, 2011 00:00:00" if the getter returns Date (Struts will do a toString()
on the getter value). So you actually need the Date field with both a setter/getter of type Date and a setter/getter of type String. Use type Date in your Action class and use String for interfacing with the view tags.
Question? How do you get handle on the proper Locale value in your ActionForm?
- Create a Date variable, a setDate(Date date) and register a special converter somewhere in the chain (don't know if it's possible)
It is possible. You can create and register a custom converter that might take String representations of dates and convert them to Date. If you use the ISO 8601 format I think you will be safe.
Question? Can you accommodate this into the existing application without breaking code that transforms String to dates in their own way by using all sorts of formats or Locales?
- Create a String variable, a setDate(String date) and let the conversion/validation to the validate method in the actionForm bean
This won't work. The validate
method is called after the parameter bindings on the ActionForm object. When you reach this point is already to late. Struts did the conversion. If you have a field of type int with value zero there is no way to know if the user actually inserted zero and conversion worked or if the user inserted "bla" and the conversion failed and you got back zero as default initialization value. If zero is a valid value for your application than you are in even bigger trouble.
So what's the convention?
There is no convention. Use the above information and apply common sense given your situation.
Ideally you should have all properties in the ActionForm as Strings so that you loose no information during the binding. But this involves manually converting the properties to the proper type in the Action class, before using them. You have full control (Struts no longer does conversions since source and destination values are of type String) but you also have a lot of boiler plate code to write to do it the proper way which at some point can become annoying.
P.S. Before I end this and go to bed (it's 01:00 AM in my Country :D) I just want to mention one thing that people often don't see. The ActionForm is not part of the model, neither should it interact directly with the model.
If you need the data from the ActionForm to be processed in the model, then map it as a one-to-one relationships with a Model DTO (data transfer object). If you don't, then you create a tight coupling between the Model and the Struts framework because your ActionForm objects are not a POJOs. Your class must extend the ActionForm class from Struts that we've been talking about. People don't do this and send the ActionForm straight to the Model. What is even worse is that they also use the validate
method to perform business validations instead of basic validation such as "is required", "is value withing range" etc.
ActionForms are just a communication path between the Action (controller) and the view. Treat it as such.