Controller Components
The Struts framework provides a rich set of features upon which an implementation can be based. The decisions to be taken at this point include:
- The type of Action object to be used for processing each user submission
- If, and how, multiple actions are to be grouped in a single Action class
- The type of ActionForm objects to be used to hold submitted form data
In this application, the actions performed in the content pane of a given page exhibit a high degree of cohesion. Consider, for example, the Compose page. The actions of sending, saving a draft, adding an attachment, etc. are all associated with a message. At this point in the design process the definition of business objects comprising the model have not been addressed, but one perceives that some sort of “message object” can assumed to be in play. Similarly, actions in the Folder page will cohere around some sort of “folder object”.
This cohesion leads to the decision to group related actions into single Action objects associated with each of the Compose, Folder, and Read pages. The Address Book and Address Select pages will share one Action object, since they can be assumed to deal with some manner of object representing an address book entry.
Struts provides two standard Action objects which are useful for mapping a set of user actions to a set of methods in a single Action objects. The org.apache.struts.actions.DispatchAction
maps the values of a configured parameter to names of methods in the object. Similarly, org.apache.struts.actions.LookupDispatchAction
maps the localized values of the labels of form submission buttons to methods, via a reverse mapping from the label value back to the resource value. .
From the UI Type column in Table 1, we see that there will be a mix of these two types of submission. This led me to the conception of a general purpose Action class combining the capabilities of the Struts DispatchAction
and LookupDispatchActon
.
This GeneralDispatchAction serves as the parent class of the
ComposeAction,
FolderAction,
AddressAction and
ReadAction classes.
(All Java classes in this project are rooted in a package "com.micromail". I have omitted the package prefixes here for simplicity. You can view the entire javadoc set here.)
Table 2 records the same page transition mapping information as Table 1, but adds specification of the Action classes, and the methods within each, required to handle each type of submission.
Origin Page |
Action Trigger Label |
Action Class |
Method Name |
Condition |
Destination Page |
(Browser login dialog) |
Submit |
LoginAction |
execute |
new user |
New User |
existing user |
Folder |
||||
New User |
Proceed |
NewUserAction |
registerPersonalName |
Folder |
|
any (menu pane) |
Compose |
ComposeAction |
compose |
Compose |
|
any (menu pane) |
Inbox/Sent/Drafts/Trash |
FolderAction |
selectFolder |
Folder |
|
any (menu pane) |
Address Book |
AddressAction |
goTo |
Address Book |
|
Address Book |
Save Address |
AddressAction |
save |
Address Book |
|
Address Book |
Edit |
AddressAction |
edit |
Address Book |
|
Address Book |
Delete |
AddressAction |
delete |
Address Book |
|
Address Select |
Insert Selected Addresses |
AddressAction |
insert |
Compose |
|
Compose |
Addresses |
ComposeAction |
selectAddresses |
Address Select |
|
Compose |
Save Draft |
ComposeAction |
saveDraft |
Folder |
|
Compose |
Send |
ComposeAction |
send |
Folder |
|
Compose |
Browse |
(browser) |
Compose | ||
Compose |
Add |
ComposeAction |
addAttachment |
Compose |
|
Compose |
Delete Selected Attachments |
ComposeAction |
deleteAttachments |
Compose |
|
Folder |
Sort |
FolderAction |
sort |
Folder |
|
Folder |
Delete |
FolderAction |
delete |
Folder |
|
Folder |
Read |
FolderAction |
read |
Read |
|
Folder |
Select All |
(javascript) |
Read | ||
Read |
Delete |
ReadAction |
delete |
folder not empty |
Read |
folder empty |
Folder |
||||
Read |
Next/Previous |
ReadAction |
next / previous |
Read |
|
Read |
Forward |
ReadAction |
forward |
Compose |
|
Read |
Reply |
ReadAction |
reply |
Compose |
|
Read |
Reply All |
ReadAction |
replyAll |
Compose |
|
Read |
Resume Draft |
ReadAction |
resumeDraft |
Compose |
I chose to use a single DynaActionForm class to be populated with submitted form data. The total number of possible parameters is fairly small