I am revisiting the internals of Struts after quite a while of not working
with it. I'm working on a webapp that is currently still using Struts1.1,
but it may be upgraded. My questions revolve around best practices and
patterns for using the ActionForm to do what I really want. If any of this
is solved in >1.1 versions of Struts, please let me know and I will check
them out before digging too deep!
GOAL:
====
The webapp has many Javabeans representing the domain data structure. These
beans are passed between layers. I would like my ActionForms to simply
contain these beans for painting and populating forms, so there is no messy
transformation stage to convert from ActionForm<-->Beans.
What is the best way to reuse an application's existing data bean structure
for forms?
Consider an ActionForm/bean structure like this:
------------------------------------------------
ActionForm
- ArrayList employees // holds Employee beans
Employee.java
- Integer employeeId
- String employeeName
- ArrayList assignments // holding Assignment beans
Assignment.java
- Integer assignmentId
- String assignmentName
------------------------------------------------
(in reality, imagine a nested structure 5-10 levels deep and very complex)
Now imagine a web form which is adding, changing, and deleting details for a
list of employees.
Having a structure like this would allow me to just grab the bean structure
from my business layer, which was passed the bean structure from the model
layer. My Action could just put the ArrayList of employees into the
ActionForm and go!
This approach leads to a few problems:
1. Using nested properties, I can have form inputs named
"employees[0].assignments[2].assignmentName" and the ActionForm will be
correctly set the inner bean values - as long as the structure exists. I've
seen the LazyBean solution - but is there anything wrong with just making
getters() for the ArrayLists which create the objects as necessary? For
example, in the ActionForm:
public Employee getEmployees(int i) {
if(employees == null) { employees = new ArrayList(); }
while (i>=employees.size()) { employees.add(new Employee()); }
return (Employee)employees.get(i);
}
2. Fields such as Integer, which are objects rather than int specifically so
they can be null, get set to a default value (example: 0) when the form
field is empty. If I understand correctly, I need to register a Converter
with BeanUtils so it behaves more rationally with this?
3. Invalid data trying to be set to an Integer field, for example, cannot be
presented back to the user. It either needs to be a valid number or null. In
my specific case, though, this is fine. If the user enters an invalid value,
they can just see the empty field when the screen re-paints.
4. Conversion errors throw exceptions that I can't catch in my Action, since
population happens before I have control. I can't keep a list of all fields
with conversion problems, for example, in order to flag them on the screen.
One solution I imgagined to address these annoyances is to create a FormBean
for every Bean in the application. The FormBeans would be identical in
structure to the data beans, but contain only String fields. But this would
lead to duplication of the entire domain data structure in two sets of
beans - one for real data, and one for form data. And then after ActionForm
population, the entire nested structure would need to convert itself to the
real bean structure in order for the business layer to process it. And the
real bean structure would need to be converted to the Form Bean structure to
be populated into the ActionForm. Seems like a lot of extra work, especially
considering a very complex and deep data structure in a big application.
What are the recommendations for dealing with ActionForms that contain or
represent complex nested data structures, preferrably using JavaBeans that
already exist within the application?
Thanks!
--
Matt Kruse
http://www.JavascriptToolbox.com
http://www.AjaxToolbox.com
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]