It is important to understand how all those components and containers are created at runtime to get a deeper understanding about the final layout. The following picture shows the most relevant controllers and components. To reduce complexity unimportant elements have been removed.
![]() |
In this diagramm we focus only on layout relevant parts of the
framework and ignore the brasato main servlet and dispatching process.
It is enough to know that at some point the
BaseChiefControllerCreator.createChiefController
method is called for a certain user request to create a new user
window. First, a new BaseChiefController is
created. This is the top of the controller hierarchy. The
BaseChiefController creates an instance of the
Window component and adds the HTML elements
html, head and
body in a
VelocityContainer to that window. Therefore,
the BaseChiefController is mainly responsible
to provide framework related HTML fragments such as the
debug tools, the AJAX back
channel and covers the whole issues of JavaScript
and CSS inclusion.
Then, a SimpleBaseController is created
that has a simple VelocityContainer view to add
the GUI messages, modal
dialog and a GUI stack feature. The
SimpleBaseController wrapps the application
specific base controller that handles the applications basic
behaviour. In most cases this will be the
BaseFullWebappController.
You might wonder how the framework knows which controller it
should use as the application specific base controller: the
BaseChiefController and the
SimpleBaseController are both parts of the
framework, but the BaseFullWebappController can
be replaced with whatever super controller you like. We talked above
about the BaseChiefControllerCreator that
factored all this controllers - for this purpose the
BaseChiefControllerCreator has a Spring injected
ContentCreator that has the ability to create
the base controller for the current web app. In this example the
AutoCreator with the configuration
className=BaseFullWebappController is used to create a
BaseFullWebappController at run time.
![]() |
The BaseFullWebappController deals with
the main navigation and layout of the web app. We think the approach
of a main navigation at the top - we call it
Site - is universal and can be used for almost
every web application out there. The
BaseFullWebappController has a
VelocityContainer as the main view part which
is devided into several sections:
layout wrapper (#b_page and #b_page_margins) for pure layouting purposes
web app header (#b_header): you could place a link or logo
there. The area is controlled by a Spring configured
HeaderController
the Site navigation (#b_nav):
navigation for static sites and dynamic tabs, controlled entirely
by the BaseFullWebappController
a static top navigation element (#b_topnav): for static
links like the logout button, the search field, an imprint. This
is controlled by the Spring configured
TopNavController
the main area (#b_main): The main application area for the
currently active site. The controller that is used in this area
must implement the MainController
interface. In most cases the
Main3ColsController is used which features
a 1, 2 or 3 column view.
the footer (#b_footer): Use it to display some footer
information like logged in users or a link to the project
homepage. This is controlled by a Spring configured
FooterController
Note that the nomenclatura for this elements strictly follows
the YAML web layout framework.
The BaseFullWebappController layout is based on
YAML.
The next level of layout relevant parts are generated by the
controller that is responsible for the #b_main area. As I said,
usually this is the Main3ColsController
delivered by the brasato framework. More about this later. Within the
Main3ColsController the three columns can be
filled with whatever the application needs.
When implementing the MVC approach, another fundamental paradigm is executed: the separation of the dispatching, event handling and rendering.
When a user request enters the brasato framework it gets
automatically dispatched by the
DispatcherAction. The framework computes then
which component is responsible for dealing with the request and calls
the Component.dispatchRequest() method on
this component.
There are two types of requests a component can dispatch:
a component internal action: some user
action that does only modify a view option of the component. E.g.
in the Table component the user could click
the table header which then sorts the table ascending or
descending in this column. This action does not modify the data
model nor does it modify anything in the system at all. It is
entirely GUI related and component internal only.
a component provided action: some
functionality the component offers to the controller that created
the component. E.g. in the Table component,
when one actually clicks on a link in one of the rows this is not
a table internal GUI issue. This is the selection
functionality of the table, one of the main
features the Table component offers.
When component internal actions occure, the component will handle it and the dispatching phase is finished.
But when the user action was a
functionality that the component offers to its
Listeners in the component specification, it is
a whole different story. The Listener is the
Controller who created the
Component and attached itself as
Listener. The listener gets informed whenever
some of those functions are executed by the user, we call them
Event. So, when the user presses this link in
the table row, the Table component will fire an
Event to the Controller
by calling the Controller.event()
method.
Now we entered the event handling phase.
Actually, this is still part of the dispatching phase since it happens
during the execution of the dispatchRequest()
method of the Component, but from a logical
point of view this is not dispatching anymore. Sending events from a
component to a controller, from controllers to parent controllers or
even from controllers to global event buses implement the Observer design
pattern, another fundamental design concept. But I'm not going
into details here, it is enough to know that the components will
signal to its listening controlles that a specific event
happend.
In the Controller.event() method the
Controller catches those events and executes
some business logic. For example, the controller could call the
UserManager and delete the user associated with
the selected row from the database and refresh the data model of the
table component. That's it: the controller catches the event from the
component and manipulates the datamodel. (In other cases, the
controller could fire events to its parent controller to signal that a
certain workflow is now finished, and the parent controller could then
remove the entire view of the current controller and replace it with
another view. But at some point in the hierarchy, a controller will do
some business logic and not fire an event anymore since everything has
been done that needs to be done.)
Now, when the last event is handeld, the dispatching and event handling phase is finished and the framework continues with the rendering phase. At this point all the business logic has been finished, all database transactions have been submitted, all states are set and we could call it a day for this request. Everythig that follows now is just rendering the data and the new state of the application. After this point, no business logic should be executed anymore and no data manipulation be made.
The render phase is easy: the framework takes the current
Window with the whole hierarchy of
Components and
Containers and traverses it with the
Renderer. You can think of the
Renderer as a transformer, it transforms the
internal object structure into a HTML page. The
Renderer has special implementations for each
Component and uses those while traversing the
component tree recursively. For example, the
MenuRenderer will be used to render a
MenuTree, the
TableRenderer is used to display a
Table component. Each of those
Renderer produces a string that represents the
rendered component as an HTML fragment.
The sum of all those component HTML fragments is the page as an HTML document. Thats it. In the end, the brasato framework delivers this page to the users browser.
A very powerfull feature of the brasato framework is the automated AJAX mode. When the AJAX mode is enabled, the dispatching and event phase remain the same, but an importand difference happens during rendering phase.
Instead of applying the rendering to the whole
Component tree starting from the
Window object, the framework checks for each
component in the tree if it actually has a dirty
view. Dirty means, that the view of the
Component changed since the last call. Only
those components that are marked as dirty are rendered (including the
components child components) and sent to the browser via a background
AJAX channel.
In the browser, some JavaScript code detects the corresponding element in the HTML DOM tree and replaces it with the newly rendered component view it got from the server. In fact, this new view is nothing else than a small HTML snipplet.
The effect of the AJAX mode is that the basic layout does not need to be redrawn by the browser, only parts in the DOM tree will change. This results in a more vivid user experience due to lower network traffic and less computer power needed to draw the HTML page in the browser.
From a programmers perspective nothing special has to be done to support this AJAX mode unless a programmer does some custom dispatching or a component wants to implement component-internal AJAX features (e.g. dynamic loading of a menu tree).
Components are rendered programmatically in Java code. The
Component.render() method is executed. To
understand how a component is mapped to HTML one must read the Java
sourcecode for the specific renderer. To modify the rendering, the
class must be patched and recompiled. Component
Renderers are in the same package as the
components in org.olat.core.gui.components.*
.
Generally it is not recommended to modify a renderer just to change the layout. After each update of the OLAT application all changes must be carefully reviewed and the patches reapplied. If you can't style a component with the HTML markup that is generated by a renderer, please let me know so that we can modify it for a future release.
A special case is the VelocityContainer
component. The main feature of this Container
is to position contained child components using HTML markup and to add
other elements like internationalized text fragments. This is
implemented using the Apache
Velocity templating engine. When constructing a
VelocityContainer instance in a
Controller, the path to a velocity template
file is one of the main elements of the constructor. The templates are
normally stored in a special directory _content on the
same level as the controller that constructs the element. During the
render phase, the VelocityContainer will use
this template to create the HTML fragment.
To create a velocity container instance you can use the
BasicController.createVelocityContainer()
helper method. As an argument it takes the name of your HTML template.
E.g. when giving the name "test", the velocity container will search
for a file _content/test.html.
The advantage of this approach is that it is very simple to
write Velocity templates and to position other objects like child
components, translated strings or objects that represent parts of the
data model. A so called VelocityRenderDecorator
offers many helpfull methods in the template like translating, URL
generation, child component rendering and much more. The render
decorator can be accessed using the $r variable in the
templates.
Most elements in a brasato web application are implemented in
velocity containers, almost every controllers view is constructed
using a VelocityContainer. Therefore, most of
the HTML code generated in the render phase is defined in the velocity
templates. In most cases you can forget about how other components are
rendered, most likely you will never need to modify anything there.
But for customizing the brasato web application layout, it might be
necessary to modify some of the velocity templates.
When you write your own velocity templates, make sure you write valid XHTML 1.0 transitional code. Best is to test your page using an XHTML online validator.
See the Velocity User Guide for more information about the possibilities in the velocity engine.