Table of Contents
The Open For Business Controller is a group of classes use to manage the presentation of a web application designed around the Open For Business framework. The Controller is designed to work along with the Entity Engine by keeping a constant state with the Entity Delegator, as well as the Services Framework by keeping a state with the Local Service Dispatcher. The goal of the Controller is to provide a clean mechanism of separating presentation logic from the actual display.
This Controller makes use of several J2EE Presentation Tier design patterns. The Context Security Filter is modeled after the Decorating Filter pattern. The CSF runs at the context root and is able to restrict direct access to JSP templates as well as open doors for future services such as debugging, logging and compression. The Control Servlet is modeled after the Front Controller pattern. This Servlet is where the web application's request processing begins. It makes use of helper classes which process security and events, then dispatches to a defined view. The Views are JSP templates which are very similar to those described in the Composite View pattern. These templates use helper files to limit the amount of logic found in the actual display page. These helper files are Java classes which perform the logic for a specific group of views. This process is based on the View Helper pattern.
As stated above, the main purpose of the Controller is to separate logic from display. This is accomplished by:
- Using a Filter to secure JSP template in the web application
- Using a Servlet to manage application flow
- Using Events (commands) and View Helpers for presentation logic
Context Security Filter
The Context Security Filter (CSF) defined in /WEB-INF/web.xml is used to restrict access to the web application files. In the future it may be used for debugging and/or logging requests. This is the starting point for all web requests to the application. By default all paths are rejected and only paths specifically defined are allowed direct access. The CSF is set to allow all requests to the Control Servlet by setting the mount point of the Servlet in the 'allow list'. The allow list is defined as an init-param named allowedPaths.The value is a single string of paths separated by a colon. The example webapps allow '/control:/index.html:/index.jsp:/default.html:/default.jsp:/images' paths. A path may be a directory name (starting from the root directory of the webapp) or a path to a specific file.
Example: '/images' will allow all files in the /images directory to be directly accessed.
Example: '/site-pages/contactus.html' will allow only the contactus.html file found in the /site-pages directory to be directly accessed.
Example: '/site-pages/info/*' will allow only the files in the subdirectory 'info' to be directly accessed.
When a direct request to a protected path is made the filter will do one of two things. One, the filter can redirect the user to a page defined in web.xml. This is defined by setting the init-param redirectPath to properly formatted URL. Two, the filter will throw a server error which can be defined by the init-param errorCode. The error is thrown only if there is no redirect defined. If no errorCode is defined, the filter will throw a 404 server error.
The configuration looks like this:
The Control Servlet is at the heart of all request processing. Valid requests which pass through the Context Security Filter begin processing here. When a request is received, the Control Servlet first sets up an environment for the helper classes. This environment includes (but is not limited to) setting up an initial session object and storing useful information about the initial request and setting a reference to the Entity Delegator, Service Dispatcher, and Security Handler for use by the helper classes. The request is then passed to the Request Handler for processing. The Request Handler processes the request and returns to the
ControlServlet when finished.
When the Control Servlet is first loaded it will create objects used by the web application and store them in the application context (ServletContext). These objects can be found by accessing the property in the context or via a JSP <useBean> tag. These objects include: Entity Delegator, Security object, Service Dispatcher, and the Request Handler.
The Request Handler makes use of a
RequestManager helper class to gather a list of request mappings defined in an XML configuration file. The configuration file lives in
/WEB-INF/controller.xml for the appropriate context. The mapping consists of a request URI and an optional VIEW name. View names are mapped to in the configuration file as well. A request URI can also be associated with an Event. Events are used to process web related logic by either working directly with the Entity Engine through the Entity Delegator or invoking service(s) to handle the logic through the Service Dispatcher.
When a request is received through the Request Handler it is first looked up in the request mappings; if no mapping is found an 'unknown request error' is returned. Upon a successful lookup, the Security Handler is called to verify if the current request requires authentication and the user making the request is properly authenticated. If the current user is not authenticated the Request Handler redirects the request to a proper login form. After successful authentication or if no authentication is required the Request Handler then looks up a defined event for the request. If an event is found, the request is passed to the
EventHandler for processing. After event processing is complete, the default view is looked up for this request, unless the
EventHandler requests a specific view instead. The view is then checked in the view mappings and the value is passed to the defined
ViewHandler for dispatching. If the view type is
none it is expected that the event handles the response itself; if the view type is
url the RequestHandler then redirects to the specified URL and no
ViewHandler is called.
The Request Handler looks up request mappings in an XML file which is setup like this:
<request-map uri="checkLogin" edit="false">
<description>Verify a user is logged in.</description>
<security https="false" auth="false"/>
<event type="java" path="org.ofbiz.commonapp.security.login.LoginEvents" invoke="checkLogin" />
<response name="success" type="view" value="name" />
<response name="error" type="view" value="login" />
In the above mapping, the event return code success will load the view named main. If success was defined with the type request it would then [***] instead of displaying a view, it in turn calls another request. This is known as request chaining.
The view mappings are defined as follows:
<view-map name="login" page="/login.jsp"/>
A view is looked up by name and mapped to a JSP template (page).
|uri||Y||The name of this request. This will be the name used to access the request.|
|edit||N||Reserved for future use.|
request-map element contains 0 or 1
security tag, 0 or 1
event tag and 1 or more
|https||N||Does this request require being called secure (default false.)|
|auth||N||Does this request require the caller to be authenticated (default false.)|
|external-view||N||Does this request allow passing a view through the URL. (default true).|
|direct-request||N||Does this request allow being called directly through a URL, if false can only be used in a chain (default true).|
|type||Y||Mapped to the event handler definitions to determine which EventHander will be used to run the event.|
|path||N||The path to the class or XML file containing this event, leave empty for services.|
|invoke||Y||The name of the method or service to be run.|
|name||Y||The name of the response, will also match the string returned by the event.|
|type||Y||The type of response will follow: none, request, view, url|
|value||N||The name of the method or service to be run.|
ViewHandler is called on
view type responses. Using the above example, the view handler
default will be used, since no
type is defined. This handler will dispatch to a JSP/Servlet. All ViewHandlers will receive the
page values from the
|name||Y||The name of this view mapping, matches the |
|page||N||The page mapped to this view.|
|type||N||The type of view this is, maps to a ViewHandler. An empty type will assume JSP type view.|
|info||N||Extended information passed to the view handler.|
Event Handlers are defined in the XML config file such as:
<handler name="java" type="request" class="org.ofbiz.webapp.event.JavaEventHandler"/>
As in the above request mapping the login event is defined with a type of
java. The event type is mapped to an Event Handler using the handler definitions. Custom Event Handlers can be designed and would be implemented like the above example.
Java events are processed by locating the path of the event (package and classname); then, by using the Reflection API, the Event Handler invokes the method defined. A String object is returned to the Request Handler which is mapped to the response element of the request definition.
View Handlers are defined just like Event Handlers, except the type is
<handler name="region" type="view" class="org.ofbiz.webapp.view.RegionViewHandler"/>
The view handler handles rendering the next page the user will see. The
default view handler supports standard html/jsp pages by dispatching to the page defined in the view definition. Other view handlers like
velocity use special logic to render the page to the user.
Custom view handlers can be created easily by implementing the
ViewHandler interface and setting a definition in the
controller.xml file like the above example.