This document just describes the basic program
flow for various presentation frameworks.
- Turbine
- Struts
- Lutris Base PO
- Statecharts
And here's how Barracuda does it...
- Barracuda
Turbine
Suppose we have a form which whose action is mapped to a URL that looks something like
this http://<server>/servlet/Turbine/template/AddUser.wm/action/NewUser and whose
form buttons might be named doSubmit, doCancel, etc. When the user presses a button, the
following sequence would occur.
- the /servlet portion of the path will cause the Turbine Servlet to handle the request
- Turbine evaluates whether the user has a session - if not it either redirects them to a
default page, or sends them to the requested page with a default session
- If the user has a session, Turbine makes sure the user has logged in, validates the
session, and gets / builds an ACL list. This information will be stored in the RunData
structure.
- Turbine then evaluates the /action portion of the path, causing it to instantiate and
execute the NewUser implementation of the Action interface
- Turbine then evaluates the button name (i.e. doSubmit) to determine which method to
invoke in the NewUser class.
- If there is no method matching the button name, the doPerform method specified in the
Action interface will be invoked
- The method which gets invoked is passed a copy of RunData (encapsulates HTTP
information, as well as other data)
- This method would typically load info from the underlying data model and store it as
named messages (based on form name, field name) in a FormMessages storage structure
provided by RunData
- Turbine then evaluates the /template portion of the path, and invokes the AddUser.wm
template.
- The (in this case) WebMacro template receives a copy of the RunData structure, and the
WebMacro scripting language can pull values out of the FormMessages structure to populate
specific data items in the page.
- The completed page is then returned to the client browser
Struts
Struts initially loads an ActionServlet which (as described in the javadoc)
has the following responsibilities:
- Identify, from the incoming request URI, the substring that will be
used to select an action procedure.
- Use this substring to map to the Java class name of the corresponding
action class (an implementation of the Action interface).
- If this is the first request for a particular action class,
instantiate an instance of that class and cache it for future use.
- Optionally populate the properties of an ActionForm bean associated
with this mapping.
- Call the perform() method of this action class, passing on a
reference to the mapping that was used (thereby providing access to the underlying
ActionServlet and ServletContext, as well as any specialized properties of the mapping
itself), and the request and response that were passed to the controller by the servlet
container.
For the example application all urls ending with a ".do"
extension are mapped to this Action Servlet. At initialization time, the action servlet
reads in a action.xml file which provides additional routing information that is used
during request processing. The basic application flow runs something like this:
- All GET and POST requests are routed to the protected
void process(HttpServletRequest request, HttpServletResponse response) method of the ActionServlet.
- This method first retrieves the process path of the incoming request.
This is either the "request.getPathInfo()" if available or a substring of the
full "request.getServletPath()" as returned from the servlet request API. This
is determined based on the deployment specifications in the web.xml file. Path Info would
be used if the application routes URLs based on a application prefix. The sub string of
Servlet Path would be used if the application routes URLs based on application extensions.
This is how the example app is configured and a request URL such as
'http://localhost:8080/struts-example/editRegistration.do' would be mapped to a path of
'/editRegistration'.
- The next thing that happens is an ActionMapping
class is found for the request. Based on the path retrieved from the previous step, the
action mapping class is instantiated and passed onto the following stages. This class
encapsulated the routing information obtained from the action.xml file. For example, a
path of '/editRegistration' can be associated with its own ActionMapping class or the
default ActionMappingBase
class (which can be specified in the web.xml file). A line read from the action.xml file
such as <forward name="success" path="registration.jsp"> tell
the action mapping class where to go when a findForward()
call is made on it. An additional line may be specified such as <action
path="/editRegistration"
className="org.apache.struts.example.ApplicationMapping"> to designate a
custom action mapping class for this path.
- The next step to occur is to find a ActionForm
class, if it exists, for the request. This action form attribute is retrieved from the
action mapping class associated with this request and is specified in the action.xml file.
If the action form exists, it is automagically populated with any cgi data submitted with
the request. This is done using the JavaBean method signature patters such that a form
field with the name 'passwd' would be associated with the bean property 'passwd' and can
be accessed by getter and setter methods of 'getPasswd()' and 'setPasswd(String passwd)'.
- The next step that occurs is to validate the action form if required.
The validation criteria is left up to the action from class and the validate method will
only be called if:
- A action form instance was found.
- The action form is a sub class of ValidatingActionForm
- The input form attribute exists, this attribute is also specified in
the action.xml file.
- The cancel action button was not selected.
- otherwise, the process() method of the Action Servlet continues on as
normal.
- If the validation method is invoked, the action form class validates
the submitted form parameters and reports any errors into an instance of the ErrorMessages
class. This class returns all the collected errors at the end of the validation process as
an array of Strings. If there are no errors to report, the process() method of the Action
Servlet continues on as normal. If there are errors to report, the input form attribute is
retrieved from the action mapping class and control is forwarded to this location.
- If validation was successful or it was not required by not meeting
the stated criteria, the Action
instance class associated with this request is called. The action instance class is also
retrieved from the action mapping class associated with this request and is specified in
the action.xml file. The perform()
method is called on the action instance class and any additional work that is required to
complete the request processing before generating a response is performed here. The return
value for the perform() method tell the Action Servlet where to forward control on to.
- The final stage after the perform() method is called on the Action
instance is to forward control onto a servlet that will generate the view. This servlet
will be determined by the return value of the perform() method and is typically a Java
Server Page.
Lutris Base PO
Suppose we have a form which whose action is mapped to a URL that looks something like
this http://<server>/servlet/Welcome and whose form buttons might be named
OneButton, TwoButton, etc. When the user presses a button, the following sequence would
occur.
- client javascript catches the action and adds a hidden parameter like event=one to the
form
- the request is routed to the Welcome servlet which extends BaseServletApplication.
- the servlet (optionally) implements handleDefault and handleError methods along with
additional methods like handleOne that correspond to button names
- The BaseServletApplication starts by initializing the session data..
- gets a HttpSession object, and if it doesn't exist creates it
- gets the PresentationSessionData object, again creating it if it doesn't exist, and
placing it in the HttpSession structure
- Next it performs any preprocessing by invoking the preProcess method. Tasks like
auto-login might be handled here.
- Now it dispatches the "event" to the appropriate handler by invoking the
getPage method (which the developer could override to provide custom dispatching
functionality)...
- the handleOne method would be invoked using reflection (if the method exists)
- if the method does not exist, the handleDefault method is invoked
- all of these methods return an XMLObject structure that represents an XMLC page
- If a page throws a RedirectException the servlet catches and redirects
- If any other error is encountered the handleError method is invoked
- The servlet performs post-processing by invoking either postProcess or errorPostProcess
(if there were errors)
- Finally, the XMLC page is rendered, sending the new view back to the client
Statecharts
When a request is made to the server, the statechart approach would have the following
sequence of events happen. The important thing to note here is that the Statechart engine
is directly configured from the actual statechart diagram representing the application.
This can be accomplished using a UML editing tool that supports XML. The statechart engine
only determines what the appropriate transition should be, the controllers execute that
transition:
- Requests are always made to a controller servlet. Each controller servlet is considered
to be a high level state composed of one or more sub-states. The mapping of URLs in the
static storyboard to the corresponding controller servlets are done through the use of the
web application deployment descriptor.
- Once in the controller servlet, the request is wrapped in a very generic
BarracudaRequest object. This is done to hide the semantics of a GET verses POST verses
multi-part mime requests.
- The controller would then pass the BarracudaRequest object off to a Statechart engine
which would determine:
- Does the user have an active session? If not, initialize a new session and direct the
controller to transition to its start state.
- If there is an active session, determine based on the clients history if the request
made is a valid transition. If not, direct the controller to return to a valid state.
- If the request is a valid transition, determine, based upon transition criteria
specified by the statechart specification, what the appropriate state or sub-state is and
direct the controller there.
- Repeat this last step until a response is generated.
A typical flow through a controller's sub-states might be something like this:
- Check that the user is logged in.
- Check that the user is properly authorized.
- Encapsulate request data into a type safe BarracudaRequest object.
- Commit to persistent storage all request data.
- Generate the appropriate response.
This example assumes no errors occur in each sub-state. If errors are encountered, the
statechart engine would instruct the controller of the proper transition to make and the
normal application flow would be redirected.
Barracuda
The Barracuda presentation flow is detailed here, in the Event
Delivery Flow. |