DialogAction Navigation Rules
When an HTML form is submitted, DialogAction
dispatches an event to a corresponding handler method. Automatic
validation must be turned off in a corresponding form bean. The
handler validates input data explicitly, and performs a model
update if needed. In case of an error, the handler saves errors in
the session and redirects to the same action, effectively reloading
the action. When DialogAction receives a "clean" GET
request, it renders a view.
This is how a lifecycle is defined for a standalone login dialog
in struts-config.xml:
<action path = "/login"
...
<forward name = "DIALOG-RELOAD"
path = "/login.do" redirect = "true"/>
<forward name = "DIALOG-VIEW"
path = "/loginform.jsp"/>
<forward name = "LOGIN-SUCCESS"
path = "/userhome.do" redirect = "true"/>
</action>
This is the same lifecycle for an embedded login control:
<action path = "/login"
<forward name = "DIALOG-RELOAD"
path = "/parentpage.do" redirect = "true"/>
<forward name = "DIALOG-VIEW"
path = "/loginform-embedded.jsp"/>
<forward name = "LOGIN-SUCCESS"
path = "/parentpage.do" redirect = "true"/>
</action>
Instead of reloading itself, an embedded control reloads the
parent page, which automatically reloads all controls. The same
Java code is used for both standalone and embedded components.
Handling Error Messages
Error messages are generated by a method that handles input
events. Messages must be saved between requests, so the handler
method stores messages in the session object. After the component
reloads, the JSP page reads messages from the session.
DialogAction does not explicitly remove messages
from the session after the page has been rendered. Instead,
messages are cleared each time a new input event is processed.
Struts 1.2.6 introduced a new feature in
RequestProcessor, which removes messages from the
session after they have been accessed. In this case, messages will not be
redisplayed when the page is reloaded manually.
Keeping State
For simple dialogs, there is no need to define explicit state.
All that is needed is to store input/output data between requests,
which is facilitated by using session scope for an
ActionForm. For multi-state components, state either
has to be defined explicitly, or has to be calculated based on some
criteria.
DialogAction does not define a companion
ActionForm or specific component states, but some of its
subclasses do. For example, CRUDAction (which
implements create, edit, view, and delete operations for a business
object) requires ActionForm to implement the
ICRUDForm interface. WizardAction, which
builds web wizards, requires ActionForm to implement
the IWizardManager interface.
What About AJAX?
Two-phase request processing appears to be less important with
the increasing acceptance of AJAX. But the idea of rendering a
component whenever it is reloaded is still important, because some
AJAX components do not expect that a parent page can be refreshed
by a user.
Also, building a component for both AJAX and non-AJAX
applications is easier when the non-AJAX application uses two-phase
request processing. Therefore, two-phase request processing seems
to be a valuable technology for web applications.
Conclusion
This article explained how to create simple stateful components
and embedded page controls, using existing JSP technology.
Components can be created fully in JSP, or with aid of your
favorite web framework. I used Struts because I know it well, but
you may try the one of your choice. Even if a framework has a
different component architecture, like Wicket, it is usually
possible to include a JSP fragment in a resulting page. This opens
exciting possibilities of seamless integration of JSP components
with existing and new web frameworks.
Live Demos
The following demos are built with the Struts framework and
the Struts Dialogs library:
The samples are run on a development server, which can go
offline from time to time.
References and Source Code
Michael Jouravlev lives in California and has a degree in computer science from the Moscow Aviation Institute in Moscow